stravinsky 0.2.11__tar.gz → 0.2.62__tar.gz

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 (154) hide show
  1. {stravinsky-0.2.11 → stravinsky-0.2.62}/.github/workflows/publish.yml +3 -4
  2. stravinsky-0.2.62/.mcp.json +8 -0
  3. stravinsky-0.2.62/.stravinsky/agents/agent_0de66569.out +117 -0
  4. stravinsky-0.2.62/.stravinsky/agents/agent_0de66569.system +10 -0
  5. stravinsky-0.2.62/.stravinsky/agents/agent_2ef2b305.out +142 -0
  6. stravinsky-0.2.62/.stravinsky/agents/agent_2ef2b305.system +9 -0
  7. stravinsky-0.2.62/.stravinsky/agents/agent_32fc606b.out +123 -0
  8. stravinsky-0.2.62/.stravinsky/agents/agent_32fc606b.system +10 -0
  9. stravinsky-0.2.62/.stravinsky/agents/agent_4943202a.out +112 -0
  10. stravinsky-0.2.62/.stravinsky/agents/agent_4943202a.system +10 -0
  11. stravinsky-0.2.62/.stravinsky/agents/agent_4ed6ec7a.out +132 -0
  12. stravinsky-0.2.62/.stravinsky/agents/agent_4ed6ec7a.system +9 -0
  13. stravinsky-0.2.62/.stravinsky/agents/agent_622ae68b.out +119 -0
  14. stravinsky-0.2.62/.stravinsky/agents/agent_622ae68b.system +10 -0
  15. stravinsky-0.2.62/.stravinsky/agents/agent_6731b838.out +278 -0
  16. stravinsky-0.2.62/.stravinsky/agents/agent_6731b838.system +10 -0
  17. stravinsky-0.2.62/.stravinsky/agents/agent_6c1ebe08.out +345 -0
  18. stravinsky-0.2.62/.stravinsky/agents/agent_6c1ebe08.system +9 -0
  19. stravinsky-0.2.62/.stravinsky/agents/agent_6c536f2d.out +103 -0
  20. stravinsky-0.2.62/.stravinsky/agents/agent_6c536f2d.system +10 -0
  21. stravinsky-0.2.62/.stravinsky/agents/agent_6ecde4ed.out +76 -0
  22. stravinsky-0.2.62/.stravinsky/agents/agent_6ecde4ed.system +9 -0
  23. stravinsky-0.2.62/.stravinsky/agents/agent_6f6687f1.out +388 -0
  24. stravinsky-0.2.62/.stravinsky/agents/agent_6f6687f1.system +10 -0
  25. stravinsky-0.2.62/.stravinsky/agents/agent_85449406.out +13 -0
  26. stravinsky-0.2.62/.stravinsky/agents/agent_85449406.system +9 -0
  27. stravinsky-0.2.62/.stravinsky/agents/agent_940fbc06.out +170 -0
  28. stravinsky-0.2.62/.stravinsky/agents/agent_940fbc06.system +10 -0
  29. stravinsky-0.2.62/.stravinsky/agents/agent_adc99d05.out +128 -0
  30. stravinsky-0.2.62/.stravinsky/agents/agent_adc99d05.system +10 -0
  31. stravinsky-0.2.62/.stravinsky/agents/agent_b3c09833.out +124 -0
  32. stravinsky-0.2.62/.stravinsky/agents/agent_b3c09833.system +10 -0
  33. stravinsky-0.2.62/.stravinsky/agents/agent_cdd28e91.system +10 -0
  34. stravinsky-0.2.62/.stravinsky/agents/agent_e7637527.out +353 -0
  35. stravinsky-0.2.62/.stravinsky/agents/agent_e7637527.system +9 -0
  36. stravinsky-0.2.62/.stravinsky/agents/agent_fee89a04.out +81 -0
  37. stravinsky-0.2.62/.stravinsky/agents/agent_fee89a04.system +10 -0
  38. stravinsky-0.2.62/.stravinsky/agents.json +290 -0
  39. stravinsky-0.2.62/ARCHITECTURE.md +1133 -0
  40. {stravinsky-0.2.11 → stravinsky-0.2.62}/CLAUDE.md +6 -1
  41. stravinsky-0.2.62/INSTALL.md +484 -0
  42. stravinsky-0.2.62/PKG-INFO +284 -0
  43. stravinsky-0.2.62/README.md +252 -0
  44. stravinsky-0.2.62/docs/AGENTS.md +282 -0
  45. stravinsky-0.2.62/docs/AGENT_WORKFLOW.md +974 -0
  46. stravinsky-0.2.62/docs/INSTALL.md +370 -0
  47. stravinsky-0.2.62/docs/QUICKSTART.md +127 -0
  48. stravinsky-0.2.62/docs/README.md +79 -0
  49. stravinsky-0.2.62/docs/TROUBLESHOOTING.md +382 -0
  50. stravinsky-0.2.62/docs/USAGE.md +460 -0
  51. stravinsky-0.2.62/docs/architecture_workflow.md +79 -0
  52. stravinsky-0.2.62/docs/remediation_plan.md +38 -0
  53. stravinsky-0.2.62/logs/.1c0e2f6784d083818216ed08579b248b799c8d86-audit.json +25 -0
  54. stravinsky-0.2.62/logs/.270de9f01be3c37438e0ae9542f6c146c85078ae-audit.json +25 -0
  55. stravinsky-0.2.62/logs/application-2026-01-03.log +45 -0
  56. stravinsky-0.2.62/logs/application-2026-01-04.log +232 -0
  57. stravinsky-0.2.62/logs/application-2026-01-05.log +111 -0
  58. stravinsky-0.2.62/logs/error-2026-01-03.log +3 -0
  59. stravinsky-0.2.62/logs/error-2026-01-04.log +24 -0
  60. stravinsky-0.2.62/logs/error-2026-01-05.log +8 -0
  61. stravinsky-0.2.62/mcp_bridge/__init__.py +1 -0
  62. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/auth/cli.py +84 -46
  63. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/auth/oauth.py +88 -63
  64. stravinsky-0.2.62/mcp_bridge/auth/token_refresh.py +130 -0
  65. stravinsky-0.2.62/mcp_bridge/cli/__init__.py +5 -0
  66. stravinsky-0.2.62/mcp_bridge/cli/session_report.py +585 -0
  67. stravinsky-0.2.62/mcp_bridge/hooks/__init__.py +78 -0
  68. stravinsky-0.2.62/mcp_bridge/hooks/agent_reminder.py +61 -0
  69. stravinsky-0.2.62/mcp_bridge/hooks/auto_slash_command.py +186 -0
  70. stravinsky-0.2.62/mcp_bridge/hooks/comment_checker.py +136 -0
  71. stravinsky-0.2.62/mcp_bridge/hooks/context_monitor.py +58 -0
  72. stravinsky-0.2.62/mcp_bridge/hooks/empty_message_sanitizer.py +240 -0
  73. stravinsky-0.2.62/mcp_bridge/hooks/git_noninteractive.py +89 -0
  74. stravinsky-0.2.62/mcp_bridge/hooks/keyword_detector.py +152 -0
  75. stravinsky-0.2.62/mcp_bridge/hooks/manager.py +146 -0
  76. stravinsky-0.2.62/mcp_bridge/hooks/parallel_enforcer.py +127 -0
  77. stravinsky-0.2.62/mcp_bridge/hooks/pre_compact.py +234 -0
  78. stravinsky-0.2.62/mcp_bridge/hooks/preemptive_compaction.py +231 -0
  79. stravinsky-0.2.62/mcp_bridge/hooks/rules_injector.py +507 -0
  80. stravinsky-0.2.62/mcp_bridge/hooks/session_idle.py +116 -0
  81. stravinsky-0.2.62/mcp_bridge/hooks/session_notifier.py +125 -0
  82. stravinsky-0.2.62/mcp_bridge/hooks/session_recovery.py +186 -0
  83. stravinsky-0.2.62/mcp_bridge/hooks/task_validator.py +73 -0
  84. stravinsky-0.2.62/mcp_bridge/hooks/tmux_manager.py +141 -0
  85. stravinsky-0.2.62/mcp_bridge/hooks/todo_enforcer.py +75 -0
  86. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/prompts/__init__.py +3 -1
  87. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/prompts/delphi.py +3 -2
  88. stravinsky-0.2.62/mcp_bridge/prompts/dewey.py +277 -0
  89. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/prompts/explore.py +46 -8
  90. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/prompts/multimodal.py +24 -3
  91. stravinsky-0.2.62/mcp_bridge/prompts/planner.py +222 -0
  92. stravinsky-0.2.62/mcp_bridge/prompts/stravinsky.py +739 -0
  93. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/server.py +319 -65
  94. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/server_tools.py +181 -33
  95. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/__init__.py +2 -1
  96. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/agent_manager.py +439 -284
  97. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/background_tasks.py +2 -1
  98. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/code_search.py +59 -1
  99. stravinsky-0.2.62/mcp_bridge/tools/model_invoke.py +986 -0
  100. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/skill_loader.py +51 -47
  101. stravinsky-0.2.62/mcp_bridge/tools/task_runner.py +141 -0
  102. stravinsky-0.2.62/mcp_bridge/tools/templates.py +189 -0
  103. {stravinsky-0.2.11 → stravinsky-0.2.62}/pyproject.toml +2 -1
  104. stravinsky-0.2.62/repro_spawn.py +29 -0
  105. stravinsky-0.2.62/run-mcp.sh +3 -0
  106. stravinsky-0.2.62/tests/conftest.py +8 -0
  107. stravinsky-0.2.62/tests/test_new_hooks.py +316 -0
  108. {stravinsky-0.2.11 → stravinsky-0.2.62}/uv.lock +1 -1
  109. stravinsky-0.2.11/.mcp.json +0 -3
  110. stravinsky-0.2.11/.stravinsky/agents/agent_9b9fd4f0.log +0 -0
  111. stravinsky-0.2.11/.stravinsky/agents/agent_9b9fd4f0.out +0 -1
  112. stravinsky-0.2.11/.stravinsky/agents.json +0 -1
  113. stravinsky-0.2.11/PKG-INFO +0 -210
  114. stravinsky-0.2.11/README.md +0 -178
  115. stravinsky-0.2.11/mcp_bridge/__init__.py +0 -1
  116. stravinsky-0.2.11/mcp_bridge/hooks/__init__.py +0 -28
  117. stravinsky-0.2.11/mcp_bridge/hooks/manager.py +0 -77
  118. stravinsky-0.2.11/mcp_bridge/native_hooks/context.py +0 -38
  119. stravinsky-0.2.11/mcp_bridge/native_hooks/edit_recovery.py +0 -46
  120. stravinsky-0.2.11/mcp_bridge/native_hooks/truncator.py +0 -23
  121. stravinsky-0.2.11/mcp_bridge/prompts/dewey.py +0 -183
  122. stravinsky-0.2.11/mcp_bridge/prompts/stravinsky.py +0 -345
  123. stravinsky-0.2.11/mcp_bridge/tools/model_invoke.py +0 -297
  124. stravinsky-0.2.11/mcp_bridge/tools/task_runner.py +0 -97
  125. stravinsky-0.2.11/mcp_bridge/tools/templates.py +0 -94
  126. {stravinsky-0.2.11 → stravinsky-0.2.62}/.gitignore +0 -0
  127. {stravinsky-0.2.11 → stravinsky-0.2.62}/assets/logo.png +0 -0
  128. {stravinsky-0.2.11 → stravinsky-0.2.62}/assets/logo.png.txt +0 -0
  129. {stravinsky-0.2.11 → stravinsky-0.2.62}/assets/logo_small.png +0 -0
  130. {stravinsky-0.2.11 → stravinsky-0.2.62}/error.log +0 -0
  131. {stravinsky-0.2.11 → stravinsky-0.2.62}/install_native_hooks.py +0 -0
  132. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/auth/__init__.py +0 -0
  133. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/auth/openai_oauth.py +0 -0
  134. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/auth/token_store.py +0 -0
  135. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/config/__init__.py +0 -0
  136. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/config/hooks.py +0 -0
  137. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/hooks/budget_optimizer.py +0 -0
  138. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/hooks/compaction.py +0 -0
  139. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/hooks/directory_context.py +0 -0
  140. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/hooks/edit_recovery.py +0 -0
  141. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/hooks/truncator.py +0 -0
  142. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/prompts/document_writer.py +0 -0
  143. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/prompts/frontend.py +0 -0
  144. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/continuous_loop.py +0 -0
  145. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/init.py +0 -0
  146. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/lsp/__init__.py +0 -0
  147. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/lsp/tools.py +0 -0
  148. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/project_context.py +0 -0
  149. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/tools/session_manager.py +0 -0
  150. {stravinsky-0.2.11 → stravinsky-0.2.62}/mcp_bridge/utils/__init__.py +0 -0
  151. {stravinsky-0.2.11 → stravinsky-0.2.62}/stdout_handshake_auditor.py +0 -0
  152. {stravinsky-0.2.11 → stravinsky-0.2.62}/tests/manual_test_hooks.py +0 -0
  153. {stravinsky-0.2.11 → stravinsky-0.2.62}/tests/test_hooks.py +0 -0
  154. {stravinsky-0.2.11 → stravinsky-0.2.62}/verify_tools.py +0 -0
@@ -10,7 +10,6 @@ jobs:
10
10
  build-and-publish:
11
11
  runs-on: ubuntu-latest
12
12
  permissions:
13
- id-token: write # Required for trusted publishing
14
13
  contents: read
15
14
 
16
15
  steps:
@@ -33,6 +32,6 @@ jobs:
33
32
  - name: Publish to PyPI
34
33
  uses: pypa/gh-action-pypi-publish@release/v1
35
34
  with:
36
- # Uses trusted publishing - no token needed if configured on PyPI
37
- # Fallback to token if trusted publishing not set up:
38
- password: ${{ secrets.PYPI_API_TOKEN }}
35
+ # Disable OIDC trusted publishing - use API token instead
36
+ attestations: false
37
+ password: ${{ secrets.PYPY_API_TOKEN }}
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "stravinsky": {
4
+ "command": "/Users/davidandrews/PycharmProjects/stravinsky/run-mcp.sh",
5
+ "args": []
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,117 @@
1
+ I have the complete picture now. Here's the comprehensive summary:
2
+
3
+ ---
4
+
5
+ ## Claude Code Hooks Structure in Stravinsky - Complete Analysis
6
+
7
+ ### 1. Hook Files Location
8
+
9
+ **Native hooks directory:** `/Users/davidandrews/PycharmProjects/stravinsky/mcp_bridge/native_hooks/`
10
+ - `context.py` - UserPromptSubmit hook (injects README/CLAUDE.md context)
11
+ - `edit_recovery.py` - PostToolUse for Edit error recovery
12
+ - `stravinsky_mode.py` - PreToolUse to block native tools in orchestrator mode
13
+ - `todo_delegation.py` - PostToolUse for TodoWrite parallel enforcement
14
+ - `truncator.py` - PostToolUse for response truncation
15
+
16
+ ### 2. Configuration Format (`.claude/settings.json`)
17
+
18
+ ```json
19
+ {
20
+ "hooks": {
21
+ "PreToolUse": [
22
+ {
23
+ "matcher": "Read,Search,Grep,Bash,Edit,MultiEdit",
24
+ "hooks": [
25
+ {
26
+ "type": "command",
27
+ "command": "python3 /absolute/path/to/hook.py"
28
+ }
29
+ ]
30
+ }
31
+ ],
32
+ "UserPromptSubmit": [
33
+ {
34
+ "matcher": "*",
35
+ "hooks": [
36
+ {
37
+ "type": "command",
38
+ "command": "python3 /absolute/path/to/context.py"
39
+ }
40
+ ]
41
+ }
42
+ ],
43
+ "PostToolUse": [
44
+ {
45
+ "matcher": "*",
46
+ "hooks": [...]
47
+ },
48
+ {
49
+ "matcher": "TodoWrite",
50
+ "hooks": [...]
51
+ }
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+
57
+ **Key configuration properties:**
58
+ - `matcher`: Tool names (comma-separated) or `"*"` for all
59
+ - `type`: `"command"` for shell commands
60
+ - `command`: Full command to execute
61
+
62
+ ### 3. UserPromptSubmit Hook Pattern (context.py)
63
+
64
+ ```python
65
+ import os
66
+ import sys
67
+ import json
68
+ from pathlib import Path
69
+
70
+ def main():
71
+ # 1. Read JSON input from stdin
72
+ try:
73
+ data = json.load(sys.stdin)
74
+ prompt = data.get("prompt", "")
75
+ except Exception:
76
+ return
77
+
78
+ # 2. Get working directory from env
79
+ cwd = Path(os.environ.get("CLAUDE_CWD", "."))
80
+
81
+ # 3. Load context or modify prompt
82
+ new_prompt = f"[CONTEXT]\n{context}\n\n[USER PROMPT]\n{prompt}"
83
+
84
+ # 4. Output modified prompt to stdout
85
+ print(new_prompt)
86
+
87
+ if __name__ == "__main__":
88
+ main()
89
+ ```
90
+
91
+ ### 4. Environment Variables Available
92
+ - `CLAUDE_CWD` - Current working directory
93
+ - `CLAUDE_SESSION_ID` - Session ID
94
+ - `CLAUDE_TOOL_NAME` - Tool name (for tool hooks)
95
+ - `CLAUDE_TOOL_INPUT` - JSON of tool input
96
+
97
+ ### 5. Exit Codes
98
+ - `0` - Continue normally
99
+ - `1` - Block/deny operation
100
+ - `2+` - Error (logged, continues)
101
+
102
+ ### 6. Hook Types Summary
103
+
104
+ | Hook Type | Input (stdin) | Output (stdout) | Purpose |
105
+ |-----------|---------------|-----------------|---------|
106
+ | `UserPromptSubmit` | `{"prompt": "..."}` | Modified prompt string | Augment user prompts |
107
+ | `PreToolUse` | `{"tool_name": "...", "tool_input": {...}}` | Exit code controls execution | Block/allow tools |
108
+ | `PostToolUse` | `{"tool_name": "...", "tool_response": "..."}` | Modified response | Transform tool output |
109
+ | `Stop` | Session context | Continuation prompt | Follow-up actions |
110
+
111
+ ### 7. For Todo Continuation Hook Implementation
112
+
113
+ To create a new UserPromptSubmit hook for todo continuation:
114
+
115
+ 1. **Create hook file:** `.claude/hooks/todo_reminder.py`
116
+ 2. **Pattern:** Read stdin JSON → Check TODO.md or TodoWrite state → Print augmented prompt
117
+ 3. **Register in settings.json:** Add to `UserPromptSubmit` array with `"matcher": "*"`
@@ -0,0 +1,10 @@
1
+ You are a codebase exploration specialist. Find files, patterns, and answer 'where is X?' questions.
2
+
3
+ MODEL ROUTING (MANDATORY):
4
+ You MUST use invoke_gemini with model="gemini-3-flash" for ALL analysis and reasoning.
5
+ Use Claude's native tools (Read, Grep, Glob) ONLY for file access, then pass content to invoke_gemini.
6
+
7
+ WORKFLOW:
8
+ 1. Use Read/Grep/Glob to get file contents
9
+ 2. Call invoke_gemini(prompt="Analyze this: <content>", model="gemini-3-flash", agent_context={"agent_type": "explore"}) for analysis
10
+ 3. Return the Gemini response
@@ -0,0 +1,142 @@
1
+ ## Delphi's Strategic Analysis: Hook Consolidation & Circular Invocation
2
+
3
+ The strategic advisor (GPT-5.2) has provided comprehensive architectural analysis. Here are the key recommendations:
4
+
5
+ ---
6
+
7
+ ## Question 1: Hook Consolidation Strategy
8
+
9
+ ### **Recommendation: Hybrid + Unified Interface**
10
+
11
+ **Core Strategy:**
12
+ - **Native Hooks**: Keep for tool access control and "must-block" behavior (security gates)
13
+ - **MCP Hooks**: Keep for MCP tool dispatch, model routing, session lifecycle, budgeting
14
+ - **Unified Interface**: Create shared hook protocol with adapters for both contexts
15
+
16
+ ### Key Insights
17
+
18
+ **Technical Analysis:**
19
+ - "All Native" or "All MCP" create impedance mismatches because Claude Code's native tools exist outside MCP
20
+ - Current hybrid is technically sound IF boundaries are crisp
21
+ - Performance: MCP hooks are faster (in-process), native hooks add subprocess overhead
22
+
23
+ **Security Layering:**
24
+ - **Native**: Hard gates (deny/allow) for Claude Code tools + pre-execution redaction
25
+ - **MCP**: Soft/hard gates for MCP tools + model invocation policy, quotas, logging
26
+ - This layered approach provides defense in depth
27
+
28
+ **Industry Pattern:**
29
+ Matches production agentic CLI designs:
30
+ - Native = enforcement boundary (closest to execution)
31
+ - MCP = orchestration layer (rich lifecycle management)
32
+
33
+ ### Actionable Migration Path
34
+
35
+ 1. **Define canonical event model**: `ToolEvent`, `ModelInvokeEvent`, `SessionEvent`
36
+ 2. **Wrap existing native hooks** with compatibility shim
37
+ 3. **Port MCP hooks tier-by-tier** into unified form (lowest risk first)
38
+ 4. **Single source of truth** for policies (allow/deny lists, budgets) consumed by both contexts
39
+
40
+ ### Success Metrics
41
+ - % of hook logic shared vs duplicated
42
+ - Hook-induced latency (p50/p95)
43
+ - Incident rate for "unexpected block" / "policy mismatch" bugs
44
+ - Trace completeness (native + MCP share `trace_id`)
45
+
46
+ ---
47
+
48
+ ## Question 2: Circular Invocation Pattern
49
+
50
+ ### **Recommendation: Keep Current (Option D) + Add Local Model Proxy**
51
+
52
+ **Core Strategy:**
53
+ Decouple model transport without losing Claude Code's tool ecosystem:
54
+
55
+ ```
56
+ Claude Code (main)
57
+
58
+ Stravinsky MCP Server
59
+
60
+ agent_spawn → Claude CLI process (agent)
61
+
62
+ Agent invokes tools (Read/Grep/Bash) + invoke_gemini
63
+
64
+ MCP invoke_gemini → LOCAL MODEL PROXY (Unix socket/HTTP)
65
+
66
+ Model Proxy → Google Antigravity / OpenAI API
67
+ ```
68
+
69
+ ### Key Benefits
70
+
71
+ **Performance:**
72
+ - Breaks tight "agent → MCP stdio → provider" coupling
73
+ - Scales concurrency independent of MCP's stdio constraints
74
+ - Moves heavy provider I/O out of MCP event loop
75
+
76
+ **Security:**
77
+ - Keeps centralized auth/token management
78
+ - Enables per-provider circuit breakers and rate limits
79
+ - Maintains audit logging with unified trace IDs
80
+
81
+ **Flexibility:**
82
+ - Hybrid routing: model-only tasks can use proxy directly (no subprocess)
83
+ - Tasks needing tools still use `agent_spawn` with full Claude Code access
84
+
85
+ ### Failure Mode Analysis
86
+
87
+ **Current Risks:**
88
+ - Head-of-line blocking on single MCP stdio transport
89
+ - Re-entrancy contention with many concurrent agents
90
+ - Cascade failures from provider rate limits
91
+ - Zombie agents outliving orchestrator
92
+
93
+ **Mitigations:**
94
+ - Circuit breaker per provider
95
+ - Queue + concurrency limits
96
+ - Agent cancellation propagation
97
+ - Persistent task ledger for resumable state
98
+
99
+ ### Migration Path
100
+
101
+ 1. **Implement model proxy** with same request/response schema as current `invoke_*`
102
+ 2. **Switch MCP tools** to proxy-backed implementation (transparent change)
103
+ 3. **Add trace ID propagation** from Claude → agent → proxy
104
+ 4. **Optional: Add hybrid routing** for model-only tasks (Python worker calling proxy directly)
105
+
106
+ ### Success Metrics
107
+ - End-to-end `invoke_*` latency (p50/p95) under N concurrent agents
108
+ - MCP protocol stability (fewer hangs/timeouts)
109
+ - Provider error rate and retry amplification
110
+ - Reduction in spawned Claude processes for model-only work
111
+
112
+ ---
113
+
114
+ ## Long-Term Vision (5 Years)
115
+
116
+ **Hook System:**
117
+ - Unified interface enables porting to alternative frontends (other IDEs)
118
+ - New hook types added without duplicating semantics
119
+ - Positions Stravinsky as "policy + orchestration layer" vs tightly coupled to one mechanism
120
+
121
+ **Model Architecture:**
122
+ - Local proxy enables multiple frontends beyond Claude Code
123
+ - Improved caching (prompt/result memoization)
124
+ - Single telemetry point for all model interactions
125
+ - Simpler adoption of new providers/models
126
+
127
+ **Ecosystem Compatibility:**
128
+ - MCP evolution (multi-client, richer transport) can be absorbed independently
129
+ - Claude Code hook API changes minimized through unified hook spec
130
+ - New use cases: team policy packs, per-project budgets, trace replay, offline simulation
131
+
132
+ ---
133
+
134
+ ## Next Steps
135
+
136
+ The advisor offers to create an actionable design document with:
137
+ - Module structure aligned with `mcp_bridge/hooks/` and `mcp_bridge/native_hooks/`
138
+ - Event schemas for unified hook interface
139
+ - Ordering rules and tier semantics
140
+ - Minimal incremental milestone plan
141
+
142
+ Would you like me to proceed with creating this design document?
@@ -0,0 +1,9 @@
1
+ You are a strategic technical advisor for architecture and hard debugging.
2
+
3
+ MODEL ROUTING (MANDATORY):
4
+ You MUST use invoke_openai with model="gpt-5.2" for ALL strategic advice and analysis.
5
+
6
+ WORKFLOW:
7
+ 1. Gather context about the problem
8
+ 2. Call invoke_openai(prompt="<problem description>", model="gpt-5.2", agent_context={"agent_type": "delphi"})
9
+ 3. Return the GPT response
@@ -0,0 +1,123 @@
1
+ Perfect! Based on my exploration of the Stravinsky codebase, here's a comprehensive analysis of how agents invoke Gemini and OpenAI:
2
+
3
+ ## 📋 Summary: Agent Model Invocation in Stravinsky
4
+
5
+ ### 1. **Agent Spawn Implementation**
6
+
7
+ The `agent_spawn()` function in `mcp_bridge/tools/agent_manager.py` is the core mechanism:
8
+
9
+ - **Entry Point**: `agent_spawn(prompt, agent_type, description, model, thinking_budget, timeout)`
10
+ - **Returns**: Task ID for tracking
11
+ - **Execution**: Spawns Claude CLI subprocess with `claude -p <prompt> --dangerously-skip-permissions`
12
+ - **Storage**: Tasks stored in `.stravinsky/agents/` directory
13
+
14
+ ### 2. **Model Routing Architecture**
15
+
16
+ **Key Innovation**: Specialized agents DON'T use Claude directly - they're instructed via system prompts to call `invoke_gemini` or `invoke_openai`:
17
+
18
+ ```python
19
+ AGENT_MODEL_ROUTING = {
20
+ "explore": None, # No CLI model - uses invoke_gemini
21
+ "dewey": None, # No CLI model - uses invoke_gemini
22
+ "document_writer": None, # No CLI model - uses invoke_gemini
23
+ "multimodal": None, # No CLI model - uses invoke_gemini
24
+ "frontend": None, # No CLI model - uses invoke_gemini
25
+ "delphi": None, # No CLI model - uses invoke_openai
26
+ "planner": "opus", # Direct Claude Opus via CLI
27
+ "_default": "sonnet", # Direct Claude Sonnet via CLI
28
+ }
29
+ ```
30
+
31
+ ### 3. **System Prompt Enforcement**
32
+
33
+ Each agent type gets a mandatory system prompt that enforces model routing:
34
+
35
+ **Example - Explore Agent** (lines 656-665):
36
+ ```
37
+ You MUST use invoke_gemini with model="gemini-3-flash" for ALL analysis and reasoning.
38
+ Use Claude's native tools (Read, Grep, Glob) ONLY for file access, then pass content to invoke_gemini.
39
+
40
+ WORKFLOW:
41
+ 1. Use Read/Grep/Glob to get file contents
42
+ 2. Call invoke_gemini(prompt="Analyze this: <content>", model="gemini-3-flash") for analysis
43
+ 3. Return the Gemini response
44
+ ```
45
+
46
+ **Example - Delphi Agent** (lines 692-696):
47
+ ```
48
+ You MUST use invoke_openai with model="gpt-5.2" for ALL strategic advice and analysis.
49
+
50
+ WORKFLOW:
51
+ 1. Gather context about the problem
52
+ 2. Call invoke_openai(prompt="<problem description>", model="gpt-5.2")
53
+ 3. Return the GPT response
54
+ ```
55
+
56
+ ### 4. **invoke_gemini Implementation**
57
+
58
+ Located in `mcp_bridge/tools/model_invoke.py`:
59
+
60
+ - **OAuth Flow**: Uses TokenStore with automatic refresh
61
+ - **API**: Calls Google Antigravity API (`/v1internal:generateContent`)
62
+ - **Features**: Session persistence for thinking cache, endpoint fallback, retry logic
63
+ - **Thinking Support**: Supports `thinking_budget` parameter for extended reasoning
64
+
65
+ ### 5. **invoke_openai Implementation**
66
+
67
+ Also in `model_invoke.py`:
68
+
69
+ - **OAuth Flow**: Uses OpenAI ChatGPT OAuth tokens
70
+ - **API**: Calls `chatgpt.com/backend-api/codex/responses` (SSE streaming)
71
+ - **Features**: JWT account ID extraction, Codex instructions fetching from GitHub
72
+ - **Streaming**: Parses SSE events for `response.output_text.delta`
73
+
74
+ ### 6. **Output and Logging Structure**
75
+
76
+ For each spawned agent task:
77
+
78
+ ```
79
+ .stravinsky/agents/
80
+ ├── agent_abc123.out # stdout - final response from agent
81
+ ├── agent_abc123.log # stderr - errors/warnings
82
+ └── agent_abc123.system # system prompt file (if custom)
83
+ ```
84
+
85
+ **Key logging points**:
86
+ - Line 248: "Spawning Claude CLI agent {task_id} ({agent_type})"
87
+ - Line 316: "Agent {task_id} completed successfully"
88
+ - Line 327: "Agent {task_id} failed: {error_msg}"
89
+
90
+ ### 7. **Agent Context & Metadata**
91
+
92
+ The `AgentTask` dataclass tracks:
93
+
94
+ ```python
95
+ @dataclass
96
+ class AgentTask:
97
+ id: str # Task identifier (e.g., "agent_abc123")
98
+ prompt: str # Full task prompt
99
+ agent_type: str # explore, dewey, delphi, etc.
100
+ description: str # Short display description
101
+ status: str # pending/running/completed/failed/cancelled
102
+ created_at: str # ISO timestamp
103
+ started_at: Optional[str] # When execution began
104
+ completed_at: Optional[str] # When finished
105
+ result: Optional[str] # Final output
106
+ error: Optional[str] # Error message if failed
107
+ pid: Optional[int] # Process ID for cancellation
108
+ timeout: int = 300 # Max execution time
109
+ parent_session_id: Optional[str] # For notifications
110
+ progress: Optional[Dict] # Real-time progress tracking
111
+ ```
112
+
113
+ ### 8. **Key Architectural Patterns**
114
+
115
+ ✅ **Separation of Concerns**: Claude CLI handles tool access, external models (Gemini/GPT) handle reasoning
116
+ ✅ **Cost Optimization**: Cheap models (gemini-3-flash) for exploration, expensive models (gpt-5.2) for strategy
117
+ ✅ **Non-Blocking**: All agents run in background threads, allowing parallel execution
118
+ ✅ **Persistence**: Task state survives process restarts via JSON storage
119
+ ✅ **Zombie Detection**: Progress tracking checks if PIDs still exist (line 541-555)
120
+
121
+ ---
122
+
123
+ **Bottom Line**: Stravinsky agents are Claude CLI subprocesses that are **instructed via system prompts** to delegate their actual reasoning to Gemini or OpenAI by calling `invoke_gemini`/`invoke_openai` MCP tools. This creates a multi-model orchestration layer where Claude manages tool usage while specialized models handle domain-specific reasoning.
@@ -0,0 +1,10 @@
1
+ You are a codebase exploration specialist. Find files, patterns, and answer 'where is X?' questions.
2
+
3
+ MODEL ROUTING (MANDATORY):
4
+ You MUST use invoke_gemini with model="gemini-3-flash" for ALL analysis and reasoning.
5
+ Use Claude's native tools (Read, Grep, Glob) ONLY for file access, then pass content to invoke_gemini.
6
+
7
+ WORKFLOW:
8
+ 1. Use Read/Grep/Glob to get file contents
9
+ 2. Call invoke_gemini(prompt="Analyze this: <content>", model="gemini-3-flash") for analysis
10
+ 3. Return the Gemini response
@@ -0,0 +1,112 @@
1
+ The Gemini calls aren't working. Let me analyze this directly based on the code I've read:
2
+
3
+ ## Analysis: Delegation and Parallel Execution in Stravinsky
4
+
5
+ Based on my examination of the codebase, here's what I found:
6
+
7
+ ### 1. **`run_in_background` Parameter - Documentation Error**
8
+
9
+ **Finding**: `run_in_background=true` appears in hook instructions but is **NOT implemented** in either the native Task tool or the MCP agent_spawn tool.
10
+
11
+ **Evidence**:
12
+ - `.claude/hooks/todo_delegation.py` (line 69-70): Shows example using `run_in_background=true`
13
+ - `.claude/hooks/parallel_execution.py` (line 82, 95-97): Shows example using `run_in_background=true`
14
+ - `mcp_bridge/tools/agent_manager.py` (line 646): agent_spawn has `blocking` parameter (default False), NOT `run_in_background`
15
+ - Native Task tool: No `run_in_background` parameter exists in Claude Code's Task tool
16
+
17
+ **Conclusion**: This is a **documentation inconsistency**. The hooks are providing incorrect example syntax.
18
+
19
+ ### 2. **Two Parallel Delegation Systems**
20
+
21
+ The codebase has **TWO separate delegation mechanisms**:
22
+
23
+ #### A. **Native Claude Code System** (Task tool)
24
+ - **Where**: Used in `.claude/agents/stravinsky.md` orchestrator
25
+ - **Tool**: Native `Task(subagent_type="explore", prompt="...", description="...")`
26
+ - **Behavior**: Blocking by default - returns results directly in function response
27
+ - **No async mode**: Task tool is synchronous, no background execution
28
+ - **Usage**: Stravinsky orchestrator delegates to explore/dewey/code-reviewer/debugger/frontend
29
+
30
+ #### B. **Stravinsky MCP System** (agent_spawn)
31
+ - **Where**: `mcp_bridge/tools/agent_manager.py`
32
+ - **Tool**: `agent_spawn(prompt="...", agent_type="explore", blocking=False)`
33
+ - **Behavior**:
34
+ - `blocking=False` (default): Returns task_id immediately, async execution
35
+ - `blocking=True`: Waits for completion, returns full result
36
+ - **Collection**: Use `agent_output(task_id, block=True)` to retrieve results
37
+ - **Usage**: MCP tools for when native subagents need to spawn their own background work
38
+
39
+ ### 3. **Stravinsky Mode Flow**
40
+
41
+ **Activation**:
42
+ 1. User invokes `/stravinsky` skill
43
+ 2. `parallel_execution.py` (UserPromptSubmit hook) detects invocation
44
+ 3. Creates `~/.stravinsky_mode` marker file
45
+ 4. Injects parallel execution instructions into prompt
46
+
47
+ **Enforcement**:
48
+ 1. `stravinsky_mode.py` (PreToolUse hook) checks for marker file
49
+ 2. Blocks Read/Grep/Bash/Edit/MultiEdit with exit code 2
50
+ 3. Forces delegation to Task tool instead
51
+
52
+ **Post-TodoWrite**:
53
+ 1. `todo_delegation.py` (PostToolUse hook) fires after TodoWrite
54
+ 2. Counts pending todos
55
+ 3. If 2+ pending and stravinsky mode active: exit code 2 (HARD BLOCK)
56
+ 4. If 2+ pending and mode inactive: exit code 1 (WARNING)
57
+
58
+ ### 4. **Gaps and Inconsistencies**
59
+
60
+ **Critical Issues**:
61
+
62
+ 1. **Invalid Parameter**: Hooks instruct `run_in_background=true` but this parameter doesn't exist
63
+ - Should be removed or corrected to match actual API
64
+
65
+ 2. **Mixed Metaphors**:
66
+ - Hooks say "Task tool" but show agent_spawn examples
67
+ - `.claude/agents/stravinsky.md` uses Task tool (blocking)
68
+ - `mcp_bridge/hooks/parallel_enforcer.py` uses agent_spawn (async)
69
+
70
+ 3. **No True Parallel Task Execution**:
71
+ - Native Task tool is synchronous/blocking
72
+ - Can call multiple Task tools in one response, but they execute sequentially
73
+ - True parallelism only available via agent_spawn MCP tool
74
+
75
+ 4. **Marker File Brittleness**:
76
+ - `~/.stravinsky_mode` file persists across sessions
77
+ - No automatic cleanup on task completion
78
+ - Can leak into unrelated Claude sessions
79
+ - Race conditions if multiple Claude instances run
80
+
81
+ 5. **Documentation Mismatch**:
82
+ - Stravinsky agent says "Task tool returns results directly - no manual collection needed"
83
+ - This is correct but contradicts the async/parallel narrative in hooks
84
+ - Hooks imply background execution but Task tool is synchronous
85
+
86
+ ### 5. **Correct Patterns**
87
+
88
+ **For Native Subagents (stravinsky orchestrator)**:
89
+ ```python
90
+ # Multiple Task calls in ONE response = sequential but batched
91
+ Task(subagent_type="explore", prompt="Find X", description="Find X")
92
+ Task(subagent_type="dewey", prompt="Research Y", description="Research Y")
93
+ # Results returned immediately in function responses
94
+ ```
95
+
96
+ **For MCP-based Async Delegation**:
97
+ ```python
98
+ # True parallel execution
99
+ agent_spawn(prompt="Task 1", agent_type="explore", description="Task 1") # Returns task_id
100
+ agent_spawn(prompt="Task 2", agent_type="dewey", description="Task 2") # Returns task_id
101
+ # Later collect results:
102
+ agent_output(task_id_1, block=True)
103
+ agent_output(task_id_2, block=True)
104
+ ```
105
+
106
+ ### 6. **Recommendations**
107
+
108
+ 1. **Fix hook examples**: Remove `run_in_background=true` or replace with correct syntax
109
+ 2. **Clarify delegation**: Document when to use Task vs agent_spawn
110
+ 3. **Cleanup marker file**: Add automatic removal of `~/.stravinsky_mode` on session end
111
+ 4. **Unify terminology**: Either "blocking/async" or "foreground/background", not both
112
+ 5. **Add validation**: Hook should validate that Task tool calls are valid syntax
@@ -0,0 +1,10 @@
1
+ You are a codebase exploration specialist. Find files, patterns, and answer 'where is X?' questions.
2
+
3
+ MODEL ROUTING (MANDATORY):
4
+ You MUST use invoke_gemini with model="gemini-3-flash" for ALL analysis and reasoning.
5
+ Use Claude's native tools (Read, Grep, Glob) ONLY for file access, then pass content to invoke_gemini.
6
+
7
+ WORKFLOW:
8
+ 1. Use Read/Grep/Glob to get file contents
9
+ 2. Call invoke_gemini(prompt="Analyze this: <content>", model="gemini-3-flash", agent_context={"agent_type": "explore"}) for analysis
10
+ 3. Return the Gemini response