Releases: Edmonds-Commerce-Limited/claude-code-hooks-daemon
v3.8.2 - Comprehensive Venv Resolver SSOT
Release v3.8.2 - Comprehensive Venv Resolver SSOT
Release Date: 2026-04-22
Type: Patch Release (hot fix for v3.8.0 / v3.8.1)
Summary
Version 3.8.2 completes the v3.7.0 → v3.8.x fingerprint-keyed venv migration. v3.7.0 moved the venv to untracked/venv-py{MM}-{fp}/ and auto-deletes the legacy untracked/venv/ after a successful upgrade. v3.8.0 fixed the skill wrappers. v3.8.1 added the fingerprint-mismatch scan-fallback. But many install, upgrade, QA, and diagnostic scripts still referenced the old path directly, so any script outside the skill surface — the installer's post-install validator, upgrade helpers, worktree tooling, QA runners — would false-fail with "Python venv not found" on any v3.7.0+ install where the agent's python3 differs from the installer's Python.
v3.8.2 introduces two new SSOT helpers — scripts/install/venv_resolver.sh for bash consumers and daemon.paths.resolve_existing_venv_python() for Python consumers — and migrates every remaining hardcoded consumer to use them. All four helpers now implement the identical 4-step precedence:
$HOOKS_DAEMON_VENV_PATH(explicit override)untracked/venv-{current-fingerprint}/bin/python- first matching
untracked/venv-*/bin/python(scan-fallback) untracked/venv/bin/python(legacy fallback)
Highlights
- No more "Python venv not found" false-fails on v3.7.0+ installs: Every script across install, upgrade, QA, and diagnostics now resolves the venv through the shared SSOT. The installer's own post-install validator, which previously reported every correctly-installed v3.7.0+ install as broken, now passes.
- Four SSOTs in lockstep: Python (
daemon.paths.resolve_existing_venv_python), install/upgrade bash (scripts/install/venv_resolver.sh), skill bash (skills/hooks-daemon/scripts/_resolve-venv.sh), and project-level bash (scripts/venv-include.bash) all implement the identical 4-step precedence. Parity is enforced by integration tests that exercise each helper side-by-side. init.shgets the v3.8.1 scan-fallback: The v3.8.1 fix for the skill resolver also applies toinit.sh's_resolve_python_cmd(), which had the same latent bug. Now handled.- Upgrade guide template fixed: The generic
CLAUDE/UPGRADES/upgrade-template/verification.shchecked the legacy path directly, so any future upgrade guide generated from the template would inherit the bug. Template now uses the shared scan-fallback pattern.
Changes
Fixed
- Hardcoded legacy
untracked/venv/bin/pythonpaths across install, upgrade, QA, and diagnostic scripts:scripts/upgrade.sh,scripts/upgrade_version.sh,scripts/install/project_detection.sh,scripts/install/rollback.sh,scripts/install/validation.sh,scripts/validate_worktrees.sh,scripts/setup_worktree.sh,scripts/detect_location.sh,scripts/debug_hooks.sh,scripts/qa/run_all.sh, andscripts/qa/run_strategy_pattern_check.shall now resolve the venv via the sharedscripts/install/venv_resolver.shSSOT helper. client_validator.pyreported "venv missing" on fingerprint-keyed installs: The installer's post-install validator now calls the Python-side SSOTdaemon.paths.resolve_existing_venv_python()instead of checkinguntracked/venv/bin/pythondirectly.init.shmissed scan-fallback between fingerprint-match and legacy:_resolve_python_cmd()now scansuntracked/venv-*/bin/pythonbefore the legacy fallback, matching the v3.8.1 skill-resolver fix.CLAUDE/UPGRADES/upgrade-template/verification.shhardcoded legacy path: The generic verification template now applies the scan-fallback pattern, so every future upgrade guide generated from it handles v3.7.0+ layouts correctly.
Added
scripts/install/venv_resolver.sh: Shared bash SSOT for install/upgrade/verify scripts. Implements the canonical 4-step precedence. Covered by 7 integration tests intests/integration/test_install_venv_resolver.py.daemon.paths.resolve_existing_venv_python(): Python SSOT for in-process consumers. Covered by unit tests intests/unit/daemon/test_paths_resolve_existing_venv.py.
Breaking Changes
None. All changes are internal path-resolution refactors. Consumers that invoked the affected scripts continue to work identically; the fix is purely about where those scripts look for the venv.
Upgrade Instructions
Upgrading Existing Installations
/hooks-daemon upgradeOr, from the daemon directory:
cd .claude/hooks-daemon
./scripts/upgrade.shNew Installations
git clone -b v3.8.2 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.shVerify
/hooks-daemon health
# Expected: "Daemon: RUNNING" — no "Python venv not found" messageTest Statistics
- Total tests: 7,801 passing (4 skipped) — up from 7,778 in v3.8.1 (23 new tests for the two new SSOT helpers and their bash/Python parity)
- Coverage: 95.0% (requirement: 95%)
- QA gates: 10/10 passed
Contributors
- joseph
Comparison
Full diff: v3.8.1...v3.8.2
v3.8.1 - Skill Resolver Fingerprint-Mismatch Fallback
Release v3.8.1 - Skill Resolver Fingerprint-Mismatch Fallback
Release Date: 2026-04-22
Type: Patch Release (hot fix for v3.8.0)
Summary
Version 3.8.1 is a hot fix for v3.8.0. The _resolve-venv.sh helper shipped in v3.8.0 recomputes the fingerprint from ${HOOKS_DAEMON_PYTHON:-python3}, but python3 on the agent's PATH may resolve to a different interpreter than the one the installer used when it built the venv (e.g. installer ran under /usr/bin/python3.13 → fingerprint py313-956ed987, but system python3 is 3.9 → fingerprint py39-3bb0ae3d). The resolver looked for the computed fingerprint, did not find it, and fell through to the legacy untracked/venv/ path — which v3.7.0 auto-deletes after a successful upgrade. Result: /hooks-daemon status, /hooks-daemon health, and /hooks-daemon init-handlers reported Python venv not found: …/untracked/venv/bin/python on v3.7.0+ installs even though the daemon itself was healthy and running.
The fix adds a scan-fallback to the resolver: after fingerprint-match fails, scan $DAEMON_DIR/untracked/venv-*/bin/python and use the first working venv. The venv's own bin/python symlink points to whichever base interpreter the installer chose, so the scanned venv is usable regardless of what python3 resolves to in the agent's current PATH. The same scan-fallback was added to scripts/venv-include.bash::_resolve_venv_dir() which has the identical bug.
Highlights
- Skill wrappers find their venv when installer's Python differs from resolver's
python3:/hooks-daemonskill invocations work again on systems where the installer picked a specific interpreter (e.g.python3.13) and the agent's PATH resolvespython3to a different version (e.g.python3.9). - Project-level
venv-include.bashgets the same fix: Scripts sourcingvenv-include.bash(QA helpers, install scripts) now tolerate the same mismatch.
Changes
Fixed
_resolve-venv.shfingerprint-mismatch fallback: When the fingerprint recomputed at skill-invocation time does not match the venv directory the installer created, the resolver now scans for any existinguntracked/venv-*/bin/pythonand uses the first one found, instead of falling straight to the legacy path. Precedence is now:$HOOKS_DAEMON_VENV_PATH→untracked/venv-{recomputed-fingerprint}/bin/python→ first matchinguntracked/venv-*/bin/python→untracked/venv/bin/python(legacy fallback).scripts/venv-include.bashfingerprint-mismatch fallback: Same scan-fallback added to_resolve_venv_dir()so that root-level helper scripts (QA runners, install scripts) tolerate the same mismatch.
Breaking Changes
None. The scan-fallback is purely additive — it runs only when the existing fingerprint-match and explicit-override paths fail.
Upgrade Instructions
Upgrading Existing Installations
/hooks-daemon upgradeOr, from the daemon directory:
cd .claude/hooks-daemon
./scripts/upgrade.shThe upgrade reinstalls the skill files, so the v3.8.0 resolver is replaced with the fixed v3.8.1 version automatically.
New Installations
git clone -b v3.8.1 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.shVerify
/hooks-daemon health
# Expected: "Daemon: RUNNING" and handler count = 84If /hooks-daemon health still reports Python venv not found after upgrading:
ls .claude/hooks-daemon/untracked/
# Expected: at least one venv-{fingerprint}/ directory presentTest Statistics
- Total tests: 7,778 passing (4 skipped) — 3 new regression tests for the fingerprint-mismatch fallback
- Coverage: 95.0% (requirement: 95%)
- QA gates: 10/10 passed
Contributors
- joseph
Comparison
Full diff: v3.8.0...v3.8.1
v3.8.0 - Skill Wrapper Venv Fix & gh_pr_comments
Release v3.8.0 - Skill Wrapper Venv Fix & gh_pr_comments Handler
Release Date: 2026-04-22
Type: Minor Release (hot fix for v3.7.0)
Summary
Version 3.8.0 is a hot fix for v3.7.0. The fingerprint-keyed venv refactor in v3.7.0 updated the daemon runtime paths but missed the three /hooks-daemon skill wrapper scripts (daemon-cli.sh, health-check.sh, init-handlers.sh), which continued to hardcode the pre-v3.7.0 path $DAEMON_DIR/untracked/venv/bin/python. On fresh v3.7.0 installs the legacy directory does not exist, so every skill invocation failed with Python venv not found: …/untracked/venv/bin/python and the skill was unusable.
This release ships a shared _resolve-venv.sh helper next to the wrappers that applies the same resolution precedence as init.sh's _resolve_python_cmd(), restoring the skill on v3.7.0+ installs without regressing the pre-v3.7.0 layout.
The release also folds in two items that had already landed on main since v3.7.0: a fix for list-venvs/prune-venvs path resolution in normal-install mode, and a new gh_pr_comments handler that mirrors the existing gh_issue_comments handler.
Highlights
- Skill wrappers resolve the correct venv:
/hooks-daemon status,/hooks-daemon health, and/hooks-daemon init-handlerswork again on v3.7.0+ installs. A new shared_resolve-venv.shhelper is the single source of truth for wrapper venv resolution. - Venv cleanup & inspection consistent across install modes:
list-venvs/prune-venvsand the post-install cleanup path now behave identically in normal-install and self-install modes. gh_pr_commentshandler: Blockgh pr view <N>without--comments(priority 40, blocking). Prevents agents from missing review feedback that lives in comments rather than the PR body.
Changes
Fixed
- Hooks-daemon skill wrapper scripts broken on v3.7.0+ installs:
daemon-cli.sh,health-check.sh, andinit-handlers.shhardcoded$DAEMON_DIR/untracked/venv/bin/python. Replaced withsource "$(dirname "$0")/_resolve-venv.sh"— a shared helper that resolves$HOOKS_DAEMON_VENV_PATH→untracked/venv-{fingerprint}/bin/python→untracked/venv/bin/python(legacy fallback)._resolve-venv.shsources$DAEMON_DIR/scripts/install/python_fingerprint.sh(which ships with every install) to compute the fingerprint; if that helper is missing the resolver falls through cleanly to the legacy path. Covered bytests/integration/test_skill_scripts_venv_resolution.py(14 cases). - Venv cleanup and inspection broken in normal-install mode:
list-venvs/prune-venvsand the post-install cleanup path resolved againstself_install_modedefaults and failed silently in normal-install setups. Fixed path resolution so both modes behave identically.
Added
gh_pr_commentshandler (PreToolUse, priority 40, blocking):gh pr view <N>without--commentsis now denied with a guidance message.gh pr view <N> --commentsandgh pr view <N> --json title,body,commentsremain allowed. Mirrors the existinggh_issue_commentshandler. Handler count rises to 84 across 13 event types.
Breaking Changes
None. The wrapper-script fix is fully backwards compatible — pre-v3.7.0 installs (where only untracked/venv/ exists) continue to work via the legacy fallback path in the new resolver.
Upgrade Instructions
Upgrading Existing Installations
/hooks-daemon upgradeOr, from the daemon directory:
cd .claude/hooks-daemon
./scripts/upgrade.shThe upgrade reinstalls the skill files, so the broken v3.7.0 wrappers are replaced with the fixed v3.8.0 versions automatically.
New Installations
git clone -b v3.8.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.shVerify
/hooks-daemon health
# Expected: "Daemon: RUNNING" and handler count = 84If /hooks-daemon health still reports Python venv not found after upgrading, confirm the skill files were re-deployed:
ls .claude/skills/hooks-daemon/scripts/
# Expected: _resolve-venv.sh present alongside daemon-cli.sh/health-check.sh/init-handlers.shTest Statistics
- Total tests: 7,775 passing (4 skipped)
- Coverage: 95.0% (requirement: 95%)
- QA gates: 10/10 passed (magic values, format, lint, type check, tests, security, dependencies, error hiding, skill references, smoke test)
Contributors
- joseph
Comparison
Full diff: v3.7.0...v3.8.0
v3.7.0 - Fingerprint-Keyed Venv Isolation
Release v3.7.0 - Fingerprint-Keyed Venv Isolation
Release Date: 2026-04-21
Type: Minor Release
Summary
Version 3.7.0 eliminates a class of silent venv corruption bugs caused by sharing the daemon's virtual environment across incompatible Python interpreters. The venv is now keyed by a fingerprint of the active Python environment — md5(sys.version | sys.base_prefix | platform.machine())[:8] — so a YOLO container (e.g. Fedora /usr/bin/python3) and the desktop host Python no longer clobber each other's binaries when opening the same project. Concurrent containers sharing the same image still share one venv. The legacy untracked/venv/ path remains a fallback for backwards compatibility and is auto-deleted only after the fingerprint-keyed venv is provisioned and the daemon is confirmed RUNNING.
Two new CLI subcommands (list-venvs, prune-venvs) give operators visibility into and control over the on-disk venv layout, including a --legacy mode to safely remove pre-v3.7.0 venvs after the upgrade.
Highlights
- Fingerprint-keyed venv path:
untracked/venv-py{MM}-{fp}/isolates venvs per Python environment while still sharing across compatible containers. - Auto-bootstrap on first start: First daemon start in a new environment provisions the correct venv automatically via stamp-based invalidation; subsequent starts are zero-overhead.
- Backwards compatible: Legacy
untracked/venv/is retained as a fallback if the fingerprint venv is absent. Auto-deletion happens only after the new venv is healthy and the daemon is confirmed RUNNING. list-venvs/prune-venvsCLI: Inspect the venv layout and safely remove stale/legacy venvs with--dry-run,--force,--legacy,--stale, and--all-except-currentselectors. The active-environment fingerprint venv is never deleted.- CI gate:
HOOKS_DAEMON_SKIP_VENV_BOOTSTRAP=1orCI=truedisables bootstrap to keep CI jobs fast.
Changes
Added
- Fingerprint-keyed venv layout (
untracked/venv-py{MM}-{fp}/): The daemon now keys its virtual environment by a Python-environment fingerprint so concurrent containers sharing the same image reuse one venv while distinct Python environments (different version, prefix, or architecture) get their own isolated venv. Legacyuntracked/venv/is retained as a fallback. - Auto-bootstrap on first startup in a new environment: Stamp-based invalidation detects when the current Python environment has no matching venv.
ensure_venv()provisions a fresh fingerprint-keyed venv automatically on first start; subsequent starts skip the check for zero-overhead operation. - Auto-deletion of legacy
untracked/venv/after successful upgrade: The installer and upgrader delete the pre-fingerprintuntracked/venv/once the fingerprint-keyed venv is provisioned and the daemon is confirmed RUNNING. Deletion is skipped if the daemon fails to start, ensuring safe fallback. list-venvsCLI subcommand: Tabular or JSON listing of all venvs under the daemon's untracked directory, with current-environment marker.prune-venvsCLI subcommand: Modes include--legacy,--all-except-current, and--stale. Requires--forceto delete;--dry-runpreviews. The active-environment venv is never deleted.cmd_repairretargeted to fingerprint-keyed path:repairnow rebuilds atget_venv_path()for the active Python environment.- Fingerprint SSOT helpers (Python + bash):
get_venv_fingerprint()andvenv-include.bashprovide a shared source of truth across Python code, shell scripts, and the installer. init.shlazyPYTHON_CMDresolution:init.shsourcesvenv-include.bashat runtime rather than at clone time.
Changed
- Install and upgrade scripts use fingerprint-keyed paths:
install.sh,upgrade.sh, and QA scripts (run_all.sh,run_tests.sh, etc.) resolvePYTHON_CMDviavenv-include.bash/ensure_venv().
Breaking Changes
None. Legacy untracked/venv/ remains a fallback for backwards compatibility. Auto-deletion of the legacy venv only occurs after the fingerprint-keyed venv is proven healthy.
Upgrade Instructions
New Installations
git clone -b v3.7.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.shUpgrading Existing Installations
cd .claude/hooks-daemon
git fetch --tags
git checkout v3.7.0
./upgrade.shThe upgrade script provisions the fingerprint-keyed venv, restarts the daemon, and — if the daemon starts successfully — removes the legacy untracked/venv/. If the daemon fails to start, the legacy venv is left in place as a fallback.
Post-Upgrade Tasks
After upgrading, review CLAUDE/UPGRADES/v3/v3.6-to-v3.7/post-upgrade-tasks/ — it contains 1 recommended task:
01-prune-legacy-venv.md: Verify that the legacyuntracked/venv/has been removed. If you opened the project in a mixed container/host environment before upgrading, the legacy venv may contain corrupted binaries; runningprune-venvs --legacy --dry-runthen--forceconfirms cleanup.
Testing
- Tests: 7,721+ passing
- Coverage: 95.0%
- Type Safety: MyPy strict mode compliant
- Security: Bandit scan clean
- QA checks: 10/10 passing
Contributors
- joseph
Full Changelog
Compare: v3.6.0...v3.7.0
v3.6.0 - Stash-by-Default and Auto-Commit CLAUDE.md
Release v3.6.0 - Stash-by-Default and Auto-Commit CLAUDE.md
Release Date: 2026-04-20
Type: Minor Release
Summary
Version 3.6.0 ships two improvements to daily development workflow. The git_stash handler now blocks stashing by default (previously advisory) — agents must supply an explicit reason via MUST_STASH_BECAUSE="<reason>" to proceed. The daemon also now auto-commits CLAUDE.md after regenerating handler guidance on restart, eliminating the unexplained dirty file that previously prompted agents to revert or stash it.
Highlights
- Stash blocked by default:
git stashis now denied unless prefixed withMUST_STASH_BECAUSE="<reason>", enforcing deliberate, explained stash operations. MUST_STASH_BECAUSEescape hatch: Agents and developers can still stash when genuinely needed — the block message explains exactly how.- Auto-commit
CLAUDE.mdon restart: The dirtyCLAUDE.mdafter daemon restart is now committed atomically and automatically, removing a persistent source of agent confusion. - Isolated single-file commit: The auto-commit uses
git commit --only, touching nothing outsideCLAUDE.mdand leaving other staged changes untouched.
Changes
Added
git stashblocked by default withMUST_STASH_BECAUSEescape hatch: Thegit_stashhandler default mode has changed fromwarntodeny. Stashing is now blocked unless the command is prefixed withMUST_STASH_BECAUSE="<reason>"(e.g.MUST_STASH_BECAUSE="switching branches for hotfix" git stash). An empty or missing reason does not bypass the block. The deny message explains the escape hatch. To revert to advisory-only behaviour, sethandlers.pre_tool_use.git_stash.options.mode: warnin.claude/hooks-daemon.yaml.- Auto-commit
CLAUDE.mdafter daemon restart injection: When the daemon restarts and regenerates the<hooksdaemon>guidance section inCLAUDE.md, the file is now automatically committed if dirty. This prevents LLMs from seeing an unexplained dirtyCLAUDE.mdand attempting to revert or stash it. The commit usesgit commit --onlyfor atomic single-file commits, touches no other staged files, and skips silently in non-git repos or when git operations fail.
Breaking Changes
None.
Upgrade Instructions
New Installations
git clone -b v3.6.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.shUpgrading Existing Installations
cd .claude/hooks-daemon
git fetch --tags
git checkout v3.6.0
./upgrade.shBehaviour Change: git stash now denied by default
If your project relies on git stash being advisory (warn mode), you must explicitly restore the old behaviour after upgrading:
# .claude/hooks-daemon.yaml
handlers:
pre_tool_use:
git_stash:
options:
mode: warnWithout this override, any git stash command will be blocked. Agents and developers can bypass the block on a case-by-case basis with:
MUST_STASH_BECAUSE="<reason>" git stashTesting
- Tests: 7,666+ passing
- Coverage: 95.0%
- Type Safety: MyPy strict mode compliant
- Security: Bandit scan clean
- QA checks: 10/10 passing
Contributors
- joseph
Full Changelog
Compare: v3.5.0...v3.6.0
v3.5.0 - Implicit Monorepo Support for Dependency Directories
Release v3.5.0 - Implicit Monorepo Support for Dependency Directories
Release Date: 2026-04-16
Type: Minor Release
Summary
Version 3.5.0 teaches the markdown_organization handler to treat vendor/ (PHP Composer) and node_modules/ (npm) as implicit monorepo roots. Each package inside these directories is now a sub-project where normal markdown rules apply — docs/ is allowed, random locations are blocked. Previously, any markdown write inside a dependency directory was unconditionally blocked unless allowed_markdown_paths was manually configured. The deny message now advises about allowed_markdown_paths and monorepo_subproject_patterns config options so users know how to unblock legitimate paths themselves.
Added
- Implicit monorepo support for
vendor/andnode_modules/: Themarkdown_organizationhandler now treats dependency directories as implicit monorepo roots. Normal per-package markdown rules apply within each package subtree — files in recognised locations such asdocs/are allowed, while files in unrecognised locations are blocked. Supports Composer two-level paths (vendor/{vendor}/{package}/), npm unscoped (node_modules/{package}/), and npm scoped (node_modules/@{scope}/{package}/). - Config advice in deny message: When the handler blocks a markdown write, the deny message now includes guidance about
allowed_markdown_paths(for extra allowed paths) andmonorepo_subproject_patterns(for sub-projects with their owndocs/,CLAUDE/, etc.) in.claude/hooks-daemon.yaml. - Updated
get_claude_md()guidance: Documents the dependency directory behaviour so agents understand why markdown in vendor trees is handled differently.
Install / Upgrade
# New installation
git clone -b v3.5.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh
# Upgrade from v3.4.x
cd .claude/hooks-daemon && ./upgrade.shTest Stats
- Tests: 7,656+ passing
- Coverage: 95.1%
- QA checks: 10/10 passing
Breaking Changes
None.
Comparison
Full diff: v3.4.0...v3.5.0
v3.4.0 - Hook-Registration Drift Detection
Release v3.4.0 - Hook-Registration Drift Detection
Release Date: 2026-04-15
Type: Minor Release
Summary
Version 3.4.0 extends the hook_registration_checker SessionStart handler with proactive drift detection for two failure modes that previously went unnoticed: hooks placed in settings.local.json (invisible to teammates and silently doubling up on events), and hook commands that bypass the daemon wrapper entirely by invoking custom scripts or inline Python directly. Both violations are now surfaced at session start with actionable remediation guidance. The cli health subcommand gains the same checks, so operators can validate hook configuration at install and upgrade time without waiting for a new Claude Code session.
Added
- Hook-registration drift detection at SessionStart: The
hook_registration_checkerhandler now detects and flags two additional policy violations beyond duplicate hooks: (1) anyhooksentry present insettings.local.jsonis flagged as a policy violation (previously only duplicates ofsettings.jsonentries were flagged; now any hooks insettings.local.jsonare caught regardless of whether they duplicatesettings.json); (2) any hook command that does not invoke the daemon wrapper (.claude/hooks/{event}) is flagged as a legacy-style bypass, with guidance to port the logic into a project-level handler viainit-project-handlers. cli healthsurfaces hook-registration drift: ThehealthCLI subcommand now includes hook-registration validation in its output, giving operators an install-time and upgrade-time check for misplaced hooks and legacy-style commands without needing to start a new Claude Code session.
Install / Upgrade
# New installation
git clone -b v3.4.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh
# Upgrade from v3.3.x
cd .claude/hooks-daemon && ./upgrade.shTest Stats
- Tests: 7,649+ passing
- Coverage: 95.1%
- QA checks: 10/10 passing
Breaking Changes
None.
Comparison
Full diff: v3.3.1...v3.4.0
v3.3.1 - Restore Shipped-Broken Skill and Agent Frontmatter
Release v3.3.1 - Restore Shipped-Broken Skill and Agent Frontmatter
Release Date: 2026-04-14
Type: Patch Release (Dogfooding Fix)
Summary
v3.3.0 announced a fix for the markdown_table_formatter YAML frontmatter mangling bug — and then shipped a release artefact with 12 files still damaged by that very bug. This patch restores them.
Six SKILL.md files (hooks-daemon, release, acceptance-test, configure, mode, optimise) and six .claude/agents/*.md files had their frontmatter collapsed into a ## name: ... description: ... argument-hint: ... heading by the v3.1.0 batch-format commit (30db070), which ran the pre-fix mdformat across all project markdown. The v3.3.0 handler fix prevents new corruption, but files damaged on disk before the fix landed stayed damaged — and those damaged files were still committed. Every upgrade reached into client projects and re-deployed the broken skill/agent metadata, which is why Claude Code's skill-discovery system-reminders were showing release: --- instead of a real description line.
All 12 files have been restored from git history (30db070^, the parent of the corrupting commit). The v3.3.0 fix to markdown_table_formatter was verified via round-trip on a restored file: frontmatter is preserved byte-for-byte on subsequent Write/Edit operations.
This is exactly the scenario the v3.3.0 post-upgrade task 01-audit-markdown-frontmatter.md walks client projects through — and we should have run it against the daemon's own repo before tagging v3.3.0.
Fixed
- 6
SKILL.mdfiles:src/claude_code_hooks_daemon/skills/hooks-daemon/SKILL.md,.claude/skills/{release,acceptance-test,configure,mode,optimise}/SKILL.md— frontmatter restored; five wholesale-restored from30db070^,release/SKILL.mdhad its frontmatter block surgically rebuilt to preserve the subsequent b38f5a6 UNRELEASED-task-move documentation edits. - 6
.claude/agents/*.mdfiles:transcript-inspector.md,release-agent.md,qa-runner.md,qa-fixer.md,python-developer.md,code-reviewer.md— frontmatter restored from30db070^(none had post-corruption edits).
Install / Upgrade
# New installation
git clone -b v3.3.1 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh
# Upgrade from any v3.x
cd .claude/hooks-daemon && ./upgrade.shUpgrading from v3.3.0 will overwrite the broken skill/agent files with the restored versions.
Test Stats
- Tests: 7,621+ passing
- Coverage: 95%+
- QA checks: 10/10 passing
- No source-code changes — restoration is content-only in
.claude/skills/*/SKILL.md,.claude/agents/*.md, andsrc/claude_code_hooks_daemon/skills/hooks-daemon/SKILL.md
Acceptance Testing
Per RELEASING.md Step 12, PATCH releases with no handler-code changes skip the full acceptance suite. Targeted verification performed:
- Formatter round-trip on
.claude/skills/mode/SKILL.mdviaformat-markdownCLI — frontmatter preserved byte-for-byte; body re-aligned cleanly. - Skill-discovery system-reminder confirmed all 6 restored skills now expose correct
description:values instead of---.
Comparison
Full diff: v3.3.0...v3.3.1
v3.3.0 - Markdown Frontmatter Fix + Post-Upgrade Task Convention
Release v3.3.0 - Markdown Frontmatter Fix + Post-Upgrade Task Convention
Release Date: 2026-04-14
Type: Minor Release
Summary
Version 3.3.0 fixes a silent file-corruption bug in the markdown_table_formatter PostToolUse handler and the format-markdown CLI subcommand, and introduces a generic post-upgrade-tasks/ convention that gives the release pipeline a formal mechanism for shipping post-upgrade instructions (audits, config migrations, workflow changes, notifications) to upgrading LLMs and humans.
The markdown fix is important on its own — any .md file whose first line was --- (notably Claude Code SKILL.md files, but also any Jekyll/Hugo/MkDocs content) was being silently rewritten so the opening --- became a 70-underscore thematic break and the YAML body was collapsed into a ## heading. The bug is now fixed, but files already damaged on disk remain damaged — the shipped post-upgrade task 01-audit-markdown-frontmatter.md walks an upgrading agent through detection and remediation.
Added
post-upgrade-tasks/convention: Tasks are drafted inCLAUDE/UPGRADES/UNRELEASED/post-upgrade-tasks/during the release cycle and moved into the versioned upgrade guide at release time. Each task is a self-contained.mdfile with a mandatory header (Type/Severity/Applies to/Idempotent) and sectionsWhy/How to detect/How to handle/How to confirm/Rollback. Advisory only — nothing runs them automatically.- Release pipeline BLOCKING gate (Step 6):
RELEASING.mdand the/releaseskill now require moving every UNRELEASED task into the versioned upgrade guide before the Opus documentation review. Release ABORTS if any task file remains inUNRELEASED/after Step 6. The Opus review checklist verifies the versioned guide's task index is populated and that release notes reference post-upgrade tasks when any arecriticalorrecommended. - Per-release task index README:
CLAUDE/UPGRADES/upgrade-template/post-upgrade-tasks/README.mdtemplate with the task-index table schema.
Fixed
markdown_table_formatterYAML frontmatter mangling: The handler and theformat-markdownCLI now strip frontmatter before formatting and re-attach it byte-for-byte afterwards. Previously,mdformat(which does not understand frontmatter) rewrote the opening---as a 70-underscore thematic break, collapsed the YAML body onto a##heading, and lost the closing---.
Post-Upgrade Tasks
After upgrading, review CLAUDE/UPGRADES/v3/v3.2-to-v3.3/post-upgrade-tasks/ — it contains 1 recommended task that may require action in your project: 01-audit-markdown-frontmatter.md walks through detecting and restoring any .md files damaged by the frontmatter bug during v3.0.0–v3.2.1. If the project has never been on v3.0.0–v3.2.1, skip this task.
Install / Upgrade
# New installation
git clone -b v3.3.0 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh
# Upgrade from v3.2.x
cd .claude/hooks-daemon && ./upgrade.shTest Stats
- Tests: 7,621+ passing
- Coverage: 95%+
- QA checks: 10/10 passing
Comparison
Full diff: v3.2.1...v3.3.0
v3.2.1 - Allow .github/ Markdown Files
Release v3.2.1 - Allow .github/ Markdown Files
Release Date: 2026-04-10
Type: Patch Release (Configuration)
Summary
Version 3.2.1 activates the allowed_markdown_paths configuration for the markdown_organization handler and adds .github/ as a permitted directory for markdown files. This enables writing markdown files under .github/ (e.g. issue templates, PR templates, triage prompt files) without being blocked by the handler.
Changed
- Markdown organization allowed paths: Activated explicit
allowed_markdown_pathsconfiguration inhooks-daemon.yaml, adding^\.github/.*\.md$alongside all previously built-in default paths
Install / Upgrade
# New installation
git clone -b v3.2.1 https://github.com/Edmonds-Commerce-Limited/claude-code-hooks-daemon.git .claude/hooks-daemon
cd .claude/hooks-daemon && ./install.sh
# Upgrade from v3.2.x
cd .claude/hooks-daemon && ./upgrade.shTest Stats
- Tests: 7,622+ passing
- Coverage: 95%+
- QA checks: 10/10 passing
Comparison
Full diff: v3.2.0...v3.2.1