stravinsky 0.2.40__py3-none-any.whl → 0.3.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. mcp_bridge/__init__.py +1 -1
  2. mcp_bridge/auth/token_refresh.py +130 -0
  3. mcp_bridge/cli/__init__.py +6 -0
  4. mcp_bridge/cli/install_hooks.py +1265 -0
  5. mcp_bridge/cli/session_report.py +585 -0
  6. mcp_bridge/hooks/HOOKS_SETTINGS.json +175 -0
  7. mcp_bridge/hooks/README.md +215 -0
  8. mcp_bridge/hooks/__init__.py +119 -43
  9. mcp_bridge/hooks/edit_recovery.py +42 -37
  10. mcp_bridge/hooks/git_noninteractive.py +89 -0
  11. mcp_bridge/hooks/keyword_detector.py +30 -0
  12. mcp_bridge/hooks/manager.py +50 -0
  13. mcp_bridge/hooks/notification_hook.py +103 -0
  14. mcp_bridge/hooks/parallel_enforcer.py +127 -0
  15. mcp_bridge/hooks/parallel_execution.py +111 -0
  16. mcp_bridge/hooks/pre_compact.py +123 -0
  17. mcp_bridge/hooks/preemptive_compaction.py +81 -7
  18. mcp_bridge/hooks/rules_injector.py +507 -0
  19. mcp_bridge/hooks/session_idle.py +116 -0
  20. mcp_bridge/hooks/session_notifier.py +125 -0
  21. mcp_bridge/{native_hooks → hooks}/stravinsky_mode.py +51 -16
  22. mcp_bridge/hooks/subagent_stop.py +98 -0
  23. mcp_bridge/hooks/task_validator.py +73 -0
  24. mcp_bridge/hooks/tmux_manager.py +141 -0
  25. mcp_bridge/hooks/todo_continuation.py +90 -0
  26. mcp_bridge/hooks/todo_delegation.py +88 -0
  27. mcp_bridge/hooks/tool_messaging.py +164 -0
  28. mcp_bridge/hooks/truncator.py +21 -17
  29. mcp_bridge/notifications.py +151 -0
  30. mcp_bridge/prompts/__init__.py +3 -1
  31. mcp_bridge/prompts/dewey.py +30 -20
  32. mcp_bridge/prompts/explore.py +46 -8
  33. mcp_bridge/prompts/multimodal.py +24 -3
  34. mcp_bridge/prompts/planner.py +222 -0
  35. mcp_bridge/prompts/stravinsky.py +107 -28
  36. mcp_bridge/server.py +170 -10
  37. mcp_bridge/server_tools.py +554 -32
  38. mcp_bridge/tools/agent_manager.py +316 -106
  39. mcp_bridge/tools/background_tasks.py +2 -1
  40. mcp_bridge/tools/code_search.py +97 -11
  41. mcp_bridge/tools/lsp/__init__.py +7 -0
  42. mcp_bridge/tools/lsp/manager.py +448 -0
  43. mcp_bridge/tools/lsp/tools.py +637 -150
  44. mcp_bridge/tools/model_invoke.py +270 -47
  45. mcp_bridge/tools/semantic_search.py +2492 -0
  46. mcp_bridge/tools/templates.py +32 -18
  47. stravinsky-0.3.4.dist-info/METADATA +420 -0
  48. stravinsky-0.3.4.dist-info/RECORD +79 -0
  49. stravinsky-0.3.4.dist-info/entry_points.txt +5 -0
  50. mcp_bridge/native_hooks/edit_recovery.py +0 -46
  51. mcp_bridge/native_hooks/truncator.py +0 -23
  52. stravinsky-0.2.40.dist-info/METADATA +0 -204
  53. stravinsky-0.2.40.dist-info/RECORD +0 -57
  54. stravinsky-0.2.40.dist-info/entry_points.txt +0 -3
  55. /mcp_bridge/{native_hooks → hooks}/context.py +0 -0
  56. {stravinsky-0.2.40.dist-info → stravinsky-0.3.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,175 @@
1
+ {
2
+ "description": "Stravinsky MCP Hooks Configuration - Copy this to .claude/settings.json",
3
+ "installation_note": "These hooks are bundled with the stravinsky PyPI package. Hook paths should point to the installed package location or .claude/hooks/ if copied locally.",
4
+
5
+ "hooks": {
6
+ "Notification": [
7
+ {
8
+ "matcher": "*",
9
+ "hooks": [
10
+ {
11
+ "type": "command",
12
+ "command": "python3 ~/.claude/hooks/notification_hook.py",
13
+ "description": "Agent spawn notification messages"
14
+ }
15
+ ]
16
+ }
17
+ ],
18
+ "SubagentStop": [
19
+ {
20
+ "matcher": "*",
21
+ "hooks": [
22
+ {
23
+ "type": "command",
24
+ "command": "python3 ~/.claude/hooks/subagent_stop.py",
25
+ "description": "Agent completion handling and validation"
26
+ }
27
+ ]
28
+ }
29
+ ],
30
+ "PreCompact": [
31
+ {
32
+ "matcher": "*",
33
+ "hooks": [
34
+ {
35
+ "type": "command",
36
+ "command": "python3 ~/.claude/hooks/pre_compact.py",
37
+ "description": "Context preservation before compaction"
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ "PreToolUse": [
43
+ {
44
+ "matcher": "Read,Search,Grep,Bash,Edit,MultiEdit",
45
+ "hooks": [
46
+ {
47
+ "type": "command",
48
+ "command": "python3 ~/.claude/hooks/stravinsky_mode.py",
49
+ "description": "Hard blocking of direct tools in stravinsky mode"
50
+ }
51
+ ]
52
+ }
53
+ ],
54
+ "UserPromptSubmit": [
55
+ {
56
+ "matcher": "*",
57
+ "hooks": [
58
+ {
59
+ "type": "command",
60
+ "command": "python3 ~/.claude/hooks/parallel_execution.py",
61
+ "description": "Pre-emptive parallel execution enforcement"
62
+ },
63
+ {
64
+ "type": "command",
65
+ "command": "python3 ~/.claude/hooks/context.py",
66
+ "description": "Auto-inject project context (CLAUDE.md, README.md)"
67
+ },
68
+ {
69
+ "type": "command",
70
+ "command": "python3 ~/.claude/hooks/todo_continuation.py",
71
+ "description": "Remind about incomplete todos"
72
+ }
73
+ ]
74
+ }
75
+ ],
76
+ "PostToolUse": [
77
+ {
78
+ "matcher": "*",
79
+ "hooks": [
80
+ {
81
+ "type": "command",
82
+ "command": "python3 ~/.claude/hooks/truncator.py",
83
+ "description": "Truncate long tool responses"
84
+ }
85
+ ]
86
+ },
87
+ {
88
+ "matcher": "mcp__stravinsky__*,mcp__grep-app__*,Task",
89
+ "hooks": [
90
+ {
91
+ "type": "command",
92
+ "command": "python3 ~/.claude/hooks/tool_messaging.py",
93
+ "description": "User-friendly MCP tool messaging"
94
+ }
95
+ ]
96
+ },
97
+ {
98
+ "matcher": "Edit,MultiEdit",
99
+ "hooks": [
100
+ {
101
+ "type": "command",
102
+ "command": "python3 ~/.claude/hooks/edit_recovery.py",
103
+ "description": "Recovery guidance for failed Edit operations"
104
+ }
105
+ ]
106
+ },
107
+ {
108
+ "matcher": "TodoWrite",
109
+ "hooks": [
110
+ {
111
+ "type": "command",
112
+ "command": "python3 ~/.claude/hooks/todo_delegation.py",
113
+ "description": "Parallel execution enforcer after TodoWrite"
114
+ }
115
+ ]
116
+ }
117
+ ]
118
+ },
119
+
120
+ "usage_instructions": {
121
+ "installation": [
122
+ "1. Copy this file to .claude/settings.json in your project root",
123
+ "2. Ensure hook scripts are available at .claude/hooks/ (copy from package or use symlink)",
124
+ "3. Restart Claude Code or run /reload"
125
+ ],
126
+ "hook_paths": {
127
+ "local_copy": "Copy hooks to .claude/hooks/ and use relative paths (as shown above)",
128
+ "package_install": "Use absolute paths to installed package: python -c 'import mcp_bridge; print(mcp_bridge.__path__[0])'/hooks/",
129
+ "development": "For development, symlink: ln -s /path/to/stravinsky/mcp_bridge/hooks .claude/hooks"
130
+ },
131
+ "customization": [
132
+ "Disable individual hooks by removing them from the hooks array",
133
+ "Adjust matchers to change which tools trigger hooks",
134
+ "Add custom hooks by creating new Python scripts"
135
+ ]
136
+ },
137
+
138
+ "hook_overview": {
139
+ "execution_control": {
140
+ "parallel_execution.py": "Detects implementation tasks and injects parallel execution instructions before response generation. Activates stravinsky mode on /stravinsky invocation.",
141
+ "stravinsky_mode.py": "Blocks native file tools (Read, Grep, Bash, Edit) when stravinsky mode is active, forcing Task delegation.",
142
+ "todo_delegation.py": "Hard blocks response completion after TodoWrite if 2+ pending items exist without spawning Task agents."
143
+ },
144
+ "context_management": {
145
+ "context.py": "Auto-injects CLAUDE.md, README.md, or AGENTS.md content into prompts for project-specific context.",
146
+ "todo_continuation.py": "Reminds about incomplete in_progress or pending todos before starting new work.",
147
+ "pre_compact.py": "Preserves critical context patterns (ARCHITECTURE, DESIGN DECISION, etc.) before compaction."
148
+ },
149
+ "tool_enhancement": {
150
+ "tool_messaging.py": "Outputs user-friendly messages about which agent/tool was used (e.g., 'delphi:gpt-5.2-medium(\"Analyzing architecture\")').",
151
+ "edit_recovery.py": "Detects Edit tool failures and suggests recovery actions (re-read file, verify exact match).",
152
+ "truncator.py": "Truncates tool responses longer than 30k characters to prevent token overflow."
153
+ },
154
+ "agent_lifecycle": {
155
+ "notification_hook.py": "Outputs spawn messages for agent delegation (e.g., 'spawned explore:gemini-3-flash(\"Find auth code\")').",
156
+ "subagent_stop.py": "Handles subagent completion, validates output, and can block if critical agents fail."
157
+ }
158
+ },
159
+
160
+ "exit_code_reference": {
161
+ "0": "Success - Allow continuation",
162
+ "1": "Warning - Show message but continue",
163
+ "2": "Block - Hard failure (prevents tool execution in PreToolUse, or signals error in PostToolUse)"
164
+ },
165
+
166
+ "state_files": {
167
+ "~/.stravinsky_mode": "Marker file indicating stravinsky orchestrator mode is active (enables hard blocking)",
168
+ "~/.claude/state/compaction.jsonl": "Audit log of context compaction events with preserved items",
169
+ ".claude/todo_state.json": "Cached todo state for continuation enforcement"
170
+ },
171
+
172
+ "version": "0.2.63",
173
+ "package": "stravinsky",
174
+ "documentation": "https://github.com/GratefulDave/stravinsky"
175
+ }
@@ -0,0 +1,215 @@
1
+ # Stravinsky Hooks for Claude Code
2
+
3
+ This directory contains 11 production-ready hooks that integrate with Claude Code to enforce parallel execution, stravinsky mode, and advanced workflow patterns.
4
+
5
+ ## Quick Start
6
+
7
+ ### Option 1: Copy to Local Project
8
+
9
+ ```bash
10
+ # In your Claude Code project root
11
+ mkdir -p .claude/hooks
12
+ cp -r $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks/*.py .claude/hooks/
13
+ cp $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks/HOOKS_SETTINGS.json .claude/settings.json
14
+ ```
15
+
16
+ ### Option 2: Symlink (Development)
17
+
18
+ ```bash
19
+ # In your Claude Code project root
20
+ mkdir -p .claude
21
+ ln -s $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks .claude/hooks
22
+ cp .claude/hooks/HOOKS_SETTINGS.json .claude/settings.json
23
+ ```
24
+
25
+ ## Hook Files (11 Total)
26
+
27
+ ### Core Execution (3)
28
+ 1. **parallel_execution.py** - UserPromptSubmit hook
29
+ - Detects implementation tasks and injects parallel execution instructions
30
+ - Activates stravinsky mode when `/stravinsky` is invoked
31
+ - Creates `~/.stravinsky_mode` marker file for hard blocking
32
+
33
+ 2. **stravinsky_mode.py** - PreToolUse hook
34
+ - Blocks Read, Grep, Bash, Edit, MultiEdit when stravinsky mode is active
35
+ - Forces delegation via Task tool instead
36
+ - Exit code 2 = hard block
37
+
38
+ 3. **todo_delegation.py** - PostToolUse hook (after TodoWrite)
39
+ - Enforces parallel Task spawning when 2+ pending todos exist
40
+ - Blocks continuation without Task delegation in stravinsky mode
41
+ - Exit code 2 = hard block if stravinsky mode active
42
+
43
+ ### Context Management (3)
44
+ 4. **context.py** - UserPromptSubmit hook
45
+ - Auto-injects CLAUDE.md, README.md, or AGENTS.md content
46
+ - Prepends project context to every prompt
47
+ - Reduces need for explicit context requests
48
+
49
+ 5. **todo_continuation.py** - UserPromptSubmit hook
50
+ - Reminds about in_progress and pending todos
51
+ - Prevents starting new work when existing todos are incomplete
52
+ - Uses `.claude/todo_state.json` cache
53
+
54
+ 6. **pre_compact.py** - PreCompact hook
55
+ - Preserves critical context before compaction (ARCHITECTURE, DESIGN DECISION, etc.)
56
+ - Logs compaction events to `~/.claude/state/compaction.jsonl`
57
+ - Maintains stravinsky mode state across compactions
58
+
59
+ ### Tool Enhancement (3)
60
+ 7. **tool_messaging.py** - PostToolUse hook
61
+ - User-friendly messages for MCP tools and Task delegations
62
+ - Format: `🎯 delphi:gpt-5.2-medium('Strategic analysis')`
63
+ - Works with mcp__stravinsky__* and mcp__grep-app__* tools
64
+
65
+ 8. **edit_recovery.py** - PostToolUse hook (after Edit/MultiEdit)
66
+ - Detects Edit failures (oldString not found, multiple matches, etc.)
67
+ - Suggests recovery: re-read file, verify exact match
68
+ - Appends recovery guidance to error messages
69
+
70
+ 9. **truncator.py** - PostToolUse hook (all tools)
71
+ - Truncates responses longer than 30k characters
72
+ - Prevents token overflow and context bloat
73
+ - Adds truncation markers for transparency
74
+
75
+ ### Agent Lifecycle (2)
76
+ 10. **notification_hook.py** - Notification hook
77
+ - Outputs spawn messages for agent delegations
78
+ - Format: `spawned explore:gemini-3-flash('Find auth code')`
79
+ - Maps agents to their display models
80
+
81
+ 11. **subagent_stop.py** - SubagentStop hook
82
+ - Handles subagent completion events
83
+ - Validates output and detects failures
84
+ - Can block completion for critical agents (delphi, code-reviewer, debugger)
85
+
86
+ ## Configuration
87
+
88
+ The `HOOKS_SETTINGS.json` file contains the complete hook configuration for `.claude/settings.json`. It includes:
89
+
90
+ - Hook type mappings (UserPromptSubmit, PreToolUse, PostToolUse, etc.)
91
+ - Tool matchers (which tools trigger which hooks)
92
+ - Command paths (python3 .claude/hooks/hookname.py)
93
+ - Descriptions for each hook
94
+
95
+ ## Hook Types & Exit Codes
96
+
97
+ ### Hook Types
98
+ - **UserPromptSubmit**: Before response generation (can modify prompt)
99
+ - **PreToolUse**: Before tool execution (can block with exit 2)
100
+ - **PostToolUse**: After tool execution (can modify response)
101
+ - **Notification**: On notification events
102
+ - **SubagentStop**: When subagent completes
103
+ - **PreCompact**: Before context compaction
104
+
105
+ ### Exit Codes
106
+ - `0` - Success (allow continuation)
107
+ - `1` - Warning (show message but continue)
108
+ - `2` - Block/Error (prevents tool in PreToolUse, signals failure in PostToolUse)
109
+
110
+ ## State Files
111
+
112
+ Hooks use these state files:
113
+
114
+ | File | Purpose |
115
+ |------|---------|
116
+ | `~/.stravinsky_mode` | Marker for stravinsky orchestrator mode (enables hard blocking) |
117
+ | `~/.claude/state/compaction.jsonl` | Audit log of context compaction events |
118
+ | `.claude/todo_state.json` | Cached todo state for continuation enforcement |
119
+
120
+ ## Testing Hooks
121
+
122
+ Test individual hooks with JSON input:
123
+
124
+ ```bash
125
+ # Test parallel_execution
126
+ echo '{"prompt": "implement feature X"}' | python3 parallel_execution.py
127
+
128
+ # Test stravinsky_mode (should block)
129
+ touch ~/.stravinsky_mode
130
+ echo '{"toolName": "Read", "params": {}}' | python3 stravinsky_mode.py
131
+ echo $? # Should be 2
132
+
133
+ # Test todo_delegation
134
+ echo '{"tool_name": "TodoWrite", "tool_input": {"todos": [{"status": "pending"}, {"status": "pending"}]}}' | python3 todo_delegation.py
135
+ ```
136
+
137
+ ## Customization
138
+
139
+ To disable a hook:
140
+ 1. Open `.claude/settings.json`
141
+ 2. Find the hook in the hooks array
142
+ 3. Remove or comment out the hook object
143
+
144
+ To modify a hook:
145
+ 1. Copy the hook file to your project's `.claude/hooks/`
146
+ 2. Edit as needed
147
+ 3. Update the command path in `.claude/settings.json`
148
+
149
+ ## Environment Variables
150
+
151
+ Hooks receive these from Claude Code:
152
+ - `CLAUDE_CWD` - Current working directory
153
+ - `CLAUDE_TOOL_NAME` - Tool being invoked
154
+ - `CLAUDE_SESSION_ID` - Active session ID
155
+
156
+ ## Workflow
157
+
158
+ ### Stravinsky Mode Flow
159
+ 1. User invokes `/stravinsky`
160
+ 2. `parallel_execution.py` detects it and creates `~/.stravinsky_mode`
161
+ 3. `stravinsky_mode.py` now blocks Read/Grep/Bash/Edit tools
162
+ 4. Claude must use Task tool for delegation
163
+ 5. `todo_delegation.py` enforces parallel Task spawning for 2+ pending todos
164
+
165
+ ### Normal Flow (No Stravinsky Mode)
166
+ 1. User submits prompt
167
+ 2. `context.py` injects CLAUDE.md content
168
+ 3. `todo_continuation.py` reminds about incomplete todos
169
+ 4. `parallel_execution.py` adds parallel execution guidance if implementation task
170
+ 5. Claude generates response
171
+ 6. `tool_messaging.py` outputs friendly tool messages
172
+ 7. `truncator.py` truncates long responses
173
+
174
+ ## Troubleshooting
175
+
176
+ ### Hooks Not Firing
177
+ - Check `.claude/settings.json` exists with hook configuration
178
+ - Verify hook scripts are executable: `chmod +x .claude/hooks/*.py`
179
+ - Check hook paths are correct (relative to project root)
180
+ - Restart Claude Code: `/reload`
181
+
182
+ ### Stravinsky Mode Stuck Active
183
+ - Remove marker file: `rm ~/.stravinsky_mode`
184
+ - Check for orphaned mode files: `ls -la ~/ | grep stravinsky`
185
+
186
+ ### Hooks Causing Errors
187
+ - Test hooks individually (see Testing section above)
188
+ - Check Python version: `python3 --version` (requires 3.8+)
189
+ - Review hook stderr output in Claude Code logs
190
+ - Disable problematic hooks temporarily
191
+
192
+ ## Integration with Stravinsky MCP
193
+
194
+ These hooks are designed to work seamlessly with the Stravinsky MCP server:
195
+
196
+ - `tool_messaging.py` recognizes `mcp__stravinsky__*` tools
197
+ - `parallel_execution.py` works with `agent_spawn` MCP tool
198
+ - `stravinsky_mode.py` forces use of MCP Task delegation
199
+ - All hooks respect the parallel execution philosophy
200
+
201
+ ## Version
202
+
203
+ Version: 0.2.61
204
+ Package: stravinsky
205
+ Repository: https://github.com/GratefulDave/stravinsky
206
+
207
+ ## License
208
+
209
+ MIT License - See package LICENSE file
210
+
211
+ ## Support
212
+
213
+ For issues or questions:
214
+ - GitHub Issues: https://github.com/GratefulDave/stravinsky/issues
215
+ - Documentation: See CLAUDE.md in package root
@@ -1,49 +1,125 @@
1
1
  """
2
- Hooks initialization.
3
- Registers all Tier 1-4 hooks into the HookManager.
2
+ Stravinsky Hooks - Claude Code Integration
3
+
4
+ This package contains all hook files for deep integration with Claude Code.
5
+ Hooks are Python scripts that intercept Claude Code events to enforce
6
+ parallel execution, stravinsky mode, and other workflow patterns.
7
+
8
+ ## Available Hooks
9
+
10
+ ### Core Execution Hooks
11
+ - `parallel_execution.py` - UserPromptSubmit: Pre-emptive parallel execution enforcement
12
+ - `stravinsky_mode.py` - PreToolUse: Hard blocking of direct tools (Read, Grep, Bash)
13
+ - `todo_delegation.py` - PostToolUse: Parallel execution enforcer after TodoWrite
14
+
15
+ ### Context & State Hooks
16
+ - `context.py` - UserPromptSubmit: Auto-inject project context (CLAUDE.md, README.md)
17
+ - `todo_continuation.py` - UserPromptSubmit: Remind about incomplete todos
18
+ - `pre_compact.py` - PreCompact: Context preservation before compaction
19
+
20
+ ### Tool Enhancement Hooks
21
+ - `tool_messaging.py` - PostToolUse: User-friendly tool/agent messaging
22
+ - `edit_recovery.py` - PostToolUse: Recovery guidance for failed Edit operations
23
+ - `truncator.py` - PostToolUse: Truncate long tool responses to prevent token overflow
24
+
25
+ ### Agent Lifecycle Hooks
26
+ - `notification_hook.py` - Notification: Agent spawn messages
27
+ - `subagent_stop.py` - SubagentStop: Agent completion handling
28
+
29
+ ## Installation for Claude Code
30
+
31
+ Copy the HOOKS_SETTINGS.json configuration to your project's .claude/settings.json:
32
+
33
+ ```bash
34
+ # From PyPI package location
35
+ cp $(python -c "import mcp_bridge; print(mcp_bridge.__path__[0])")/hooks/HOOKS_SETTINGS.json .claude/settings.json
36
+ ```
37
+
38
+ Or manually configure in .claude/settings.json (see HOOKS_SETTINGS.json for template).
39
+
40
+ ## Hook Types
41
+
42
+ Claude Code supports these hook types:
43
+ - **UserPromptSubmit**: Fires before response generation
44
+ - **PreToolUse**: Fires before tool execution (can block with exit 2)
45
+ - **PostToolUse**: Fires after tool execution
46
+ - **Notification**: Fires on notification events
47
+ - **SubagentStop**: Fires when subagent completes
48
+ - **PreCompact**: Fires before context compaction
49
+
50
+ ## Exit Codes
51
+
52
+ - `0` - Success (allow continuation)
53
+ - `1` - Warning (show but continue)
54
+ - `2` - Block (hard failure in stravinsky mode)
55
+
56
+ ## Environment Variables
57
+
58
+ Hooks receive these environment variables from Claude Code:
59
+ - `CLAUDE_CWD` - Current working directory
60
+ - `CLAUDE_TOOL_NAME` - Tool being invoked (PreToolUse/PostToolUse)
61
+ - `CLAUDE_SESSION_ID` - Active session ID
62
+
63
+ ## State Management
64
+
65
+ Stravinsky mode uses a marker file for state:
66
+ - `~/.stravinsky_mode` - Active when file exists
67
+ - Created by `/stravinsky` skill invocation
68
+ - Enables hard blocking of direct tools
69
+
70
+ ## Usage
71
+
72
+ These hooks are automatically installed with the Stravinsky MCP package.
73
+ To enable them in a Claude Code project:
74
+
75
+ 1. Copy HOOKS_SETTINGS.json to .claude/settings.json
76
+ 2. Adjust hook paths if needed (default assumes installed via PyPI)
77
+ 3. Restart Claude Code or reload configuration
78
+
79
+ ## Development
80
+
81
+ To test hooks locally:
82
+
83
+ ```bash
84
+ # Test parallel_execution hook
85
+ echo '{"prompt": "implement feature X"}' | python parallel_execution.py
86
+
87
+ # Test stravinsky_mode hook (requires marker file)
88
+ touch ~/.stravinsky_mode
89
+ echo '{"toolName": "Read", "params": {}}' | python stravinsky_mode.py
90
+ echo $? # Should be 2 (blocked)
91
+ rm ~/.stravinsky_mode
92
+ ```
93
+
94
+ ## Package Contents
4
95
  """
5
96
 
6
- from .manager import get_hook_manager
7
- from .truncator import output_truncator_hook
8
- from .edit_recovery import edit_error_recovery_hook
9
- from .directory_context import directory_context_hook
10
- from .compaction import context_compaction_hook
11
- from .budget_optimizer import budget_optimizer_hook
12
- from .todo_enforcer import todo_continuation_hook
13
- from .keyword_detector import keyword_detector_hook
14
- from .comment_checker import comment_checker_hook
15
- from .context_monitor import context_monitor_hook
16
- from .agent_reminder import agent_reminder_hook
17
- from .preemptive_compaction import preemptive_compaction_hook
18
- from .auto_slash_command import auto_slash_command_hook
19
- from .session_recovery import session_recovery_hook
20
- from .empty_message_sanitizer import empty_message_sanitizer_hook
97
+ __all__ = [
98
+ # Core execution
99
+ "parallel_execution",
100
+ "stravinsky_mode",
101
+ "todo_delegation",
102
+ # Context & state
103
+ "context",
104
+ "todo_continuation",
105
+ "pre_compact",
106
+ # Tool enhancement
107
+ "tool_messaging",
108
+ "edit_recovery",
109
+ "truncator",
110
+ # Agent lifecycle
111
+ "notification_hook",
112
+ "subagent_stop",
113
+ ]
21
114
 
22
115
 
23
116
  def initialize_hooks():
24
- """Register all available hooks."""
25
- manager = get_hook_manager()
26
-
27
- # Tier 1: Post-tool-call (immediate response modification)
28
- manager.register_post_tool_call(output_truncator_hook)
29
- manager.register_post_tool_call(edit_error_recovery_hook)
30
- manager.register_post_tool_call(comment_checker_hook)
31
- manager.register_post_tool_call(agent_reminder_hook)
32
- manager.register_post_tool_call(session_recovery_hook)
33
-
34
- # Tier 2: Pre-model-invoke (context management)
35
- manager.register_pre_model_invoke(directory_context_hook)
36
- manager.register_pre_model_invoke(context_compaction_hook)
37
- manager.register_pre_model_invoke(context_monitor_hook)
38
- manager.register_pre_model_invoke(preemptive_compaction_hook)
39
- manager.register_pre_model_invoke(empty_message_sanitizer_hook)
40
-
41
- # Tier 3: Pre-model-invoke (performance optimization)
42
- manager.register_pre_model_invoke(budget_optimizer_hook)
43
-
44
- # Tier 4: Pre-model-invoke (behavior enforcement)
45
- manager.register_pre_model_invoke(keyword_detector_hook)
46
- manager.register_pre_model_invoke(todo_continuation_hook)
47
- manager.register_pre_model_invoke(auto_slash_command_hook)
48
-
49
- return manager
117
+ """Initialize and register all hooks with the HookManager."""
118
+ # Currently hooks are primarily external scripts or lazy-loaded.
119
+ # This entry point allows for future internal hook registration.
120
+ pass
121
+
122
+
123
+ __version__ = "0.2.63"
124
+ __author__ = "David Andrews"
125
+ __description__ = "Claude Code hooks for Stravinsky MCP parallel execution"
@@ -1,41 +1,46 @@
1
- """
2
- Edit error recovery hook.
3
- Detects common mistakes in file editing and injects high-priority corrective directives.
4
- """
5
-
1
+ import os
2
+ import sys
3
+ import json
6
4
  import re
7
- from typing import Any, Dict, Optional
8
5
 
9
- EDIT_ERROR_PATTERNS = [
10
- r"oldString and newString must be different",
11
- r"oldString not found",
12
- r"oldString found multiple times",
13
- r"Target content not found",
14
- r"Multiple occurrences of target content found",
15
- ]
6
+ def main():
7
+ # Claude Code PostToolUse inputs via Environment Variables
8
+ tool_name = os.environ.get("CLAUDE_TOOL_NAME")
9
+
10
+ # We only care about Edit/MultiEdit
11
+ if tool_name not in ["Edit", "MultiEdit"]:
12
+ return
16
13
 
17
- EDIT_RECOVERY_PROMPT = """
18
- > **[EDIT ERROR - IMMEDIATE ACTION REQUIRED]**
19
- > You made an Edit mistake. STOP and do this NOW:
20
- > 1. **READ** the file immediately to see its ACTUAL current state.
21
- > 2. **VERIFY** what the content really looks like (your assumption was wrong).
22
- > 3. **APOLOGIZE** briefly to the user for the error.
23
- > 4. **CONTINUE** with corrected action based on the real file content.
24
- > **DO NOT** attempt another edit until you've read and verified the file state.
25
- """
14
+ # Read from stdin (Claude Code passes the tool response via stdin for some hook types,
15
+ # but for PostToolUse it's often better to check the environment variable if available.
16
+ # Actually, the summary says input is a JSON payload.
17
+ try:
18
+ data = json.load(sys.stdin)
19
+ tool_response = data.get("tool_response", "")
20
+ except Exception:
21
+ # Fallback to direct string if not JSON
22
+ return
26
23
 
27
- async def edit_error_recovery_hook(tool_name: str, arguments: Dict[str, Any], output: str) -> Optional[str]:
28
- """
29
- Analyzes tool output for edit errors and appends corrective directives.
30
- """
31
- # Check if this is an edit-related tool (handling both built-in and common MCP tools)
32
- edit_tools = ["replace_file_content", "multi_replace_file_content", "write_to_file", "edit_file", "Edit"]
33
-
34
- # We also check the output content for common patterns even if the tool name doesn't match perfectly
35
- is_edit_error = any(re.search(pattern, output, re.IGNORECASE) for pattern in EDIT_ERROR_PATTERNS)
36
-
37
- if is_edit_error or any(tool in tool_name for tool in edit_tools):
38
- if any(re.search(pattern, output, re.IGNORECASE) for pattern in EDIT_ERROR_PATTERNS):
39
- return output + EDIT_RECOVERY_PROMPT
40
-
41
- return None
24
+ # Error patterns
25
+ error_patterns = [
26
+ r"oldString not found",
27
+ r"oldString matched multiple times",
28
+ r"line numbers out of range"
29
+ ]
30
+
31
+ recovery_needed = any(re.search(p, tool_response, re.IGNORECASE) for p in error_patterns)
32
+
33
+ if recovery_needed:
34
+ correction = (
35
+ "\n\n[SYSTEM RECOVERY] It appears the Edit tool failed to find the target string. "
36
+ "Please call 'Read' on the file again to verify the current content, "
37
+ "then ensure your 'oldString' is an EXACT match including all whitespace."
38
+ )
39
+ # For PostToolUse, stdout is captured and appended/replaces output
40
+ print(tool_response + correction)
41
+ else:
42
+ # No change
43
+ print(tool_response)
44
+
45
+ if __name__ == "__main__":
46
+ main()