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.

Files changed (143) hide show
  1. shotgun/agents/agent_manager.py +715 -75
  2. shotgun/agents/common.py +80 -75
  3. shotgun/agents/config/constants.py +21 -10
  4. shotgun/agents/config/manager.py +322 -97
  5. shotgun/agents/config/models.py +114 -84
  6. shotgun/agents/config/provider.py +232 -88
  7. shotgun/agents/context_analyzer/__init__.py +28 -0
  8. shotgun/agents/context_analyzer/analyzer.py +471 -0
  9. shotgun/agents/context_analyzer/constants.py +9 -0
  10. shotgun/agents/context_analyzer/formatter.py +115 -0
  11. shotgun/agents/context_analyzer/models.py +212 -0
  12. shotgun/agents/conversation_history.py +125 -2
  13. shotgun/agents/conversation_manager.py +57 -19
  14. shotgun/agents/export.py +6 -7
  15. shotgun/agents/history/compaction.py +10 -5
  16. shotgun/agents/history/context_extraction.py +93 -6
  17. shotgun/agents/history/history_processors.py +129 -12
  18. shotgun/agents/history/token_counting/__init__.py +31 -0
  19. shotgun/agents/history/token_counting/anthropic.py +127 -0
  20. shotgun/agents/history/token_counting/base.py +78 -0
  21. shotgun/agents/history/token_counting/openai.py +90 -0
  22. shotgun/agents/history/token_counting/sentencepiece_counter.py +127 -0
  23. shotgun/agents/history/token_counting/tokenizer_cache.py +92 -0
  24. shotgun/agents/history/token_counting/utils.py +144 -0
  25. shotgun/agents/history/token_estimation.py +12 -12
  26. shotgun/agents/llm.py +62 -0
  27. shotgun/agents/models.py +59 -4
  28. shotgun/agents/plan.py +6 -7
  29. shotgun/agents/research.py +7 -8
  30. shotgun/agents/specify.py +6 -7
  31. shotgun/agents/tasks.py +6 -7
  32. shotgun/agents/tools/__init__.py +0 -2
  33. shotgun/agents/tools/codebase/codebase_shell.py +6 -0
  34. shotgun/agents/tools/codebase/directory_lister.py +6 -0
  35. shotgun/agents/tools/codebase/file_read.py +11 -2
  36. shotgun/agents/tools/codebase/query_graph.py +6 -0
  37. shotgun/agents/tools/codebase/retrieve_code.py +6 -0
  38. shotgun/agents/tools/file_management.py +82 -16
  39. shotgun/agents/tools/registry.py +217 -0
  40. shotgun/agents/tools/web_search/__init__.py +55 -16
  41. shotgun/agents/tools/web_search/anthropic.py +76 -51
  42. shotgun/agents/tools/web_search/gemini.py +50 -27
  43. shotgun/agents/tools/web_search/openai.py +26 -17
  44. shotgun/agents/tools/web_search/utils.py +2 -2
  45. shotgun/agents/usage_manager.py +164 -0
  46. shotgun/api_endpoints.py +15 -0
  47. shotgun/cli/clear.py +53 -0
  48. shotgun/cli/compact.py +186 -0
  49. shotgun/cli/config.py +41 -67
  50. shotgun/cli/context.py +111 -0
  51. shotgun/cli/export.py +1 -1
  52. shotgun/cli/feedback.py +50 -0
  53. shotgun/cli/models.py +3 -2
  54. shotgun/cli/plan.py +1 -1
  55. shotgun/cli/research.py +1 -1
  56. shotgun/cli/specify.py +1 -1
  57. shotgun/cli/tasks.py +1 -1
  58. shotgun/cli/update.py +16 -2
  59. shotgun/codebase/core/change_detector.py +5 -3
  60. shotgun/codebase/core/code_retrieval.py +4 -2
  61. shotgun/codebase/core/ingestor.py +57 -16
  62. shotgun/codebase/core/manager.py +20 -7
  63. shotgun/codebase/core/nl_query.py +1 -1
  64. shotgun/codebase/models.py +4 -4
  65. shotgun/exceptions.py +32 -0
  66. shotgun/llm_proxy/__init__.py +19 -0
  67. shotgun/llm_proxy/clients.py +44 -0
  68. shotgun/llm_proxy/constants.py +15 -0
  69. shotgun/logging_config.py +18 -27
  70. shotgun/main.py +91 -12
  71. shotgun/posthog_telemetry.py +81 -10
  72. shotgun/prompts/agents/export.j2 +18 -1
  73. shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +5 -1
  74. shotgun/prompts/agents/partials/interactive_mode.j2 +24 -7
  75. shotgun/prompts/agents/plan.j2 +1 -1
  76. shotgun/prompts/agents/research.j2 +1 -1
  77. shotgun/prompts/agents/specify.j2 +270 -3
  78. shotgun/prompts/agents/state/system_state.j2 +4 -0
  79. shotgun/prompts/agents/tasks.j2 +1 -1
  80. shotgun/prompts/loader.py +2 -2
  81. shotgun/prompts/tools/web_search.j2 +14 -0
  82. shotgun/sentry_telemetry.py +27 -18
  83. shotgun/settings.py +238 -0
  84. shotgun/shotgun_web/__init__.py +19 -0
  85. shotgun/shotgun_web/client.py +138 -0
  86. shotgun/shotgun_web/constants.py +21 -0
  87. shotgun/shotgun_web/models.py +47 -0
  88. shotgun/telemetry.py +24 -36
  89. shotgun/tui/app.py +251 -23
  90. shotgun/tui/commands/__init__.py +1 -1
  91. shotgun/tui/components/context_indicator.py +179 -0
  92. shotgun/tui/components/mode_indicator.py +70 -0
  93. shotgun/tui/components/status_bar.py +48 -0
  94. shotgun/tui/containers.py +91 -0
  95. shotgun/tui/dependencies.py +39 -0
  96. shotgun/tui/protocols.py +45 -0
  97. shotgun/tui/screens/chat/__init__.py +5 -0
  98. shotgun/tui/screens/chat/chat.tcss +54 -0
  99. shotgun/tui/screens/chat/chat_screen.py +1234 -0
  100. shotgun/tui/screens/chat/codebase_index_prompt_screen.py +64 -0
  101. shotgun/tui/screens/chat/codebase_index_selection.py +12 -0
  102. shotgun/tui/screens/chat/help_text.py +40 -0
  103. shotgun/tui/screens/chat/prompt_history.py +48 -0
  104. shotgun/tui/screens/chat.tcss +11 -0
  105. shotgun/tui/screens/chat_screen/command_providers.py +226 -11
  106. shotgun/tui/screens/chat_screen/history/__init__.py +22 -0
  107. shotgun/tui/screens/chat_screen/history/agent_response.py +66 -0
  108. shotgun/tui/screens/chat_screen/history/chat_history.py +116 -0
  109. shotgun/tui/screens/chat_screen/history/formatters.py +115 -0
  110. shotgun/tui/screens/chat_screen/history/partial_response.py +43 -0
  111. shotgun/tui/screens/chat_screen/history/user_question.py +42 -0
  112. shotgun/tui/screens/confirmation_dialog.py +151 -0
  113. shotgun/tui/screens/feedback.py +193 -0
  114. shotgun/tui/screens/github_issue.py +102 -0
  115. shotgun/tui/screens/model_picker.py +352 -0
  116. shotgun/tui/screens/onboarding.py +431 -0
  117. shotgun/tui/screens/pipx_migration.py +153 -0
  118. shotgun/tui/screens/provider_config.py +156 -39
  119. shotgun/tui/screens/shotgun_auth.py +295 -0
  120. shotgun/tui/screens/welcome.py +198 -0
  121. shotgun/tui/services/__init__.py +5 -0
  122. shotgun/tui/services/conversation_service.py +184 -0
  123. shotgun/tui/state/__init__.py +7 -0
  124. shotgun/tui/state/processing_state.py +185 -0
  125. shotgun/tui/utils/mode_progress.py +14 -7
  126. shotgun/tui/widgets/__init__.py +5 -0
  127. shotgun/tui/widgets/widget_coordinator.py +262 -0
  128. shotgun/utils/datetime_utils.py +77 -0
  129. shotgun/utils/env_utils.py +13 -0
  130. shotgun/utils/file_system_utils.py +22 -2
  131. shotgun/utils/marketing.py +110 -0
  132. shotgun/utils/update_checker.py +69 -14
  133. shotgun_sh-0.2.11.dist-info/METADATA +130 -0
  134. shotgun_sh-0.2.11.dist-info/RECORD +194 -0
  135. {shotgun_sh-0.1.14.dist-info → shotgun_sh-0.2.11.dist-info}/entry_points.txt +1 -0
  136. {shotgun_sh-0.1.14.dist-info → shotgun_sh-0.2.11.dist-info}/licenses/LICENSE +1 -1
  137. shotgun/agents/history/token_counting.py +0 -429
  138. shotgun/agents/tools/user_interaction.py +0 -37
  139. shotgun/tui/screens/chat.py +0 -797
  140. shotgun/tui/screens/chat_screen/history.py +0 -350
  141. shotgun_sh-0.1.14.dist-info/METADATA +0 -466
  142. shotgun_sh-0.1.14.dist-info/RECORD +0 -133
  143. {shotgun_sh-0.1.14.dist-info → shotgun_sh-0.2.11.dist-info}/WHEEL +0 -0
@@ -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
- # Hardcoded PostHog configuration
33
- api_key = "phc_KKnChzZUKeNqZDOTJ6soCBWNQSx3vjiULdwTR9H5Mcr"
36
+ # Get API key from settings (handles build constants + env vars automatically)
37
+ api_key = settings.telemetry.posthog_api_key
34
38
 
35
- logger.debug("Using hardcoded PostHog configuration")
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 user ID from config
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
- user_id = config_manager.get_user_id()
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=user_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("PostHog user identified with anonymous ID: %s", user_id)
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
- # Get user ID for tracking
112
+ import asyncio
113
+
114
+ # Get shotgun instance ID for tracking
100
115
  config_manager = get_config_manager()
101
- user_id = config_manager.get_user_id()
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=user_id, event=event_name, properties=properties
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
+ )
@@ -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 ask_user tool to gather specific details about:
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. Do not make assumptions about what the user wants.
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
- - BEFORE GETTING TO WORK, ALWAYS THINK WHAT YOU'RE GOING TO DO AND ask_user() TO ACCEPT WHAT YOU'RE GOING TO DO.
10
- - ALWAYS USE ask_user TO REVIEW AND ACCEPT THE ARTIFACT SECTION YOU'VE WORKED ON BEFORE PROCEEDING TO THE NEXT SECTION.
11
- - AFTER USING write_artifact_section(), ALWAYS USE ask_user() TO REVIEW AND ACCEPT THE ARTIFACT SECTION YOU'VE WORKED ON BEFORE PROCEEDING TO THE NEXT SECTION.
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, ASK before proceeding
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 using ask_user tool
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
 
@@ -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 ask_user tool to gather specific details about:
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 USING ask_user(). FINISH THE QUESTION WITH ASKING FOR A GO AHEAD.
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
- - This is your persistent memory store - ALWAYS load it first
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 file updated as you work - it's your memory across sessions
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
 
@@ -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 ask_user tool to gather specific details about:
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, select_autoescape
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=select_autoescape(["j2"]),
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.