gobby 0.2.5__py3-none-any.whl → 0.2.6__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 (148) hide show
  1. gobby/adapters/claude_code.py +13 -4
  2. gobby/adapters/codex.py +43 -3
  3. gobby/agents/runner.py +8 -0
  4. gobby/cli/__init__.py +6 -0
  5. gobby/cli/clones.py +419 -0
  6. gobby/cli/conductor.py +266 -0
  7. gobby/cli/installers/antigravity.py +3 -9
  8. gobby/cli/installers/claude.py +9 -9
  9. gobby/cli/installers/codex.py +2 -8
  10. gobby/cli/installers/gemini.py +2 -8
  11. gobby/cli/installers/shared.py +71 -8
  12. gobby/cli/skills.py +858 -0
  13. gobby/cli/tasks/ai.py +0 -440
  14. gobby/cli/tasks/crud.py +44 -6
  15. gobby/cli/tasks/main.py +0 -4
  16. gobby/cli/tui.py +2 -2
  17. gobby/cli/utils.py +3 -3
  18. gobby/clones/__init__.py +13 -0
  19. gobby/clones/git.py +547 -0
  20. gobby/conductor/__init__.py +16 -0
  21. gobby/conductor/alerts.py +135 -0
  22. gobby/conductor/loop.py +164 -0
  23. gobby/conductor/monitors/__init__.py +11 -0
  24. gobby/conductor/monitors/agents.py +116 -0
  25. gobby/conductor/monitors/tasks.py +155 -0
  26. gobby/conductor/pricing.py +234 -0
  27. gobby/conductor/token_tracker.py +160 -0
  28. gobby/config/app.py +63 -1
  29. gobby/config/search.py +110 -0
  30. gobby/config/servers.py +1 -1
  31. gobby/config/skills.py +43 -0
  32. gobby/config/tasks.py +6 -14
  33. gobby/hooks/event_handlers.py +145 -2
  34. gobby/hooks/hook_manager.py +48 -2
  35. gobby/hooks/skill_manager.py +130 -0
  36. gobby/install/claude/hooks/hook_dispatcher.py +4 -4
  37. gobby/install/codex/hooks/hook_dispatcher.py +1 -1
  38. gobby/install/gemini/hooks/hook_dispatcher.py +87 -12
  39. gobby/llm/claude.py +22 -34
  40. gobby/llm/claude_executor.py +46 -256
  41. gobby/llm/codex_executor.py +59 -291
  42. gobby/llm/executor.py +21 -0
  43. gobby/llm/gemini.py +134 -110
  44. gobby/llm/litellm_executor.py +143 -6
  45. gobby/llm/resolver.py +95 -33
  46. gobby/mcp_proxy/instructions.py +54 -0
  47. gobby/mcp_proxy/models.py +15 -0
  48. gobby/mcp_proxy/registries.py +68 -5
  49. gobby/mcp_proxy/server.py +33 -3
  50. gobby/mcp_proxy/services/tool_proxy.py +81 -1
  51. gobby/mcp_proxy/stdio.py +2 -1
  52. gobby/mcp_proxy/tools/__init__.py +0 -2
  53. gobby/mcp_proxy/tools/agent_messaging.py +317 -0
  54. gobby/mcp_proxy/tools/clones.py +903 -0
  55. gobby/mcp_proxy/tools/memory.py +1 -24
  56. gobby/mcp_proxy/tools/metrics.py +65 -1
  57. gobby/mcp_proxy/tools/orchestration/__init__.py +3 -0
  58. gobby/mcp_proxy/tools/orchestration/cleanup.py +151 -0
  59. gobby/mcp_proxy/tools/orchestration/wait.py +467 -0
  60. gobby/mcp_proxy/tools/session_messages.py +1 -2
  61. gobby/mcp_proxy/tools/skills/__init__.py +631 -0
  62. gobby/mcp_proxy/tools/task_orchestration.py +7 -0
  63. gobby/mcp_proxy/tools/task_readiness.py +14 -0
  64. gobby/mcp_proxy/tools/task_sync.py +1 -1
  65. gobby/mcp_proxy/tools/tasks/_context.py +0 -20
  66. gobby/mcp_proxy/tools/tasks/_crud.py +91 -4
  67. gobby/mcp_proxy/tools/tasks/_expansion.py +348 -0
  68. gobby/mcp_proxy/tools/tasks/_factory.py +6 -16
  69. gobby/mcp_proxy/tools/tasks/_lifecycle.py +60 -29
  70. gobby/mcp_proxy/tools/tasks/_lifecycle_validation.py +18 -29
  71. gobby/mcp_proxy/tools/workflows.py +1 -1
  72. gobby/mcp_proxy/tools/worktrees.py +5 -0
  73. gobby/memory/backends/__init__.py +6 -1
  74. gobby/memory/backends/mem0.py +6 -1
  75. gobby/memory/extractor.py +477 -0
  76. gobby/memory/manager.py +11 -2
  77. gobby/prompts/defaults/handoff/compact.md +63 -0
  78. gobby/prompts/defaults/handoff/session_end.md +57 -0
  79. gobby/prompts/defaults/memory/extract.md +61 -0
  80. gobby/runner.py +37 -16
  81. gobby/search/__init__.py +48 -6
  82. gobby/search/backends/__init__.py +159 -0
  83. gobby/search/backends/embedding.py +225 -0
  84. gobby/search/embeddings.py +238 -0
  85. gobby/search/models.py +148 -0
  86. gobby/search/unified.py +496 -0
  87. gobby/servers/http.py +23 -8
  88. gobby/servers/routes/admin.py +280 -0
  89. gobby/servers/routes/mcp/tools.py +241 -52
  90. gobby/servers/websocket.py +2 -2
  91. gobby/sessions/analyzer.py +2 -0
  92. gobby/sessions/transcripts/base.py +1 -0
  93. gobby/sessions/transcripts/claude.py +64 -5
  94. gobby/skills/__init__.py +91 -0
  95. gobby/skills/loader.py +685 -0
  96. gobby/skills/manager.py +384 -0
  97. gobby/skills/parser.py +258 -0
  98. gobby/skills/search.py +463 -0
  99. gobby/skills/sync.py +119 -0
  100. gobby/skills/updater.py +385 -0
  101. gobby/skills/validator.py +368 -0
  102. gobby/storage/clones.py +378 -0
  103. gobby/storage/database.py +1 -1
  104. gobby/storage/memories.py +43 -13
  105. gobby/storage/migrations.py +180 -6
  106. gobby/storage/sessions.py +73 -0
  107. gobby/storage/skills.py +749 -0
  108. gobby/storage/tasks/_crud.py +4 -4
  109. gobby/storage/tasks/_lifecycle.py +41 -6
  110. gobby/storage/tasks/_manager.py +14 -5
  111. gobby/storage/tasks/_models.py +8 -3
  112. gobby/sync/memories.py +39 -4
  113. gobby/sync/tasks.py +83 -6
  114. gobby/tasks/__init__.py +1 -2
  115. gobby/tasks/validation.py +24 -15
  116. gobby/tui/api_client.py +4 -7
  117. gobby/tui/app.py +5 -3
  118. gobby/tui/screens/orchestrator.py +1 -2
  119. gobby/tui/screens/tasks.py +2 -4
  120. gobby/tui/ws_client.py +1 -1
  121. gobby/utils/daemon_client.py +2 -2
  122. gobby/workflows/actions.py +84 -2
  123. gobby/workflows/context_actions.py +43 -0
  124. gobby/workflows/detection_helpers.py +115 -31
  125. gobby/workflows/engine.py +13 -2
  126. gobby/workflows/lifecycle_evaluator.py +29 -1
  127. gobby/workflows/loader.py +19 -6
  128. gobby/workflows/memory_actions.py +74 -0
  129. gobby/workflows/summary_actions.py +17 -0
  130. gobby/workflows/task_enforcement_actions.py +448 -6
  131. {gobby-0.2.5.dist-info → gobby-0.2.6.dist-info}/METADATA +82 -21
  132. {gobby-0.2.5.dist-info → gobby-0.2.6.dist-info}/RECORD +136 -107
  133. gobby/install/codex/prompts/forget.md +0 -7
  134. gobby/install/codex/prompts/memories.md +0 -7
  135. gobby/install/codex/prompts/recall.md +0 -7
  136. gobby/install/codex/prompts/remember.md +0 -13
  137. gobby/llm/gemini_executor.py +0 -339
  138. gobby/mcp_proxy/tools/task_expansion.py +0 -591
  139. gobby/tasks/context.py +0 -747
  140. gobby/tasks/criteria.py +0 -342
  141. gobby/tasks/expansion.py +0 -626
  142. gobby/tasks/prompts/expand.py +0 -327
  143. gobby/tasks/research.py +0 -421
  144. gobby/tasks/tdd.py +0 -352
  145. {gobby-0.2.5.dist-info → gobby-0.2.6.dist-info}/WHEEL +0 -0
  146. {gobby-0.2.5.dist-info → gobby-0.2.6.dist-info}/entry_points.txt +0 -0
  147. {gobby-0.2.5.dist-info → gobby-0.2.6.dist-info}/licenses/LICENSE.md +0 -0
  148. {gobby-0.2.5.dist-info → gobby-0.2.6.dist-info}/top_level.txt +0 -0
@@ -1,327 +0,0 @@
1
- """
2
- Expansion Prompt Builder.
3
-
4
- Handles the construction of system and user prompts for task expansion,
5
- instructing the agent to return structured JSON for subtask creation.
6
- """
7
-
8
- import logging
9
- from pathlib import Path
10
-
11
- from gobby.config.app import TaskExpansionConfig
12
- from gobby.prompts import PromptLoader
13
- from gobby.storage.tasks import Task
14
- from gobby.tasks.context import ExpansionContext
15
-
16
- logger = logging.getLogger(__name__)
17
-
18
- # JSON Schema for subtask output
19
- SUBTASK_SCHEMA = """
20
- {
21
- "subtasks": [
22
- {
23
- "title": "string (required) - Short, actionable title",
24
- "description": "string (optional) - Detailed description with implementation notes",
25
- "priority": "integer (optional) - 1=High, 2=Medium (default), 3=Low",
26
- "task_type": "string (optional) - task|bug|feature|epic (default: task)",
27
- "category": "string (required for actionable tasks) - code|config|docs|research|planning|manual (NOT test)",
28
- "validation": "string (optional) - Acceptance criteria with project commands",
29
- "depends_on": ["integer (optional) - Array of 0-based indices of subtasks this depends on"]
30
- }
31
- ]
32
- }
33
- """
34
-
35
- # Default System Prompt (Structured JSON output)
36
- DEFAULT_SYSTEM_PROMPT = """You are a senior technical project manager and architect.
37
- Your goal is to break down a high-level task into clear, actionable, and atomic subtasks.
38
-
39
- ## Output Format
40
-
41
- You MUST respond with a JSON object containing a "subtasks" array. Each subtask has:
42
-
43
- | Field | Type | Required | Description |
44
- |-------|------|----------|-------------|
45
- | title | string | Yes | Short, actionable title for the subtask |
46
- | description | string | No | Detailed description including implementation notes |
47
- | priority | integer | No | 1=High, 2=Medium (default), 3=Low |
48
- | task_type | string | No | "task" (default), "bug", "feature", "epic" |
49
- | category | string | Yes* | Task domain: code, config, docs, research, planning, manual (NOT test) |
50
- | validation | string | No | Acceptance criteria with project commands |
51
- | depends_on | array[int] | No | Indices (0-based) of subtasks this one depends on |
52
-
53
- *Required for actionable tasks. Use "planning" for epic/phase tasks.
54
-
55
- ## Category Values
56
-
57
- Choose the appropriate category for each subtask:
58
- - **code**: Implementation tasks (write/modify source code)
59
- - **config**: Configuration file changes (.yaml, .toml, .json, .env)
60
- - **docs**: Documentation tasks (README, docstrings, guides)
61
- - **refactor**: Refactoring tasks (updating existing code, including existing tests)
62
- - **research**: Investigation/exploration tasks
63
- - **planning**: Design/architecture tasks, parent phases
64
- - **manual**: Manual functional testing (observe output, verify behavior)
65
-
66
- NOTE: Do NOT use category "test" - TDD test tasks are created automatically.
67
- Use "refactor" for tasks that update existing test files to work with new code.
68
-
69
- ## Example Output
70
-
71
- ```json
72
- {
73
- "subtasks": [
74
- {
75
- "title": "Create database schema",
76
- "description": "Define tables for users, sessions, and permissions",
77
- "priority": 1,
78
- "category": "code",
79
- "validation": "Run migrations and verify tables exist with `{unit_tests}`"
80
- },
81
- {
82
- "title": "Implement data access layer",
83
- "description": "Create repository classes for CRUD operations",
84
- "depends_on": [0],
85
- "category": "code",
86
- "validation": "Unit tests for all repository methods pass"
87
- },
88
- {
89
- "title": "Add API endpoints",
90
- "description": "REST endpoints for user management",
91
- "depends_on": [1],
92
- "category": "code",
93
- "validation": "Integration tests for all endpoints pass"
94
- }
95
- ]
96
- }
97
- ```
98
-
99
- ## Dependency System
100
-
101
- Use `depends_on` to specify execution order:
102
- - Reference subtasks by their 0-based index in the array
103
- - A subtask with `depends_on: [0, 2]` requires subtasks 0 and 2 to complete first
104
- - Order your array logically - dependencies should come before dependents
105
-
106
- ## Rules
107
-
108
- 1. **Atomicity**: Each subtask should be small enough to be completed in one session (10-30 mins of work).
109
- 2. **Dependencies**: Use `depends_on` to enforce logical order (e.g., create file before importing it).
110
- 3. **Context Awareness**: Reference specific existing files or functions from the provided codebase context.
111
- 4. **Categories Required**: Every actionable subtask MUST have a category from the enum.
112
- 5. **Validation Criteria**: Include validation criteria for code/config tasks.
113
- 6. **Completeness**: The set of subtasks must fully accomplish the parent task.
114
- 7. **JSON Only**: Output ONLY valid JSON - no markdown, no explanation, no code blocks.
115
- 8. **No Scope Creep**: Do NOT include optional features, alternatives, or "nice-to-haves". Each subtask must be a concrete requirement from the parent task. Never invent additional features, suggest "consider also adding X", or include "(Optional)" sections. Implement exactly what is specified.
116
- 9. **NO TEST TASKS**: Do NOT create subtasks for writing tests. TDD is applied AUTOMATICALLY after expansion. Creating test tasks like "Write tests for X", "Add unit tests", "Create test file", "Verify with tests", or ANY task with category="test" will cause DUPLICATE test work. Only create implementation subtasks.
117
-
118
- ## Validation Criteria Rules
119
-
120
- For each subtask, generate PRECISE validation criteria in the `validation` field.
121
- Use the project's verification commands (provided in context) rather than hardcoded commands.
122
-
123
- ### 1. Measurable
124
- Use exact commands from project context, not vague descriptions.
125
-
126
- | BAD (Vague) | GOOD (Measurable) |
127
- |-------------|-------------------|
128
- | "Tests pass" | "`{unit_tests}` exits with code 0" |
129
- | "No type errors" | "`{type_check}` reports no errors" |
130
- | "Linting passes" | "`{lint}` exits with code 0" |
131
-
132
- ### 2. Specific
133
- Reference actual files and functions from the provided context.
134
-
135
- | BAD (Generic) | GOOD (Specific) |
136
- |---------------|-----------------|
137
- | "Function moved correctly" | "`ClassName` exists in `path/to/new/file.ext` with same signature" |
138
- | "Tests updated" | "`tests/module/test_file.ext` imports from new location" |
139
- | "Config added" | "`ConfigName` in `path/to/config.ext` has required fields" |
140
-
141
- ### 3. Verifiable
142
- Include commands that can be executed to verify completion.
143
-
144
- | BAD (Unverifiable) | GOOD (Verifiable) |
145
- |--------------------|-------------------|
146
- | "No regressions" | "No test files removed: `git diff --name-only HEAD~1 | grep -v test`" |
147
- | "Module importable" | "Import succeeds without errors in project's runtime" |
148
- | "File created" | "File exists at expected path with expected exports" |
149
-
150
- **Important:** Replace `{unit_tests}`, `{type_check}`, `{lint}` with actual commands from the Project Verification Commands section in the context.
151
- """
152
-
153
- # NOTE: TDD_MODE_INSTRUCTIONS removed - TDD is now applied automatically post-expansion
154
- # by _apply_tdd_sandwich() in task_expansion.py for non-epic code/config tasks
155
-
156
- # Default User Prompt Template
157
- DEFAULT_USER_PROMPT = """Analyze and expand this task into subtasks.
158
-
159
- ## Parent Task
160
- - **ID**: {task_id}
161
- - **Title**: {title}
162
- - **Description**: {description}
163
-
164
- ## Context
165
- {context_str}
166
-
167
- ## Research Findings
168
- {research_str}
169
-
170
- ## Instructions
171
-
172
- Return a JSON object with a "subtasks" array. Remember to:
173
- 1. Use `depends_on` with 0-based indices to specify dependencies
174
- 2. Include a category for each coding subtask
175
- 3. Order subtasks logically - dependencies before dependents
176
- 4. Output ONLY valid JSON - no markdown, no explanation
177
-
178
- Return the JSON now."""
179
-
180
-
181
- class ExpansionPromptBuilder:
182
- """Builds prompts for task expansion."""
183
-
184
- def __init__(self, config: TaskExpansionConfig, project_dir: Path | None = None):
185
- self.config = config
186
- self._loader = PromptLoader(project_dir=project_dir)
187
-
188
- # Register fallbacks for strangler fig pattern
189
- # NOTE: TDD is applied post-expansion, not in prompt
190
- self._loader.register_fallback("expansion/system", lambda: DEFAULT_SYSTEM_PROMPT)
191
- self._loader.register_fallback("expansion/user", lambda: DEFAULT_USER_PROMPT)
192
-
193
- def get_system_prompt(self, tdd_mode: bool = False) -> str:
194
- """
195
- Get the system prompt (from config, template file, or default).
196
-
197
- Precedence order:
198
- 1. Inline config (deprecated): config.system_prompt
199
- 2. Config path: config.system_prompt_path
200
- 3. Template file: expansion/system.md
201
- 4. Python constant fallback: DEFAULT_SYSTEM_PROMPT
202
-
203
- Args:
204
- tdd_mode: Deprecated, ignored. TDD is now applied post-expansion.
205
- """
206
- # 1. Inline config (deprecated, for backwards compatibility)
207
- if self.config.system_prompt:
208
- return self.config.system_prompt
209
-
210
- # 2. Config path or 3. Template file
211
- prompt_path = self.config.system_prompt_path or "expansion/system"
212
-
213
- try:
214
- # Pass empty context - tdd_mode no longer used in templates
215
- return self._loader.render(prompt_path, {})
216
- except FileNotFoundError:
217
- logger.debug(f"Prompt template '{prompt_path}' not found, using fallback")
218
- # 4. Python constant fallback
219
- return DEFAULT_SYSTEM_PROMPT
220
-
221
- def build_user_prompt(
222
- self,
223
- task: Task,
224
- context: ExpansionContext,
225
- user_instructions: str | None = None,
226
- ) -> str:
227
- """
228
- Build the user prompt by injecting context into the template.
229
-
230
- Precedence order:
231
- 1. Inline config (deprecated): config.prompt
232
- 2. Config path: config.prompt_path
233
- 3. Template file: expansion/user.md
234
- 4. Python constant fallback: DEFAULT_USER_PROMPT
235
- """
236
- # Check if using inline config (deprecated)
237
- use_legacy_template = self.config.prompt is not None
238
-
239
- # Format context string
240
- context_parts = []
241
- if context.relevant_files:
242
- context_parts.append("**Relevant Files:**")
243
- for f in context.relevant_files:
244
- context_parts.append(f"- {f}")
245
-
246
- if context.existing_tests:
247
- context_parts.append("\n**Existing Tests:**")
248
- for module, test_files in context.existing_tests.items():
249
- context_parts.append(f"- {module}:")
250
- for tf in test_files:
251
- context_parts.append(f" - {tf}")
252
- context_parts.append(
253
- "\n*Note: When creating test tasks for modules with existing tests, "
254
- "update the existing test files rather than creating new ones.*"
255
- )
256
-
257
- if context.function_signatures:
258
- context_parts.append("\n**Functions Being Modified:**")
259
- for file_path, signatures in context.function_signatures.items():
260
- context_parts.append(f"- {file_path}:")
261
- for sig in signatures:
262
- context_parts.append(f" - `{sig}`")
263
- context_parts.append(
264
- "\n*Note: Reference these signatures in validation criteria "
265
- "to ensure functions are preserved or properly refactored.*"
266
- )
267
-
268
- if context.verification_commands:
269
- context_parts.append("\n**Project Verification Commands:**")
270
- context_parts.append("Use these commands in validation criteria:")
271
- for name, cmd in context.verification_commands.items():
272
- context_parts.append(f"- `{{{name}}}` = `{cmd}`")
273
-
274
- if context.project_patterns:
275
- context_parts.append("\n**Project Patterns:**")
276
- for k, v in context.project_patterns.items():
277
- context_parts.append(f"- {k}: {v}")
278
-
279
- if context.related_tasks:
280
- context_parts.append("\n**Related Tasks:**")
281
- for t in context.related_tasks:
282
- context_parts.append(f"- {t.title} ({t.status})")
283
-
284
- if context.project_structure:
285
- context_parts.append("\n**Project Structure:**")
286
- context_parts.append(context.project_structure)
287
- context_parts.append(
288
- "\n*IMPORTANT: Use these actual paths when referencing files. "
289
- "Do NOT invent paths like 'gt/core/' or 'lib/utils/' - only use paths shown above.*"
290
- )
291
-
292
- context_str = (
293
- "\n".join(context_parts) if context_parts else "No additional context available."
294
- )
295
-
296
- # Format research findings
297
- research_str = context.agent_findings or "No research performed."
298
-
299
- # Build context for template rendering
300
- template_context = {
301
- "task_id": task.id,
302
- "title": task.title,
303
- "description": task.description or "",
304
- "context_str": context_str,
305
- "research_str": research_str,
306
- }
307
-
308
- # Render using appropriate method
309
- if use_legacy_template:
310
- # 1. Inline config (deprecated)
311
- template = self.config.prompt or DEFAULT_USER_PROMPT
312
- prompt = template.format(**template_context)
313
- else:
314
- # 2. Config path or 3. Template file
315
- prompt_path = self.config.prompt_path or "expansion/user"
316
- try:
317
- prompt = self._loader.render(prompt_path, template_context)
318
- except FileNotFoundError:
319
- logger.debug(f"Prompt template '{prompt_path}' not found, using fallback")
320
- # 4. Python constant fallback
321
- prompt = DEFAULT_USER_PROMPT.format(**template_context)
322
-
323
- # Append specific user instructions if provided
324
- if user_instructions:
325
- prompt += f"\n\n## Additional Instructions\n{user_instructions}"
326
-
327
- return prompt