shotgun-sh 0.1.14__py3-none-any.whl → 0.2.11__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.
Potentially problematic release.
This version of shotgun-sh might be problematic. Click here for more details.
- shotgun/agents/agent_manager.py +715 -75
- shotgun/agents/common.py +80 -75
- shotgun/agents/config/constants.py +21 -10
- shotgun/agents/config/manager.py +322 -97
- shotgun/agents/config/models.py +114 -84
- shotgun/agents/config/provider.py +232 -88
- shotgun/agents/context_analyzer/__init__.py +28 -0
- shotgun/agents/context_analyzer/analyzer.py +471 -0
- shotgun/agents/context_analyzer/constants.py +9 -0
- shotgun/agents/context_analyzer/formatter.py +115 -0
- shotgun/agents/context_analyzer/models.py +212 -0
- shotgun/agents/conversation_history.py +125 -2
- shotgun/agents/conversation_manager.py +57 -19
- shotgun/agents/export.py +6 -7
- shotgun/agents/history/compaction.py +10 -5
- shotgun/agents/history/context_extraction.py +93 -6
- shotgun/agents/history/history_processors.py +129 -12
- shotgun/agents/history/token_counting/__init__.py +31 -0
- shotgun/agents/history/token_counting/anthropic.py +127 -0
- shotgun/agents/history/token_counting/base.py +78 -0
- shotgun/agents/history/token_counting/openai.py +90 -0
- shotgun/agents/history/token_counting/sentencepiece_counter.py +127 -0
- shotgun/agents/history/token_counting/tokenizer_cache.py +92 -0
- shotgun/agents/history/token_counting/utils.py +144 -0
- shotgun/agents/history/token_estimation.py +12 -12
- shotgun/agents/llm.py +62 -0
- shotgun/agents/models.py +59 -4
- shotgun/agents/plan.py +6 -7
- shotgun/agents/research.py +7 -8
- shotgun/agents/specify.py +6 -7
- shotgun/agents/tasks.py +6 -7
- shotgun/agents/tools/__init__.py +0 -2
- shotgun/agents/tools/codebase/codebase_shell.py +6 -0
- shotgun/agents/tools/codebase/directory_lister.py +6 -0
- shotgun/agents/tools/codebase/file_read.py +11 -2
- shotgun/agents/tools/codebase/query_graph.py +6 -0
- shotgun/agents/tools/codebase/retrieve_code.py +6 -0
- shotgun/agents/tools/file_management.py +82 -16
- shotgun/agents/tools/registry.py +217 -0
- shotgun/agents/tools/web_search/__init__.py +55 -16
- shotgun/agents/tools/web_search/anthropic.py +76 -51
- shotgun/agents/tools/web_search/gemini.py +50 -27
- shotgun/agents/tools/web_search/openai.py +26 -17
- shotgun/agents/tools/web_search/utils.py +2 -2
- shotgun/agents/usage_manager.py +164 -0
- shotgun/api_endpoints.py +15 -0
- shotgun/cli/clear.py +53 -0
- shotgun/cli/compact.py +186 -0
- shotgun/cli/config.py +41 -67
- shotgun/cli/context.py +111 -0
- shotgun/cli/export.py +1 -1
- shotgun/cli/feedback.py +50 -0
- shotgun/cli/models.py +3 -2
- shotgun/cli/plan.py +1 -1
- shotgun/cli/research.py +1 -1
- shotgun/cli/specify.py +1 -1
- shotgun/cli/tasks.py +1 -1
- shotgun/cli/update.py +16 -2
- shotgun/codebase/core/change_detector.py +5 -3
- shotgun/codebase/core/code_retrieval.py +4 -2
- shotgun/codebase/core/ingestor.py +57 -16
- shotgun/codebase/core/manager.py +20 -7
- shotgun/codebase/core/nl_query.py +1 -1
- shotgun/codebase/models.py +4 -4
- shotgun/exceptions.py +32 -0
- shotgun/llm_proxy/__init__.py +19 -0
- shotgun/llm_proxy/clients.py +44 -0
- shotgun/llm_proxy/constants.py +15 -0
- shotgun/logging_config.py +18 -27
- shotgun/main.py +91 -12
- shotgun/posthog_telemetry.py +81 -10
- shotgun/prompts/agents/export.j2 +18 -1
- shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +5 -1
- shotgun/prompts/agents/partials/interactive_mode.j2 +24 -7
- shotgun/prompts/agents/plan.j2 +1 -1
- shotgun/prompts/agents/research.j2 +1 -1
- shotgun/prompts/agents/specify.j2 +270 -3
- shotgun/prompts/agents/state/system_state.j2 +4 -0
- shotgun/prompts/agents/tasks.j2 +1 -1
- shotgun/prompts/loader.py +2 -2
- shotgun/prompts/tools/web_search.j2 +14 -0
- shotgun/sentry_telemetry.py +27 -18
- shotgun/settings.py +238 -0
- shotgun/shotgun_web/__init__.py +19 -0
- shotgun/shotgun_web/client.py +138 -0
- shotgun/shotgun_web/constants.py +21 -0
- shotgun/shotgun_web/models.py +47 -0
- shotgun/telemetry.py +24 -36
- shotgun/tui/app.py +251 -23
- shotgun/tui/commands/__init__.py +1 -1
- shotgun/tui/components/context_indicator.py +179 -0
- shotgun/tui/components/mode_indicator.py +70 -0
- shotgun/tui/components/status_bar.py +48 -0
- shotgun/tui/containers.py +91 -0
- shotgun/tui/dependencies.py +39 -0
- shotgun/tui/protocols.py +45 -0
- shotgun/tui/screens/chat/__init__.py +5 -0
- shotgun/tui/screens/chat/chat.tcss +54 -0
- shotgun/tui/screens/chat/chat_screen.py +1234 -0
- shotgun/tui/screens/chat/codebase_index_prompt_screen.py +64 -0
- shotgun/tui/screens/chat/codebase_index_selection.py +12 -0
- shotgun/tui/screens/chat/help_text.py +40 -0
- shotgun/tui/screens/chat/prompt_history.py +48 -0
- shotgun/tui/screens/chat.tcss +11 -0
- shotgun/tui/screens/chat_screen/command_providers.py +226 -11
- shotgun/tui/screens/chat_screen/history/__init__.py +22 -0
- shotgun/tui/screens/chat_screen/history/agent_response.py +66 -0
- shotgun/tui/screens/chat_screen/history/chat_history.py +116 -0
- shotgun/tui/screens/chat_screen/history/formatters.py +115 -0
- shotgun/tui/screens/chat_screen/history/partial_response.py +43 -0
- shotgun/tui/screens/chat_screen/history/user_question.py +42 -0
- shotgun/tui/screens/confirmation_dialog.py +151 -0
- shotgun/tui/screens/feedback.py +193 -0
- shotgun/tui/screens/github_issue.py +102 -0
- shotgun/tui/screens/model_picker.py +352 -0
- shotgun/tui/screens/onboarding.py +431 -0
- shotgun/tui/screens/pipx_migration.py +153 -0
- shotgun/tui/screens/provider_config.py +156 -39
- shotgun/tui/screens/shotgun_auth.py +295 -0
- shotgun/tui/screens/welcome.py +198 -0
- shotgun/tui/services/__init__.py +5 -0
- shotgun/tui/services/conversation_service.py +184 -0
- shotgun/tui/state/__init__.py +7 -0
- shotgun/tui/state/processing_state.py +185 -0
- shotgun/tui/utils/mode_progress.py +14 -7
- shotgun/tui/widgets/__init__.py +5 -0
- shotgun/tui/widgets/widget_coordinator.py +262 -0
- shotgun/utils/datetime_utils.py +77 -0
- shotgun/utils/env_utils.py +13 -0
- shotgun/utils/file_system_utils.py +22 -2
- shotgun/utils/marketing.py +110 -0
- shotgun/utils/update_checker.py +69 -14
- shotgun_sh-0.2.11.dist-info/METADATA +130 -0
- shotgun_sh-0.2.11.dist-info/RECORD +194 -0
- {shotgun_sh-0.1.14.dist-info → shotgun_sh-0.2.11.dist-info}/entry_points.txt +1 -0
- {shotgun_sh-0.1.14.dist-info → shotgun_sh-0.2.11.dist-info}/licenses/LICENSE +1 -1
- shotgun/agents/history/token_counting.py +0 -429
- shotgun/agents/tools/user_interaction.py +0 -37
- shotgun/tui/screens/chat.py +0 -797
- shotgun/tui/screens/chat_screen/history.py +0 -350
- shotgun_sh-0.1.14.dist-info/METADATA +0 -466
- shotgun_sh-0.1.14.dist-info/RECORD +0 -133
- {shotgun_sh-0.1.14.dist-info → shotgun_sh-0.2.11.dist-info}/WHEEL +0 -0
shotgun/posthog_telemetry.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
"""PostHog analytics setup for Shotgun."""
|
|
2
2
|
|
|
3
|
+
from enum import StrEnum
|
|
3
4
|
from typing import Any
|
|
4
5
|
|
|
5
6
|
import posthog
|
|
7
|
+
from pydantic import BaseModel
|
|
6
8
|
|
|
7
9
|
from shotgun import __version__
|
|
8
10
|
from shotgun.agents.config import get_config_manager
|
|
11
|
+
from shotgun.agents.conversation_manager import ConversationManager
|
|
9
12
|
from shotgun.logging_config import get_early_logger
|
|
13
|
+
from shotgun.settings import settings
|
|
10
14
|
|
|
11
15
|
# Use early logger to prevent automatic StreamHandler creation
|
|
12
16
|
logger = get_early_logger(__name__)
|
|
@@ -29,10 +33,15 @@ def setup_posthog_observability() -> bool:
|
|
|
29
33
|
logger.debug("PostHog is already initialized, skipping")
|
|
30
34
|
return True
|
|
31
35
|
|
|
32
|
-
#
|
|
33
|
-
api_key =
|
|
36
|
+
# Get API key from settings (handles build constants + env vars automatically)
|
|
37
|
+
api_key = settings.telemetry.posthog_api_key
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
# If no API key is available, skip PostHog initialization
|
|
40
|
+
if not api_key:
|
|
41
|
+
logger.debug("No PostHog API key available, skipping initialization")
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
logger.debug("Using PostHog API key from settings")
|
|
36
45
|
|
|
37
46
|
# Determine environment based on version
|
|
38
47
|
# Dev versions contain "dev", "rc", "alpha", or "beta"
|
|
@@ -48,14 +57,16 @@ def setup_posthog_observability() -> bool:
|
|
|
48
57
|
# Store the client for later use
|
|
49
58
|
_posthog_client = posthog
|
|
50
59
|
|
|
51
|
-
# Set user context with anonymous
|
|
60
|
+
# Set user context with anonymous shotgun instance ID from config
|
|
52
61
|
try:
|
|
62
|
+
import asyncio
|
|
63
|
+
|
|
53
64
|
config_manager = get_config_manager()
|
|
54
|
-
|
|
65
|
+
shotgun_instance_id = asyncio.run(config_manager.get_shotgun_instance_id())
|
|
55
66
|
|
|
56
67
|
# Identify the user in PostHog
|
|
57
68
|
posthog.identify( # type: ignore[attr-defined]
|
|
58
|
-
distinct_id=
|
|
69
|
+
distinct_id=shotgun_instance_id,
|
|
59
70
|
properties={
|
|
60
71
|
"version": __version__,
|
|
61
72
|
"environment": environment,
|
|
@@ -66,7 +77,9 @@ def setup_posthog_observability() -> bool:
|
|
|
66
77
|
posthog.disabled = False
|
|
67
78
|
posthog.personal_api_key = None # Not needed for event tracking
|
|
68
79
|
|
|
69
|
-
logger.debug(
|
|
80
|
+
logger.debug(
|
|
81
|
+
"PostHog user identified with anonymous ID: %s", shotgun_instance_id
|
|
82
|
+
)
|
|
70
83
|
except Exception as e:
|
|
71
84
|
logger.warning("Failed to set user context: %s", e)
|
|
72
85
|
|
|
@@ -96,9 +109,11 @@ def track_event(event_name: str, properties: dict[str, Any] | None = None) -> No
|
|
|
96
109
|
return
|
|
97
110
|
|
|
98
111
|
try:
|
|
99
|
-
|
|
112
|
+
import asyncio
|
|
113
|
+
|
|
114
|
+
# Get shotgun instance ID for tracking
|
|
100
115
|
config_manager = get_config_manager()
|
|
101
|
-
|
|
116
|
+
shotgun_instance_id = asyncio.run(config_manager.get_shotgun_instance_id())
|
|
102
117
|
|
|
103
118
|
# Add version and environment to properties
|
|
104
119
|
if properties is None:
|
|
@@ -113,7 +128,7 @@ def track_event(event_name: str, properties: dict[str, Any] | None = None) -> No
|
|
|
113
128
|
|
|
114
129
|
# Track the event using PostHog's capture method
|
|
115
130
|
_posthog_client.capture(
|
|
116
|
-
distinct_id=
|
|
131
|
+
distinct_id=shotgun_instance_id, event=event_name, properties=properties
|
|
117
132
|
)
|
|
118
133
|
logger.debug("Tracked PostHog event: %s", event_name)
|
|
119
134
|
except Exception as e:
|
|
@@ -132,3 +147,59 @@ def shutdown() -> None:
|
|
|
132
147
|
logger.warning("Error shutting down PostHog: %s", e)
|
|
133
148
|
finally:
|
|
134
149
|
_posthog_client = None
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class FeedbackKind(StrEnum):
|
|
153
|
+
BUG = "bug"
|
|
154
|
+
FEATURE = "feature"
|
|
155
|
+
OTHER = "other"
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class Feedback(BaseModel):
|
|
159
|
+
kind: FeedbackKind
|
|
160
|
+
description: str
|
|
161
|
+
shotgun_instance_id: str
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
SURVEY_ID = "01999f81-9486-0000-4fa6-9632959f92f3"
|
|
165
|
+
Q_KIND_ID = "aaa5fcc3-88ba-4c24-bcf5-1481fd5efc2b"
|
|
166
|
+
Q_DESCRIPTION_ID = "a0ed6283-5d4b-452c-9160-6768d879db8a"
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def submit_feedback_survey(feedback: Feedback) -> None:
|
|
170
|
+
global _posthog_client
|
|
171
|
+
if _posthog_client is None:
|
|
172
|
+
logger.debug("PostHog not initialized, skipping feedback survey")
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
import asyncio
|
|
176
|
+
|
|
177
|
+
config_manager = get_config_manager()
|
|
178
|
+
config = asyncio.run(config_manager.load())
|
|
179
|
+
conversation_manager = ConversationManager()
|
|
180
|
+
conversation = None
|
|
181
|
+
try:
|
|
182
|
+
conversation = asyncio.run(conversation_manager.load())
|
|
183
|
+
except Exception as e:
|
|
184
|
+
logger.debug(f"Failed to load conversation history: {e}")
|
|
185
|
+
last_10_messages = []
|
|
186
|
+
if conversation is not None:
|
|
187
|
+
last_10_messages = conversation.get_agent_messages()[:10]
|
|
188
|
+
|
|
189
|
+
track_event(
|
|
190
|
+
"survey sent",
|
|
191
|
+
properties={
|
|
192
|
+
"$survey_id": SURVEY_ID,
|
|
193
|
+
"$survey_questions": [
|
|
194
|
+
{"id": Q_KIND_ID, "question": "Feedback type"},
|
|
195
|
+
{"id": Q_DESCRIPTION_ID, "question": "Feedback description"},
|
|
196
|
+
],
|
|
197
|
+
f"$survey_response_{Q_KIND_ID}": feedback.kind,
|
|
198
|
+
f"$survey_response_{Q_DESCRIPTION_ID}": feedback.description,
|
|
199
|
+
"selected_model": config.selected_model.value
|
|
200
|
+
if config.selected_model
|
|
201
|
+
else None,
|
|
202
|
+
"config_version": config.config_version,
|
|
203
|
+
"last_10_messages": last_10_messages, # last 10 messages
|
|
204
|
+
},
|
|
205
|
+
)
|
shotgun/prompts/agents/export.j2
CHANGED
|
@@ -124,6 +124,7 @@ content_tasks = read_file('tasks.md') # Read implementation details
|
|
|
124
124
|
- `plan.md` - Extract development approach and stages
|
|
125
125
|
- `tasks.md` - Understand implementation tasks and structure
|
|
126
126
|
2. **Map content to agents.md standard sections**:
|
|
127
|
+
- **Research, Specifications, and Planning**: ALWAYS include this section first. Check which pipeline files exist in `.shotgun/` (research.md, specification.md, plan.md, tasks.md) and list only the ones that exist. If none exist, omit this section.
|
|
127
128
|
- **Project Overview**: Brief description and key technologies from specification.md
|
|
128
129
|
- **Dev Environment Setup**: Installation, dependencies, dev server commands
|
|
129
130
|
- **Code Style Guidelines**: Coding conventions and patterns from research.md
|
|
@@ -170,6 +171,14 @@ For additional specialized exports (only if specifically requested):
|
|
|
170
171
|
<CORRECT_CONTENT_TEMPLATE>
|
|
171
172
|
# Agents.md - [Project Name]
|
|
172
173
|
|
|
174
|
+
## Research, Specifications, and Planning
|
|
175
|
+
|
|
176
|
+
The `.shotgun/` folder contains background research, specifications, and implementation planning files. Refer to these files for additional context:
|
|
177
|
+
- `research.md` - Codebase analysis and research findings
|
|
178
|
+
- `specification.md` - Project requirements and specifications
|
|
179
|
+
- `plan.md` - Development plan and implementation approach
|
|
180
|
+
- `tasks.md` - Task breakdown and implementation progress
|
|
181
|
+
|
|
173
182
|
## Project Overview
|
|
174
183
|
- Brief description of what the project does
|
|
175
184
|
- Key technologies and frameworks used
|
|
@@ -253,6 +262,14 @@ This project is about [making assumptions without reading files]...
|
|
|
253
262
|
<GOOD_CONTENT_EXAMPLE>
|
|
254
263
|
# Agents.md - E-commerce API Project
|
|
255
264
|
|
|
265
|
+
## Research, Specifications, and Planning
|
|
266
|
+
|
|
267
|
+
The `.shotgun/` folder contains background research, specifications, and implementation planning files. Refer to these files for additional context:
|
|
268
|
+
- `research.md` - Codebase analysis and research findings
|
|
269
|
+
- `specification.md` - Project requirements and specifications
|
|
270
|
+
- `plan.md` - Development plan and implementation approach
|
|
271
|
+
- `tasks.md` - Task breakdown and implementation progress
|
|
272
|
+
|
|
256
273
|
## Project Overview
|
|
257
274
|
- REST API for product catalog management with authentication
|
|
258
275
|
- Built with Python/FastAPI for high performance async operations
|
|
@@ -316,7 +333,7 @@ This project is about [making assumptions without reading files]...
|
|
|
316
333
|
USER INTERACTION - CLARIFY EXPORT REQUIREMENTS:
|
|
317
334
|
|
|
318
335
|
- ALWAYS ask clarifying questions when export requirements are unclear
|
|
319
|
-
- Use
|
|
336
|
+
- Use clarifying questions to gather specific details about:
|
|
320
337
|
- Target format and file type preferences
|
|
321
338
|
- Intended use case and audience for the export
|
|
322
339
|
- Specific content sections to include/exclude from files
|
|
@@ -7,7 +7,10 @@ Your extensive expertise spans, among other things:
|
|
|
7
7
|
## KEY RULES
|
|
8
8
|
|
|
9
9
|
{% if interactive_mode %}
|
|
10
|
-
0. Always ask CLARIFYING QUESTIONS if the user's request is ambiguous or lacks sufficient detail.
|
|
10
|
+
0. Always ask CLARIFYING QUESTIONS using structured output if the user's request is ambiguous or lacks sufficient detail.
|
|
11
|
+
- Return your response with the clarifying_questions field populated
|
|
12
|
+
- Do not make assumptions about what the user wants
|
|
13
|
+
- Questions should be clear, specific, and answerable
|
|
11
14
|
{% endif %}
|
|
12
15
|
1. Above all, prefer using tools to do the work and NEVER respond with text.
|
|
13
16
|
2. IMPORTANT: Always ask for review and go ahead to move forward after using write_file().
|
|
@@ -20,6 +23,7 @@ Your extensive expertise spans, among other things:
|
|
|
20
23
|
9. **Be Creative**: If the user seems not to know something, always be creative and come up with ideas that fit their thinking.
|
|
21
24
|
10. Greet the user when you're just starting to work.
|
|
22
25
|
11. DO NOT repeat yourself.
|
|
26
|
+
12. If a user has agreed to a plan, you DO NOT NEED TO FOLLOW UP with them after every step to ask "is this search query ok?".
|
|
23
27
|
|
|
24
28
|
|
|
25
29
|
## Quality Standards
|
|
@@ -6,20 +6,37 @@
|
|
|
6
6
|
{% if interactive_mode -%}
|
|
7
7
|
IMPORTANT: USER INTERACTION IS ENABLED (interactive mode).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
## Structured Output Format
|
|
10
|
+
|
|
11
|
+
You must return responses using this structured format:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"response": "Your main response text here",
|
|
16
|
+
"clarifying_questions": ["Question 1?", "Question 2?"] // Optional, only when needed
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## When to Use Clarifying Questions
|
|
21
|
+
|
|
22
|
+
- BEFORE GETTING TO WORK: If the user's request is ambiguous, use clarifying_questions to ask what they want
|
|
23
|
+
- DURING WORK: After using write_file(), you can suggest that the user review it and ask any clarifying questions with clarifying_questions
|
|
12
24
|
- Don't assume - ask for confirmation of your understanding
|
|
13
|
-
- When in doubt about any aspect of the goal,
|
|
25
|
+
- When in doubt about any aspect of the goal, include clarifying_questions
|
|
26
|
+
|
|
27
|
+
## Important Notes
|
|
28
|
+
|
|
29
|
+
- If you don't need to ask questions, set clarifying_questions to null or omit it
|
|
30
|
+
- Keep response field concise - a paragraph at most for user communication
|
|
31
|
+
- Questions should be clear, specific, and independently answerable
|
|
32
|
+
- Don't ask multiple questions in one string - use separate array items
|
|
14
33
|
|
|
15
34
|
{% else -%}
|
|
16
35
|
|
|
17
36
|
IMPORTANT: USER INTERACTION IS DISABLED (non-interactive mode).
|
|
18
|
-
- You cannot ask clarifying questions
|
|
37
|
+
- You cannot ask clarifying questions (clarifying_questions will be ignored)
|
|
19
38
|
- Make reasonable assumptions based on best practices
|
|
20
39
|
- Use sensible defaults when information is missing
|
|
21
|
-
- Make reasonable assumptions based on industry best practices
|
|
22
|
-
- Use sensible defaults when specific details are not provided
|
|
23
40
|
- When in doubt, make reasonable assumptions and proceed with best practices
|
|
24
41
|
{% endif %}
|
|
25
42
|
|
shotgun/prompts/agents/plan.j2
CHANGED
|
@@ -118,7 +118,7 @@ USER INTERACTION - REDUCE UNCERTAINTY:
|
|
|
118
118
|
- FIRST read `research.md` and `specification.md` before asking ANY questions
|
|
119
119
|
- ONLY ask clarifying questions AFTER reading the context files
|
|
120
120
|
- Questions should be about gaps not covered in research/specification
|
|
121
|
-
- Use
|
|
121
|
+
- Use clarifying questions to gather specific details about:
|
|
122
122
|
- Information not found in the context files
|
|
123
123
|
- Clarifications on ambiguous specifications
|
|
124
124
|
- Priorities when multiple options exist
|
|
@@ -39,7 +39,7 @@ For research tasks:
|
|
|
39
39
|
## RESEARCH PRINCIPLES
|
|
40
40
|
|
|
41
41
|
{% if interactive_mode -%}
|
|
42
|
-
- CRITICAL: BEFORE RUNNING ANY SEARCH TOOL, ASK THE USER FOR APPROVAL
|
|
42
|
+
- CRITICAL: BEFORE RUNNING ANY SEARCH TOOL, ASK THE USER FOR APPROVAL using clarifying questions. Include what you plan to search for and ask if they want you to proceed.
|
|
43
43
|
{% endif -%}
|
|
44
44
|
- Build upon existing research rather than starting from scratch
|
|
45
45
|
- Focus on practical, actionable information over theoretical concepts
|
|
@@ -8,14 +8,281 @@ Transform requirements into detailed, actionable specifications that development
|
|
|
8
8
|
|
|
9
9
|
## MEMORY MANAGEMENT PROTOCOL
|
|
10
10
|
|
|
11
|
-
- You have exclusive write access to: `specification.md`
|
|
11
|
+
- You have exclusive write access to: `specification.md` and `.shotgun/contracts/*`
|
|
12
12
|
- SHOULD READ `research.md` for context but CANNOT write to it
|
|
13
|
-
-
|
|
13
|
+
- **specification.md is for PROSE ONLY** - no code, no implementation details, no type definitions
|
|
14
|
+
- **All code goes in .shotgun/contracts/** - types, interfaces, schemas
|
|
15
|
+
- specification.md describes WHAT and WHY, contracts/ show HOW with actual code
|
|
16
|
+
- This is your persistent memory store - ALWAYS load specification.md first
|
|
14
17
|
- Compress content regularly to stay within context limits
|
|
15
|
-
- Keep your
|
|
18
|
+
- Keep your files updated as you work - they're your memory across sessions
|
|
16
19
|
- When adding new specifications, review and consolidate overlapping requirements
|
|
17
20
|
- Structure specifications for easy reference by the next agents
|
|
18
21
|
|
|
22
|
+
## WHAT GOES IN SPECIFICATION.MD
|
|
23
|
+
|
|
24
|
+
specification.md is your prose documentation file. It should contain:
|
|
25
|
+
|
|
26
|
+
**INCLUDE in specification.md:**
|
|
27
|
+
- Requirements and business context (what needs to be built and why)
|
|
28
|
+
- Architecture overview and system design decisions
|
|
29
|
+
- Component descriptions and how they interact
|
|
30
|
+
- User workflows and use cases
|
|
31
|
+
- Directory structure as succinct prose (e.g., "src/ contains main code, tests/ contains test files")
|
|
32
|
+
- Dependencies listed in prose (e.g., "Requires TypeScript 5.0+, React 18, and PostgreSQL")
|
|
33
|
+
- Configuration requirements described (e.g., "App needs database URL and API key in environment")
|
|
34
|
+
- Testing strategies and acceptance criteria
|
|
35
|
+
- References to contract files (e.g., "See contracts/user_models.py for User type definition")
|
|
36
|
+
|
|
37
|
+
**DO NOT INCLUDE in specification.md:**
|
|
38
|
+
- Code blocks, type definitions, or function signatures (those go in contracts/)
|
|
39
|
+
- Implementation details or algorithms (describe behavior instead)
|
|
40
|
+
- Actual configuration files or build manifests (describe what's needed instead)
|
|
41
|
+
- Directory trees or file listings (keep structure descriptions succinct)
|
|
42
|
+
|
|
43
|
+
**When you need to show structure:** Reference contract files instead of inline code.
|
|
44
|
+
Example: "User authentication uses OAuth2. See contracts/auth_types.ts for AuthUser and AuthToken types."
|
|
45
|
+
|
|
46
|
+
## CONTRACT FILES
|
|
47
|
+
|
|
48
|
+
Contract files define the **interfaces and types** that form contracts between components.
|
|
49
|
+
They contain actual code that shows structure, not prose descriptions.
|
|
50
|
+
|
|
51
|
+
**ONLY put these in `.shotgun/contracts/` (language-agnostic):**
|
|
52
|
+
- **Type definitions ONLY** - Shape and structure, NO behavior or logic:
|
|
53
|
+
- Python: Pydantic models, dataclasses, `typing.Protocol` classes (interface definitions)
|
|
54
|
+
- TypeScript: interfaces, type aliases
|
|
55
|
+
- Rust: struct definitions
|
|
56
|
+
- Java: interfaces, POJOs
|
|
57
|
+
- C++: header files with class/struct declarations
|
|
58
|
+
- Go: interface types, struct definitions
|
|
59
|
+
- **Schema definitions**: API contracts and data schemas
|
|
60
|
+
- OpenAPI/Swagger specs (openapi.json, openapi.yaml)
|
|
61
|
+
- JSON Schema definitions
|
|
62
|
+
- GraphQL schemas
|
|
63
|
+
- Protobuf definitions
|
|
64
|
+
- **Protocol/Interface classes**: Pure interface definitions with method signatures only
|
|
65
|
+
- Python: `class Storage(Protocol): def save(self, data: str) -> None: ...`
|
|
66
|
+
- Use `...` (Ellipsis) for protocol methods, NOT `pass`
|
|
67
|
+
|
|
68
|
+
**NEVER put these in `.shotgun/contracts/` - NO EXECUTABLE CODE:**
|
|
69
|
+
- ❌ **Functions or methods with implementations** (even with `pass` or empty bodies)
|
|
70
|
+
- ❌ **Helper functions** with any logic whatsoever
|
|
71
|
+
- ❌ **Classes with method implementations** (use Protocol classes instead)
|
|
72
|
+
- ❌ **Standalone functions** like `def main(): pass` or `def validate_input(x): ...`
|
|
73
|
+
- ❌ **Code with behavior**: loops, conditionals, data manipulation, computations
|
|
74
|
+
- ❌ **Data constants**: dictionaries, lists, or any runtime values
|
|
75
|
+
- ❌ **`if __name__ == "__main__":` blocks** or any executable code
|
|
76
|
+
- Build/dependency configs (pyproject.toml, package.json, Cargo.toml, requirements.txt)
|
|
77
|
+
- Directory structure files (directory_structure.txt)
|
|
78
|
+
- Configuration templates (.env, config.yaml, example configs)
|
|
79
|
+
- Documentation or markdown files
|
|
80
|
+
- SQL migration files or database dumps
|
|
81
|
+
|
|
82
|
+
**These belong in specification.md instead:**
|
|
83
|
+
- Directory structure (as succinct prose: "src/ contains modules, tests/ has unit tests")
|
|
84
|
+
- Dependencies (as prose: "Requires Rust 1.70+, tokio, serde")
|
|
85
|
+
- Configuration needs (describe: "App needs DB_URL and API_KEY environment variables")
|
|
86
|
+
|
|
87
|
+
**Guidelines for contract files:**
|
|
88
|
+
- Keep each file focused on a single domain (e.g., user_types.ts, payment_models.py)
|
|
89
|
+
- Reference from specification.md: "See contracts/user_types.ts for User and Profile types"
|
|
90
|
+
- Use descriptive filenames: `auth_models.py`, `api_spec.json`, `database_types.rs`
|
|
91
|
+
- Keep files under 500 lines to avoid truncation
|
|
92
|
+
- When contracts grow large, split into focused files
|
|
93
|
+
|
|
94
|
+
**Example workflow:**
|
|
95
|
+
1. In specification.md: "Authentication system with JWT tokens. See contracts/auth_types.ts for types."
|
|
96
|
+
2. Create contract file: `write_file("contracts/auth_types.ts", content)` with actual TypeScript interfaces
|
|
97
|
+
3. Create contract file: `write_file("contracts/auth_api.json", content)` with actual OpenAPI spec
|
|
98
|
+
4. Coding agents can directly use these contracts to implement features
|
|
99
|
+
|
|
100
|
+
## HOW TO WRITE CONTRACT FILES
|
|
101
|
+
|
|
102
|
+
**CRITICAL - Always use correct file paths with write_file():**
|
|
103
|
+
|
|
104
|
+
Your working directory is `.shotgun/`, so paths should be relative to that directory.
|
|
105
|
+
|
|
106
|
+
<GOOD_EXAMPLES>
|
|
107
|
+
✅ `write_file("contracts/user_models.py", content)` - Correct path for Python models
|
|
108
|
+
✅ `write_file("contracts/auth_types.ts", content)` - Correct path for TypeScript types
|
|
109
|
+
✅ `write_file("contracts/api_spec.json", content)` - Correct path for OpenAPI spec
|
|
110
|
+
✅ `write_file("contracts/payment_service.rs", content)` - Correct path for Rust code
|
|
111
|
+
</GOOD_EXAMPLES>
|
|
112
|
+
|
|
113
|
+
<BAD_EXAMPLES>
|
|
114
|
+
❌ `write_file(".shotgun/contracts/user_models.py", content)` - WRONG! Don't include .shotgun/ prefix
|
|
115
|
+
❌ `write_file("contracts/directory_structure.txt", content)` - WRONG! No documentation files
|
|
116
|
+
❌ `write_file("contracts/pyproject.toml", content)` - WRONG! No build configs in contracts/
|
|
117
|
+
❌ `write_file("contracts/requirements.txt", content)` - WRONG! No dependency lists in contracts/
|
|
118
|
+
❌ `write_file("contracts/config.yaml", content)` - WRONG! No config templates in contracts/
|
|
119
|
+
</BAD_EXAMPLES>
|
|
120
|
+
|
|
121
|
+
**Path format rule:** Always use `contracts/filename.ext`, never `.shotgun/contracts/filename.ext`
|
|
122
|
+
|
|
123
|
+
**Language-specific examples:**
|
|
124
|
+
|
|
125
|
+
<PYTHON_EXAMPLE>
|
|
126
|
+
# Python Pydantic model contract
|
|
127
|
+
from pydantic import BaseModel, Field
|
|
128
|
+
from typing import Optional
|
|
129
|
+
|
|
130
|
+
class User(BaseModel):
|
|
131
|
+
"""User model contract."""
|
|
132
|
+
id: int
|
|
133
|
+
email: str = Field(..., description="User email address")
|
|
134
|
+
username: str
|
|
135
|
+
is_active: bool = True
|
|
136
|
+
role: Optional[str] = None
|
|
137
|
+
|
|
138
|
+
# Save as: write_file("contracts/user_models.py", content)
|
|
139
|
+
</PYTHON_EXAMPLE>
|
|
140
|
+
|
|
141
|
+
<TYPESCRIPT_EXAMPLE>
|
|
142
|
+
// TypeScript interface contract
|
|
143
|
+
interface User {
|
|
144
|
+
id: number;
|
|
145
|
+
email: string;
|
|
146
|
+
username: string;
|
|
147
|
+
isActive: boolean;
|
|
148
|
+
role?: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface AuthToken {
|
|
152
|
+
token: string;
|
|
153
|
+
expiresAt: Date;
|
|
154
|
+
userId: number;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Save as: write_file("contracts/auth_types.ts", content)
|
|
158
|
+
</TYPESCRIPT_EXAMPLE>
|
|
159
|
+
|
|
160
|
+
<RUST_EXAMPLE>
|
|
161
|
+
// Rust struct contract
|
|
162
|
+
use serde::{Deserialize, Serialize};
|
|
163
|
+
|
|
164
|
+
#[derive(Debug, Serialize, Deserialize)]
|
|
165
|
+
pub struct User {
|
|
166
|
+
pub id: u64,
|
|
167
|
+
pub email: String,
|
|
168
|
+
pub username: String,
|
|
169
|
+
pub is_active: bool,
|
|
170
|
+
pub role: Option<String>,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Save as: write_file("contracts/user_types.rs", content)
|
|
174
|
+
</RUST_EXAMPLE>
|
|
175
|
+
|
|
176
|
+
<OPENAPI_EXAMPLE>
|
|
177
|
+
{
|
|
178
|
+
"openapi": "3.0.0",
|
|
179
|
+
"info": {
|
|
180
|
+
"title": "User API",
|
|
181
|
+
"version": "1.0.0"
|
|
182
|
+
},
|
|
183
|
+
"paths": {
|
|
184
|
+
"/users": {
|
|
185
|
+
"get": {
|
|
186
|
+
"summary": "List users",
|
|
187
|
+
"responses": {
|
|
188
|
+
"200": {
|
|
189
|
+
"description": "Successful response",
|
|
190
|
+
"content": {
|
|
191
|
+
"application/json": {
|
|
192
|
+
"schema": {
|
|
193
|
+
"type": "array",
|
|
194
|
+
"items": { "$ref": "#/components/schemas/User" }
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
"components": {
|
|
204
|
+
"schemas": {
|
|
205
|
+
"User": {
|
|
206
|
+
"type": "object",
|
|
207
|
+
"properties": {
|
|
208
|
+
"id": { "type": "integer" },
|
|
209
|
+
"email": { "type": "string" },
|
|
210
|
+
"username": { "type": "string" }
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Save as: write_file("contracts/user_api.json", content)
|
|
218
|
+
</OPENAPI_EXAMPLE>
|
|
219
|
+
|
|
220
|
+
## WHAT IS ALLOWED vs WHAT IS FORBIDDEN
|
|
221
|
+
|
|
222
|
+
**✅ ALLOWED - Type Definitions (Shape and Structure):**
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
# ✅ GOOD: Pydantic model (type definition)
|
|
226
|
+
from pydantic import BaseModel
|
|
227
|
+
|
|
228
|
+
class User(BaseModel):
|
|
229
|
+
id: int
|
|
230
|
+
email: str
|
|
231
|
+
username: str
|
|
232
|
+
|
|
233
|
+
# ✅ GOOD: Protocol class (interface definition)
|
|
234
|
+
from typing import Protocol
|
|
235
|
+
|
|
236
|
+
class Storage(Protocol):
|
|
237
|
+
def save(self, data: str) -> None: ...
|
|
238
|
+
def load(self) -> str: ...
|
|
239
|
+
|
|
240
|
+
# ✅ GOOD: Type aliases and enums
|
|
241
|
+
from typing import Literal
|
|
242
|
+
from enum import Enum
|
|
243
|
+
|
|
244
|
+
UserRole = Literal["admin", "user", "guest"]
|
|
245
|
+
|
|
246
|
+
class Status(Enum):
|
|
247
|
+
ACTIVE = "active"
|
|
248
|
+
INACTIVE = "inactive"
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**❌ FORBIDDEN - Executable Code (Behavior and Logic):**
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
# ❌ BAD: Function with pass (executable code)
|
|
255
|
+
def main() -> int:
|
|
256
|
+
pass
|
|
257
|
+
|
|
258
|
+
# ❌ BAD: Function with implementation
|
|
259
|
+
def validate_input(x: str) -> str:
|
|
260
|
+
return x.strip()
|
|
261
|
+
|
|
262
|
+
# ❌ BAD: Class with method implementations
|
|
263
|
+
class HistoryManager:
|
|
264
|
+
def __init__(self):
|
|
265
|
+
pass
|
|
266
|
+
|
|
267
|
+
def add_message(self, msg: str):
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
# ❌ BAD: Data constants (runtime values)
|
|
271
|
+
SUPPORTED_PROVIDERS = [
|
|
272
|
+
{"name": "openai", "key": "OPENAI_API_KEY"}
|
|
273
|
+
]
|
|
274
|
+
|
|
275
|
+
# ❌ BAD: Helper functions
|
|
276
|
+
def get_default_config() -> dict:
|
|
277
|
+
return {"model": "gpt-4"}
|
|
278
|
+
|
|
279
|
+
# ❌ BAD: Executable code blocks
|
|
280
|
+
if __name__ == "__main__":
|
|
281
|
+
main()
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Remember**: Contracts define **SHAPES** (types, interfaces, schemas), NOT **BEHAVIOR** (functions, logic, implementations).
|
|
285
|
+
|
|
19
286
|
## AI AGENT PIPELINE AWARENESS
|
|
20
287
|
|
|
21
288
|
**CRITICAL**: Your output will be consumed by AI coding agents (Claude Code, Cursor, Windsurf, etc.)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
## System Status
|
|
2
2
|
|
|
3
|
+
Your training data may be old. The current date and time is: {{ current_datetime }} in {{ timezone_name }} (UTC{{ utc_offset }})
|
|
4
|
+
|
|
3
5
|
{% include 'agents/state/codebase/codebase_graphs_available.j2' %}
|
|
4
6
|
|
|
5
7
|
## Available Files
|
|
@@ -20,6 +22,8 @@ No files currently exist in your allowed directories. You can create:
|
|
|
20
22
|
- `exports/` folder - For exported documents
|
|
21
23
|
{% endif %}
|
|
22
24
|
|
|
25
|
+
When updating a file try to add into the footer that this was created using Shotgun (https://shotgun.sh).
|
|
26
|
+
|
|
23
27
|
{% if markdown_toc %}
|
|
24
28
|
## Document Table of Contents - READ THE ENTIRE FILE TO UNDERSTAND MORE
|
|
25
29
|
|
shotgun/prompts/agents/tasks.j2
CHANGED
|
@@ -99,7 +99,7 @@ Then organize tasks into logical sections:
|
|
|
99
99
|
USER INTERACTION - ASK CLARIFYING QUESTIONS:
|
|
100
100
|
|
|
101
101
|
- ALWAYS ask clarifying questions when the request is vague or ambiguous
|
|
102
|
-
- Use
|
|
102
|
+
- Use clarifying questions to gather specific details about:
|
|
103
103
|
- Specific features or functionality to prioritize
|
|
104
104
|
- Technical constraints or preferences
|
|
105
105
|
- Timeline and resource constraints
|
shotgun/prompts/loader.py
CHANGED
|
@@ -5,7 +5,7 @@ from datetime import datetime
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
-
from jinja2 import Environment, FileSystemLoader, Template
|
|
8
|
+
from jinja2 import Environment, FileSystemLoader, Template
|
|
9
9
|
|
|
10
10
|
from shotgun.logging_config import setup_logger
|
|
11
11
|
|
|
@@ -32,7 +32,7 @@ class PromptLoader:
|
|
|
32
32
|
self.templates_dir = templates_dir
|
|
33
33
|
self.env = Environment(
|
|
34
34
|
loader=FileSystemLoader(str(templates_dir)),
|
|
35
|
-
autoescape=
|
|
35
|
+
autoescape=False, # noqa: S701 - These are LLM prompts, not HTML
|
|
36
36
|
trim_blocks=True,
|
|
37
37
|
lstrip_blocks=True,
|
|
38
38
|
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Your training data may be old. The current date and time is: {{ current_datetime }} ({{ timezone_name }}, {{ utc_offset }})
|
|
2
|
+
|
|
3
|
+
Please provide current and accurate information about the following query:
|
|
4
|
+
|
|
5
|
+
Query: {{ query }}
|
|
6
|
+
|
|
7
|
+
Instructions:
|
|
8
|
+
- Provide comprehensive, factual information
|
|
9
|
+
- Include relevant details and context
|
|
10
|
+
- Focus on current and recent information
|
|
11
|
+
- Be specific and accurate in your response
|
|
12
|
+
- You can't ask the user for details, so assume the most relevant details for the query
|
|
13
|
+
|
|
14
|
+
ALWAYS PROVIDE THE SOURCES (urls) TO BACK UP THE INFORMATION YOU PROVIDE.
|