From 7fb028bfce29fefaa5c7502e8e61c0926b10456c Mon Sep 17 00:00:00 2001 From: harrymunro Date: Fri, 8 May 2026 10:17:05 -0300 Subject: [PATCH] fix: remove TaskCreate mode-check hook that contradicts admiral exception (#112) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PreToolUse hook on TaskCreate blanket-rejected the call whenever mode was not agent-team. The hook payload provides no field to distinguish the admiral from a captain, so the admiral itself was blocked from creating its own Ctrl+T visibility task list in subagents mode — directly contradicting the documented admiral exception in references/tool-mapping.md and references/standing-orders/wrong-ensign.md. Relax the hook: drop the over-enforcement, keep the admiral exception, and rely on the SKILL.md convention for captain discipline (captain TaskCreate in an isolated subagent context is harmless — its task list never reaches the admiral's Ctrl+T view). - Remove the TaskCreate matcher from hooks/hooks.json - Delete cmd_mode_check, its subparser, dispatch entry, and docstring line from hooks/nelson_hooks.py - Delete TestModeCheck and the cmd_mode_check import from hooks/test_nelson_hooks.py - Update the README enforcement-hooks table to drop the removed row settings.json is left untouched: its Agent|TeamCreate|TaskCreate matcher runs nelson-phase.py validate-tool, not nelson_hooks.py mode-check, and is out of scope. --- README.md | 1 - hooks/hooks.json | 9 --------- hooks/nelson_hooks.py | 31 ------------------------------- hooks/test_nelson_hooks.py | 28 ++-------------------------- 4 files changed, 2 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 64cc13f..b1c11bb 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,6 @@ Nelson is not purely advisory. A set of Claude Code hooks (`hooks/nelson_hooks.p | Event | Hook | What it enforces | |---|---|---| | `PreToolUse` on `Agent` | `preflight` | Station tier gate, file ownership conflicts, mode-tool consistency | -| `PreToolUse` on `TaskCreate` | `mode-check` | Rejects task creation in non-agent-team modes | | `PostToolUse` on `Write`/`Edit` | `brief-validate` | Turnover brief quality gate | | `TaskCompleted` | `task-complete` | Validation evidence and station controls | | `TeammateIdle` | `idle-ship` | Paid-off standing order advisory | diff --git a/hooks/hooks.json b/hooks/hooks.json index 2eb0add..27df8ef 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -9,15 +9,6 @@ "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/hooks/nelson_hooks.py\" preflight" } ] - }, - { - "matcher": "TaskCreate", - "hooks": [ - { - "type": "command", - "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/hooks/nelson_hooks.py\" mode-check" - } - ] } ], "PostToolUse": [ diff --git a/hooks/nelson_hooks.py b/hooks/nelson_hooks.py index 0f72337..8866799 100644 --- a/hooks/nelson_hooks.py +++ b/hooks/nelson_hooks.py @@ -7,7 +7,6 @@ preflight — PreToolUse on Agent: station tier gate, file ownership conflicts, mode-tool consistency - mode-check — PreToolUse on TaskCreate: reject in non-agent-team modes brief-validate — PostToolUse on Write/Edit: turnover brief quality gate task-complete — TaskCompleted: validation evidence and station controls idle-ship — TeammateIdle: paid-off standing order advisory @@ -222,31 +221,6 @@ def cmd_preflight(args: argparse.Namespace) -> None: _allow() -# --------------------------------------------------------------------------- -# Subcommand: mode-check (PreToolUse on TaskCreate) -# --------------------------------------------------------------------------- - - -def cmd_mode_check(args: argparse.Namespace) -> None: - """Reject TaskCreate in non-agent-team execution modes.""" - payload = _read_stdin() - ctx = _load_mission_context(payload) - if ctx is None: - _allow() - - _, battle_plan = ctx - mode = _get_mode(battle_plan) - if mode in ("subagents", "single-session"): - _reject( - f"Standing order violation (wrong-ensign): " - f"TaskCreate is not available in {mode} mode. " - f"Track work in the admiral's conversation context. " - f"See references/tool-mapping.md." - ) - - _allow() - - # --------------------------------------------------------------------------- # Subcommand: brief-validate (PostToolUse on Write/Edit) # --------------------------------------------------------------------------- @@ -669,10 +643,6 @@ def main() -> None: "preflight", help="Pre-flight standing order gate (PreToolUse on Agent)", ) - subparsers.add_parser( - "mode-check", - help="Mode-tool consistency check (PreToolUse on TaskCreate)", - ) subparsers.add_parser( "brief-validate", help="Turnover brief quality gate (PostToolUse on Write/Edit)", @@ -690,7 +660,6 @@ def main() -> None: dispatch = { "preflight": cmd_preflight, - "mode-check": cmd_mode_check, "brief-validate": cmd_brief_validate, "task-complete": cmd_task_complete, "idle-ship": cmd_idle_ship, diff --git a/hooks/test_nelson_hooks.py b/hooks/test_nelson_hooks.py index 8d9a057..9cb6670 100644 --- a/hooks/test_nelson_hooks.py +++ b/hooks/test_nelson_hooks.py @@ -1,8 +1,7 @@ """Tests for nelson_hooks.py — hook enforcement script. -Tests the preflight, mode-check, brief-validate, task-complete, -and idle-ship subcommands using temporary mission directories and -monkeypatched stdin. +Tests the preflight, brief-validate, task-complete, and idle-ship +subcommands using temporary mission directories and monkeypatched stdin. """ from __future__ import annotations @@ -35,7 +34,6 @@ _has_evidence, cmd_brief_validate, cmd_idle_ship, - cmd_mode_check, cmd_preflight, cmd_task_complete, ) @@ -302,28 +300,6 @@ def test_marine_subagent_in_agent_team_allows(self, tmp_path: Path) -> None: assert code == 0 -# --------------------------------------------------------------------------- -# Mode-check -# --------------------------------------------------------------------------- - - -class TestModeCheck: - def test_no_mission_allows(self, tmp_path: Path) -> None: - assert _run(cmd_mode_check, {"tool_name": "TaskCreate", "tool_input": {}}, str(tmp_path)) == 0 - - def test_subagents_mode_rejects(self, tmp_path: Path) -> None: - _make_mission(tmp_path, mode="subagents") - assert _run(cmd_mode_check, {"tool_name": "TaskCreate", "tool_input": {}}, str(tmp_path)) == 2 - - def test_single_session_rejects(self, tmp_path: Path) -> None: - _make_mission(tmp_path, mode="single-session") - assert _run(cmd_mode_check, {"tool_name": "TaskCreate", "tool_input": {}}, str(tmp_path)) == 2 - - def test_agent_team_allows(self, tmp_path: Path) -> None: - _make_mission(tmp_path, mode="agent-team") - assert _run(cmd_mode_check, {"tool_name": "TaskCreate", "tool_input": {}}, str(tmp_path)) == 0 - - # --------------------------------------------------------------------------- # Brief-validate # ---------------------------------------------------------------------------