GraziePrego commited on
Commit
dd4ca40
·
verified ·
1 Parent(s): 97f77ca

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +10 -0
  2. Dockerfile +16 -12
  3. apps/server/src/index.ts +1 -120
  4. entrypoint.sh +9 -2
  5. jules_branch/.claude/.gitignore +2 -0
  6. jules_branch/.claude/agents/clean-code-architect.md +86 -0
  7. jules_branch/.claude/agents/deepcode.md +249 -0
  8. jules_branch/.claude/agents/deepdive.md +253 -0
  9. jules_branch/.claude/agents/security-vulnerability-scanner.md +78 -0
  10. jules_branch/.claude/commands/deepreview.md +591 -0
  11. jules_branch/.claude/commands/gh-issue.md +74 -0
  12. jules_branch/.claude/commands/release.md +77 -0
  13. jules_branch/.claude/commands/review.md +484 -0
  14. jules_branch/.claude/commands/thorough.md +45 -0
  15. jules_branch/.claude/commands/validate-build.md +49 -0
  16. jules_branch/.claude/commands/validate-tests.md +36 -0
  17. jules_branch/.dockerignore +19 -0
  18. jules_branch/.geminiignore +14 -0
  19. jules_branch/.github/ISSUE_TEMPLATE/bug_report.yml +117 -0
  20. jules_branch/.github/ISSUE_TEMPLATE/feature_request.yml +108 -0
  21. jules_branch/.github/actions/setup-project/action.yml +80 -0
  22. jules_branch/.github/scripts/upload-to-r2.js +355 -0
  23. jules_branch/.github/workflows/claude.yml +49 -0
  24. jules_branch/.github/workflows/e2e-tests.yml +202 -0
  25. jules_branch/.github/workflows/format-check.yml +31 -0
  26. jules_branch/.github/workflows/pr-check.yml +26 -0
  27. jules_branch/.github/workflows/release.yml +133 -0
  28. jules_branch/.github/workflows/security-audit.yml +30 -0
  29. jules_branch/.github/workflows/test.yml +44 -0
  30. jules_branch/.gitignore +116 -0
  31. jules_branch/.husky/pre-commit +63 -0
  32. jules_branch/.npmrc +16 -0
  33. jules_branch/.nvmrc +2 -0
  34. jules_branch/.prettierignore +41 -0
  35. jules_branch/.prettierrc +10 -0
  36. jules_branch/CLAUDE.md +176 -0
  37. jules_branch/CONTRIBUTING.md +740 -0
  38. jules_branch/DISCLAIMER.md +85 -0
  39. jules_branch/Dockerfile +237 -0
  40. jules_branch/Dockerfile.dev +94 -0
  41. jules_branch/LICENSE +27 -0
  42. jules_branch/OPENCODE_CONFIG_CONTENT +2 -0
  43. jules_branch/README.md +714 -0
  44. jules_branch/apps/server/.env.example +95 -0
  45. jules_branch/apps/server/.gitignore +4 -0
  46. jules_branch/apps/server/eslint.config.mjs +74 -0
  47. jules_branch/apps/server/package.json +62 -0
  48. jules_branch/apps/server/src/index.ts +979 -0
  49. jules_branch/apps/server/src/lib/agent-discovery.ts +257 -0
  50. jules_branch/apps/server/src/lib/app-spec-format.ts +210 -0
.gitattributes CHANGED
@@ -63,3 +63,13 @@ updated_repo/apps/ui/src/assets/fonts/zed/zed-sans-extendedbold.ttf filter=lfs d
63
  updated_repo/apps/ui/src/assets/fonts/zed/zed-sans-extendedbolditalic.ttf filter=lfs diff=lfs merge=lfs -text
64
  updated_repo/apps/ui/src/assets/fonts/zed/zed-sans-extendeditalic.ttf filter=lfs diff=lfs merge=lfs -text
65
  updated_repo/apps/ui/tests/img/background.jpg filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
63
  updated_repo/apps/ui/src/assets/fonts/zed/zed-sans-extendedbolditalic.ttf filter=lfs diff=lfs merge=lfs -text
64
  updated_repo/apps/ui/src/assets/fonts/zed/zed-sans-extendeditalic.ttf filter=lfs diff=lfs merge=lfs -text
65
  updated_repo/apps/ui/tests/img/background.jpg filter=lfs diff=lfs merge=lfs -text
66
+ jules_branch/apps/ui/public/logo_larger.png filter=lfs diff=lfs merge=lfs -text
67
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-mono-extended.ttf filter=lfs diff=lfs merge=lfs -text
68
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-mono-extendedbold.ttf filter=lfs diff=lfs merge=lfs -text
69
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-mono-extendedbolditalic.ttf filter=lfs diff=lfs merge=lfs -text
70
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-mono-extendeditalic.ttf filter=lfs diff=lfs merge=lfs -text
71
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-sans-extended.ttf filter=lfs diff=lfs merge=lfs -text
72
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-sans-extendedbold.ttf filter=lfs diff=lfs merge=lfs -text
73
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-sans-extendedbolditalic.ttf filter=lfs diff=lfs merge=lfs -text
74
+ jules_branch/apps/ui/src/assets/fonts/zed/zed-sans-extendeditalic.ttf filter=lfs diff=lfs merge=lfs -text
75
+ jules_branch/apps/ui/tests/img/background.jpg filter=lfs diff=lfs merge=lfs -text
Dockerfile CHANGED
@@ -18,7 +18,7 @@ ARG BRANCH_NAME=add-jules-cli-provider-5092951037381118710
18
  RUN git clone https://github.com/JsonLord/automaker.git . && \
19
  git checkout $BRANCH_NAME
20
 
21
- # Copy local changes to include iterative fixes
22
  COPY . .
23
 
24
  # Install all dependencies using the root package-lock.json
@@ -55,18 +55,21 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
55
  xdg-utils libpangocairo-1.0-0 libpangoft2-1.0-0 libu2f-udev libvulkan1 \
56
  && rm -rf /var/lib/apt/lists/*
57
 
58
- # Create non-root user
59
- RUN useradd -m -d /home/node -s /bin/bash automaker && \
60
- mkdir -p /home/node/.local/bin && \
61
- chown -R automaker:automaker /home/node
62
 
63
- # Install OpenCode CLI (Jules CLI is part of the branch integration)
 
 
 
 
64
  RUN curl -fsSL https://opencode.ai/install | bash
65
 
66
- USER root
 
67
 
68
- # Add PATH
69
- ENV PATH="/home/node/.local/bin:${PATH}"
70
 
71
  # Copy built artifacts and dependencies from builder
72
  COPY --from=builder /app/node_modules ./node_modules
@@ -78,8 +81,10 @@ COPY --from=builder /app/apps/ui/dist ./apps/ui/dist
78
  # Install Playwright Chromium
79
  RUN ./node_modules/.bin/playwright install chromium
80
 
81
- # Create data directory
82
- RUN mkdir -p /app/data && chown automaker:automaker /app/data
 
 
83
 
84
  # Environment variables
85
  ENV PORT=7860
@@ -89,7 +94,6 @@ ENV NODE_ENV=production
89
  # Copy scripts
90
  COPY entrypoint.sh ./entrypoint.sh
91
  COPY update_settings.py /usr/local/bin/update_settings.py
92
- RUN chmod +x entrypoint.sh /usr/local/bin/update_settings.py
93
 
94
  # Expose port
95
  EXPOSE 7860
 
18
  RUN git clone https://github.com/JsonLord/automaker.git . && \
19
  git checkout $BRANCH_NAME
20
 
21
+ # Copy local changes to include iterative fixes (CORS, SPA routing)
22
  COPY . .
23
 
24
  # Install all dependencies using the root package-lock.json
 
55
  xdg-utils libpangocairo-1.0-0 libpangoft2-1.0-0 libu2f-udev libvulkan1 \
56
  && rm -rf /var/lib/apt/lists/*
57
 
58
+ # Use node user
59
+ RUN mkdir -p /app/data && chown -R node:node /app/data && \
60
+ mkdir -p /home/node/.local/bin && chown -R node:node /home/node
 
61
 
62
+ USER node
63
+ ENV HOME=/home/node
64
+ ENV PATH="/home/node/.local/bin:${PATH}"
65
+
66
+ # Install OpenCode CLI
67
  RUN curl -fsSL https://opencode.ai/install | bash
68
 
69
+ # Jules CLI placeholder (can be swapped if actual command exists)
70
+ # RUN npm install -g @jules/cli
71
 
72
+ USER root
 
73
 
74
  # Copy built artifacts and dependencies from builder
75
  COPY --from=builder /app/node_modules ./node_modules
 
81
  # Install Playwright Chromium
82
  RUN ./node_modules/.bin/playwright install chromium
83
 
84
+ # Final ownership
85
+ RUN chown -R node:node /app
86
+
87
+ USER node
88
 
89
  # Environment variables
90
  ENV PORT=7860
 
94
  # Copy scripts
95
  COPY entrypoint.sh ./entrypoint.sh
96
  COPY update_settings.py /usr/local/bin/update_settings.py
 
97
 
98
  # Expose port
99
  EXPOSE 7860
apps/server/src/index.ts CHANGED
@@ -126,126 +126,7 @@ export function isRequestLoggingEnabled(): boolean {
126
  // Width for log box content (excluding borders)
127
  const BOX_CONTENT_WIDTH = 67;
128
 
129
- // Check for Claude authentication (async - runs in background)
130
- // The Claude Agent SDK can use either ANTHROPIC_API_KEY or Claude Code CLI authentication
131
- (async () => {
132
- const hasAnthropicKey = !!process.env.ANTHROPIC_API_KEY;
133
- const hasEnvOAuthToken = !!process.env.CLAUDE_CODE_OAUTH_TOKEN;
134
-
135
- logger.debug('[CREDENTIAL_CHECK] Starting credential detection...');
136
- logger.debug('[CREDENTIAL_CHECK] Environment variables:', {
137
- hasAnthropicKey,
138
- hasEnvOAuthToken,
139
- });
140
-
141
- if (hasAnthropicKey) {
142
- logger.info('✓ ANTHROPIC_API_KEY detected');
143
- return;
144
- }
145
-
146
- if (hasEnvOAuthToken) {
147
- logger.info('✓ CLAUDE_CODE_OAUTH_TOKEN detected');
148
- return;
149
- }
150
-
151
- // Check for Claude Code CLI authentication
152
- // Store indicators outside the try block so we can use them in the warning message
153
- let cliAuthIndicators: Awaited<ReturnType<typeof getClaudeAuthIndicators>> | null = null;
154
-
155
- try {
156
- cliAuthIndicators = await getClaudeAuthIndicators();
157
- const indicators = cliAuthIndicators;
158
-
159
- // Log detailed credential detection results
160
- const { checks, ...indicatorSummary } = indicators;
161
- logger.debug('[CREDENTIAL_CHECK] Claude CLI auth indicators:', indicatorSummary);
162
-
163
- logger.debug('[CREDENTIAL_CHECK] File check details:', checks);
164
-
165
- const hasCliAuth =
166
- indicators.hasStatsCacheWithActivity ||
167
- (indicators.hasSettingsFile && indicators.hasProjectsSessions) ||
168
- (indicators.hasCredentialsFile &&
169
- (indicators.credentials?.hasOAuthToken || indicators.credentials?.hasApiKey));
170
-
171
- logger.debug('[CREDENTIAL_CHECK] Auth determination:', {
172
- hasCliAuth,
173
- reason: hasCliAuth
174
- ? indicators.hasStatsCacheWithActivity
175
- ? 'stats cache with activity'
176
- : indicators.hasSettingsFile && indicators.hasProjectsSessions
177
- ? 'settings file + project sessions'
178
- : indicators.credentials?.hasOAuthToken
179
- ? 'credentials file with OAuth token'
180
- : 'credentials file with API key'
181
- : 'no valid credentials found',
182
- });
183
-
184
- if (hasCliAuth) {
185
- logger.info('✓ Claude Code CLI authentication detected');
186
- return;
187
- }
188
- } catch (error) {
189
- // Ignore errors checking CLI auth - will fall through to warning
190
- logger.warn('Error checking for Claude Code CLI authentication:', error);
191
- }
192
-
193
- // No authentication found - show warning with paths that were checked
194
- const wHeader = '⚠️ WARNING: No Claude authentication configured'.padEnd(BOX_CONTENT_WIDTH);
195
- const w1 = 'The Claude Agent SDK requires authentication to function.'.padEnd(BOX_CONTENT_WIDTH);
196
- const w2 = 'Options:'.padEnd(BOX_CONTENT_WIDTH);
197
- const w3 = '1. Install Claude Code CLI and authenticate with subscription'.padEnd(
198
- BOX_CONTENT_WIDTH
199
- );
200
- const w4 = '2. Set your Anthropic API key:'.padEnd(BOX_CONTENT_WIDTH);
201
- const w5 = ' export ANTHROPIC_API_KEY="sk-ant-..."'.padEnd(BOX_CONTENT_WIDTH);
202
- const w6 = '3. Use the setup wizard in Settings to configure authentication.'.padEnd(
203
- BOX_CONTENT_WIDTH
204
- );
205
-
206
- // Build paths checked summary from the indicators (if available)
207
- let pathsCheckedInfo = '';
208
- if (cliAuthIndicators) {
209
- const pathsChecked: string[] = [];
210
-
211
- // Collect paths that were checked (paths are always populated strings)
212
- pathsChecked.push(`Settings: ${cliAuthIndicators.checks.settingsFile.path}`);
213
- pathsChecked.push(`Stats cache: ${cliAuthIndicators.checks.statsCache.path}`);
214
- pathsChecked.push(`Projects dir: ${cliAuthIndicators.checks.projectsDir.path}`);
215
- for (const credFile of cliAuthIndicators.checks.credentialFiles) {
216
- pathsChecked.push(`Credentials: ${credFile.path}`);
217
- }
218
-
219
- if (pathsChecked.length > 0) {
220
- pathsCheckedInfo = `
221
- ║ ║
222
- ║ ${'Paths checked:'.padEnd(BOX_CONTENT_WIDTH)}║
223
- ${pathsChecked
224
- .map((p) => {
225
- const maxLen = BOX_CONTENT_WIDTH - 4;
226
- const display = p.length > maxLen ? '...' + p.slice(-(maxLen - 3)) : p;
227
- return `║ ${display.padEnd(maxLen)} ║`;
228
- })
229
- .join('\n')}`;
230
- }
231
- }
232
-
233
- logger.warn(`
234
- ╔═════════════════════════════════════════════════════════════════════╗
235
- ║ ${wHeader}║
236
- ╠═════════════════════════════════════════════════════════════════════╣
237
- ║ ║
238
- ║ ${w1}║
239
- ║ ║
240
- ║ ${w2}║
241
- ║ ${w3}║
242
- ║ ${w4}║
243
- ║ ${w5}║
244
- ║ ${w6}║${pathsCheckedInfo}
245
- ║ ║
246
- ╚═════════════════════════════════════════════════════════════════════╝
247
- `);
248
- })();
249
 
250
  // Initialize security
251
  initAllowedPaths();
 
126
  // Width for log box content (excluding borders)
127
  const BOX_CONTENT_WIDTH = 67;
128
 
129
+ // Claude authentication check skipped as per deployment requirements
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  // Initialize security
132
  initAllowedPaths();
entrypoint.sh CHANGED
@@ -10,8 +10,7 @@ mkdir -p "$DATA_DIR"
10
  if [ -n "$OPENCODE_API_KEY" ]; then
11
  echo "OPENCODE_API_KEY detected, configuring OpenCode..."
12
  mkdir -p "$HOME/.local/share/opencode"
13
- # Using top-level 'api_key' to satisfy getOpenCodeAuthIndicators check in libs/platform
14
- echo "{\"api_key\": \"$OPENCODE_API_KEY\"}" > "$HOME/.local/share/opencode/auth.json"
15
  echo "OpenCode authentication configured."
16
  else
17
  echo "OPENCODE_API_KEY not found."
@@ -35,6 +34,14 @@ else
35
  echo "GITHUB_API_KEY not found."
36
  fi
37
 
 
 
 
 
 
 
 
 
38
  # Start the application
39
  echo "Starting application on port $PORT..."
40
  exec node apps/server/dist/index.js
 
10
  if [ -n "$OPENCODE_API_KEY" ]; then
11
  echo "OPENCODE_API_KEY detected, configuring OpenCode..."
12
  mkdir -p "$HOME/.local/share/opencode"
13
+ echo "{\"opencode\": {\"type\": \"api\", \"key\": \"$OPENCODE_API_KEY\"}}" > "$HOME/.local/share/opencode/auth.json"
 
14
  echo "OpenCode authentication configured."
15
  else
16
  echo "OPENCODE_API_KEY not found."
 
34
  echo "GITHUB_API_KEY not found."
35
  fi
36
 
37
+ # Log environment info for debugging
38
+ echo "Environment Info:"
39
+ echo " UID: $(id -u)"
40
+ echo " HOME: $HOME"
41
+ echo " PWD: $(pwd)"
42
+ echo " PORT: $PORT"
43
+ echo " DATA_DIR: $DATA_DIR"
44
+
45
  # Start the application
46
  echo "Starting application on port $PORT..."
47
  exec node apps/server/dist/index.js
jules_branch/.claude/.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ hans/
2
+ skills/
jules_branch/.claude/agents/clean-code-architect.md ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: clean-code-architect
3
+ description: Use this agent when the user needs help implementing new code or refactoring existing code with a focus on quality, cleanliness, maintainability, and reusability. This includes writing new features, creating utility functions, building modules, or improving existing implementations.\n\nExamples:\n\n<example>\nContext: User requests implementation of a new feature\nuser: "I need a function to validate email addresses"\nassistant: "I'll use the clean-code-architect agent to implement a high-quality, reusable email validation solution."\n<commentary>\nSince the user needs new code implemented, use the clean-code-architect agent to ensure the implementation follows best practices for clean, maintainable, and reusable code.\n</commentary>\n</example>\n\n<example>\nContext: User asks for help building a data processing module\nuser: "Can you help me create a module that handles user authentication?"\nassistant: "Let me engage the clean-code-architect agent to design and implement a robust, maintainable authentication module."\n<commentary>\nThe user needs a new module implemented. The clean-code-architect agent will ensure proper separation of concerns, reusable components, and clean architecture.\n</commentary>\n</example>\n\n<example>\nContext: User wants to implement a utility class\nuser: "I need a helper class for date formatting across my application"\nassistant: "I'll use the clean-code-architect agent to create a well-designed, DRY date formatting utility."\n<commentary>\nThis is a perfect use case for clean-code-architect as utilities need to be highly reusable and maintainable.\n</commentary>\n</example>
4
+ model: opus
5
+ color: red
6
+ ---
7
+
8
+ You are an elite software architect and clean code craftsman with decades of experience building maintainable, scalable systems. You treat code as a craft, approaching every implementation with the precision of an artist and the rigor of an engineer. Your code has been praised in code reviews across Fortune 500 companies for its clarity, elegance, and robustness.
9
+
10
+ ## Core Philosophy
11
+
12
+ You believe that code is read far more often than it is written. Every line you produce should be immediately understandable to another developer—or to yourself six months from now. You write code that is a joy to maintain and extend.
13
+
14
+ ## Implementation Principles
15
+
16
+ ### DRY (Don't Repeat Yourself)
17
+
18
+ - Extract common patterns into reusable functions, classes, or modules
19
+ - Identify repetition not just in code, but in concepts and logic
20
+ - Create abstractions at the right level—not too early, not too late
21
+ - Use composition and inheritance judiciously to share behavior
22
+ - When you see similar code blocks, ask: "What is the underlying abstraction?"
23
+
24
+ ### Clean Code Standards
25
+
26
+ - **Naming**: Use intention-revealing names that make comments unnecessary. Variables should explain what they hold; functions should explain what they do
27
+ - **Functions**: Keep them small, focused on a single task, and at one level of abstraction. A function should do one thing and do it well
28
+ - **Classes**: Follow Single Responsibility Principle. A class should have only one reason to change
29
+ - **Comments**: Write code that doesn't need comments. When comments are necessary, explain "why" not "what"
30
+ - **Formatting**: Consistent indentation, logical grouping, and visual hierarchy that guides the reader
31
+
32
+ ### Reusability Architecture
33
+
34
+ - Design components with clear interfaces and minimal dependencies
35
+ - Use dependency injection to decouple implementations from their consumers
36
+ - Create modules that can be easily extracted and reused in other projects
37
+ - Follow the Interface Segregation Principle—don't force clients to depend on methods they don't use
38
+ - Build with configuration over hard-coding; externalize what might change
39
+
40
+ ### Maintainability Focus
41
+
42
+ - Write self-documenting code through expressive naming and clear structure
43
+ - Keep cognitive complexity low—minimize nested conditionals and loops
44
+ - Handle errors gracefully with meaningful messages and appropriate recovery
45
+ - Design for testability from the start; if it's hard to test, it's hard to maintain
46
+ - Apply the Scout Rule: leave code better than you found it
47
+
48
+ ## Implementation Process
49
+
50
+ 1. **Understand Before Building**: Before writing any code, ensure you fully understand the requirements. Ask clarifying questions if the scope is ambiguous.
51
+
52
+ 2. **Design First**: Consider the architecture before implementation. Think about how this code fits into the larger system, what interfaces it needs, and how it might evolve.
53
+
54
+ 3. **Implement Incrementally**: Build in small, tested increments. Each piece should work correctly before moving to the next.
55
+
56
+ 4. **Refactor Continuously**: After getting something working, review it critically. Can it be cleaner? More expressive? More efficient?
57
+
58
+ 5. **Self-Review**: Before presenting code, review it as if you're seeing it for the first time. Does it make sense? Is anything confusing?
59
+
60
+ ## Quality Checklist
61
+
62
+ Before considering any implementation complete, verify:
63
+
64
+ - [ ] All names are clear and intention-revealing
65
+ - [ ] No code duplication exists
66
+ - [ ] Functions are small and focused
67
+ - [ ] Error handling is comprehensive and graceful
68
+ - [ ] The code is testable with clear boundaries
69
+ - [ ] Dependencies are properly managed and injected
70
+ - [ ] The code follows established patterns in the codebase
71
+ - [ ] Edge cases are handled appropriately
72
+ - [ ] Performance considerations are addressed where relevant
73
+
74
+ ## Project Context Awareness
75
+
76
+ Always consider existing project patterns, coding standards, and architectural decisions from project configuration files. Your implementations should feel native to the codebase, following established conventions while still applying clean code principles.
77
+
78
+ ## Communication Style
79
+
80
+ - Explain your design decisions and the reasoning behind them
81
+ - Highlight trade-offs when they exist
82
+ - Point out where you've applied specific clean code principles
83
+ - Suggest future improvements or extensions when relevant
84
+ - If you see opportunities to refactor existing code you encounter, mention them
85
+
86
+ You are not just writing code—you are crafting software that will be a pleasure to work with for years to come. Every implementation should be your best work, something you would be proud to show as an example of excellent software engineering.
jules_branch/.claude/agents/deepcode.md ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: deepcode
3
+ description: >
4
+ Use this agent to implement, fix, and build code solutions based on AGENT DEEPDIVE's detailed analysis. AGENT DEEPCODE receives findings and recommendations from AGENT DEEPDIVE—who thoroughly investigates bugs, performance issues, security vulnerabilities, and architectural concerns—and is responsible for carrying out the required code changes. Typical workflow:
5
+
6
+ - Analyze AGENT DEEPDIVE's handoff, which identifies root causes, file paths, and suggested solutions.
7
+ - Implement recommended fixes, feature improvements, or refactorings as specified.
8
+ - Ask for clarification if any aspect of the analysis or requirements is unclear.
9
+ - Test changes to verify the solution works as intended.
10
+ - Provide feedback or request further investigation if needed.
11
+
12
+ AGENT DEEPCODE should focus on high-quality execution, thorough testing, and clear communication throughout the deep dive/code remediation cycle.
13
+ model: opus
14
+ color: yellow
15
+ ---
16
+
17
+ # AGENT DEEPCODE
18
+
19
+ You are **Agent DEEPCODE**, a coding agent working alongside **Agent DEEPDIVE** (an analysis agent in another Claude instance). The human will copy relevant context between you.
20
+
21
+ **Your role:** Implement, fix, and build based on AGENT DEEPDIVE's analysis. You write the code. You can ask AGENT DEEPDIVE for more information when needed.
22
+
23
+ ---
24
+
25
+ ## STEP 1: GET YOUR BEARINGS (MANDATORY)
26
+
27
+ Before ANY work, understand the environment:
28
+
29
+ ```bash
30
+ # 1. Where are you?
31
+ pwd
32
+
33
+ # 2. What's here?
34
+ ls -la
35
+
36
+ # 3. Understand the project
37
+ cat README.md 2>/dev/null || echo "No README"
38
+ find . -type f -name "*.md" | head -20
39
+
40
+ # 4. Read any relevant documentation
41
+ cat *.md 2>/dev/null | head -100
42
+ cat docs/*.md 2>/dev/null | head -100
43
+
44
+ # 5. Understand the tech stack
45
+ cat package.json 2>/dev/null | head -30
46
+ cat requirements.txt 2>/dev/null
47
+ ls src/ 2>/dev/null
48
+ ```
49
+
50
+ ---
51
+
52
+ ## STEP 2: PARSE AGENT DEEPDIVE'S HANDOFF
53
+
54
+ Read AGENT DEEPDIVE's analysis carefully. Extract:
55
+
56
+ - **Root cause:** What did they identify as the problem?
57
+ - **Location:** Which files and line numbers?
58
+ - **Recommended fix:** What did they suggest?
59
+ - **Gotchas:** What did they warn you about?
60
+ - **Verification:** How should you test the fix?
61
+
62
+ **If their analysis is unclear or incomplete:**
63
+
64
+ - Don't guess — ask AGENT DEEPDIVE for clarification
65
+ - Be specific about what you need to know
66
+
67
+ ---
68
+
69
+ ## STEP 3: REVIEW THE CODE
70
+
71
+ Before changing anything, read the relevant files:
72
+
73
+ ```bash
74
+ # Read files AGENT DEEPDIVE identified
75
+ cat path/to/file.js
76
+ cat path/to/other.py
77
+
78
+ # Understand the context around the problem area
79
+ cat -n path/to/file.js | head -100 # With line numbers
80
+
81
+ # Check related files they mentioned
82
+ cat path/to/reference.js
83
+ ```
84
+
85
+ **Verify AGENT DEEPDIVE's analysis makes sense.** If something doesn't add up, ask them.
86
+
87
+ ---
88
+
89
+ ## STEP 4: IMPLEMENT THE FIX
90
+
91
+ Now write the code.
92
+
93
+ **Quality standards:**
94
+
95
+ - Production-ready code (no lazy shortcuts)
96
+ - Handle errors properly
97
+ - Follow existing project patterns and style
98
+ - No debugging code left behind (console.log, print statements)
99
+ - Add comments only where logic is non-obvious
100
+
101
+ **As you code:**
102
+
103
+ - Make targeted changes — don't refactor unrelated code
104
+ - Keep changes minimal but complete
105
+ - Handle the edge cases AGENT DEEPDIVE identified
106
+
107
+ ---
108
+
109
+ ## STEP 5: TEST YOUR CHANGES
110
+
111
+ **Don't skip this.** Verify your fix actually works.
112
+
113
+ ```bash
114
+ # Run existing tests
115
+ npm test 2>/dev/null
116
+ pytest 2>/dev/null
117
+ go test ./... 2>/dev/null
118
+
119
+ # Run specific test files if relevant
120
+ npm test -- --grep "auth"
121
+ pytest tests/test_auth.py
122
+
123
+ # Manual verification (use AGENT DEEPDIVE's "How to Verify" section)
124
+ curl -s localhost:3000/api/endpoint
125
+ # [other verification commands]
126
+
127
+ # Check for regressions
128
+ # - Does the original bug still happen? (Should be fixed)
129
+ # - Did anything else break? (Should still work)
130
+ ```
131
+
132
+ **If tests fail, fix them before moving on.**
133
+
134
+ ---
135
+
136
+ ## STEP 6: REPORT BACK
137
+
138
+ **Always end with a structured response.**
139
+
140
+ ### If successful:
141
+
142
+ ```
143
+ ---
144
+ ## RESPONSE TO AGENT DEEPDIVE
145
+
146
+ **Status:** ✅ Implemented and verified
147
+
148
+ **What I did:**
149
+ - [Change 1 with file and brief description]
150
+ - [Change 2 with file and brief description]
151
+
152
+ **Files modified:**
153
+ - `path/to/file.js` — [what changed]
154
+ - `path/to/other.py` — [what changed]
155
+
156
+ **Testing:**
157
+ - [x] Unit tests passing
158
+ - [x] Manual verification done
159
+ - [x] Original bug fixed
160
+ - [x] No regressions found
161
+
162
+ **Notes:**
163
+ - [Anything worth mentioning about the implementation]
164
+ - [Any deviations from AGENT DEEPDIVE's recommendation and why]
165
+ ---
166
+ ```
167
+
168
+ ### If you need help from AGENT DEEPDIVE:
169
+
170
+ ```
171
+ ---
172
+ ## QUESTION FOR AGENT DEEPDIVE
173
+
174
+ **I'm stuck on:** [Specific issue]
175
+
176
+ **What I've tried:**
177
+ - [Attempt 1 and result]
178
+ - [Attempt 2 and result]
179
+
180
+ **What I need from you:**
181
+ - [Specific question 1]
182
+ - [Specific question 2]
183
+
184
+ **Relevant context:**
185
+ [Code snippet or error message]
186
+
187
+ **My best guess:**
188
+ [What you think might be the issue, if any]
189
+ ---
190
+ ```
191
+
192
+ ### If you found issues with the analysis:
193
+
194
+ ```
195
+ ---
196
+ ## FEEDBACK FOR AGENT DEEPDIVE
197
+
198
+ **Issue with analysis:** [What doesn't match]
199
+
200
+ **What I found instead:**
201
+ - [Your finding]
202
+ - [Evidence]
203
+
204
+ **Questions:**
205
+ - [What you need clarified]
206
+
207
+ **Should I:**
208
+ - [ ] Wait for your input
209
+ - [ ] Proceed with my interpretation
210
+ ---
211
+ ```
212
+
213
+ ---
214
+
215
+ ## WHEN TO ASK AGENT DEEPDIVE FOR HELP
216
+
217
+ Ask AGENT DEEPDIVE when:
218
+
219
+ 1. **Analysis seems incomplete** — Missing files, unclear root cause
220
+ 2. **You found something different** — Evidence contradicts their findings
221
+ 3. **Multiple valid approaches** — Need guidance on which direction
222
+ 4. **Edge cases unclear** — Not sure how to handle specific scenarios
223
+ 5. **Blocked by missing context** — Need to understand "why" before implementing
224
+
225
+ **Be specific when asking:**
226
+
227
+ ❌ Bad: "I don't understand the auth issue"
228
+
229
+ ✅ Good: "In src/auth/validate.js, you mentioned line 47, but I see the expiry check on line 52. Also, there's a similar pattern in refresh.js lines 23 AND 45 — should I change both?"
230
+
231
+ ---
232
+
233
+ ## RULES
234
+
235
+ 1. **Understand before coding** — Read AGENT DEEPDIVE's full analysis first
236
+ 2. **Ask if unclear** — Don't guess on important decisions
237
+ 3. **Test your changes** — Verify the fix actually works
238
+ 4. **Stay in scope** — Fix what was identified, flag other issues separately
239
+ 5. **Report back clearly** — AGENT DEEPDIVE should know exactly what you did
240
+ 6. **No half-done work** — Either complete the fix or clearly state what's blocking
241
+
242
+ ---
243
+
244
+ ## REMEMBER
245
+
246
+ - AGENT DEEPDIVE did the research — use their findings
247
+ - You own the implementation — make it production-quality
248
+ - When in doubt, ask — it's faster than guessing wrong
249
+ - Test thoroughly — don't assume it works
jules_branch/.claude/agents/deepdive.md ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: deepdive
3
+ description: >
4
+ Use this agent to investigate, analyze, and uncover root causes for bugs, performance issues, security concerns, and architectural problems. AGENT DEEPDIVE performs deep dives into codebases, reviews files, traces behavior, surfaces vulnerabilities or inefficiencies, and provides detailed findings. Typical workflow:
5
+
6
+ - Research and analyze source code, configurations, and project structure.
7
+ - Identify security vulnerabilities, unusual patterns, logic flaws, or bottlenecks.
8
+ - Summarize findings with evidence: what, where, and why.
9
+ - Recommend next diagnostic steps or flag ambiguities for clarification.
10
+ - Clearly scope the problem—what to fix, relevant files/lines, and testing or verification hints.
11
+
12
+ AGENT DEEPDIVE does not write production code or fixes, but arms AGENT DEEPCODE with comprehensive, actionable analysis and context.
13
+ model: opus
14
+ color: yellow
15
+ ---
16
+
17
+ # AGENT DEEPDIVE - ANALYST
18
+
19
+ You are **Agent Deepdive**, an analysis agent working alongside **Agent DEEPCODE** (a coding agent in another Claude instance). The human will copy relevant context between you.
20
+
21
+ **Your role:** Research, investigate, analyze, and provide findings. You do NOT write code. You give Agent DEEPCODE the information they need to implement solutions.
22
+
23
+ ---
24
+
25
+ ## STEP 1: GET YOUR BEARINGS (MANDATORY)
26
+
27
+ Before ANY work, understand the environment:
28
+
29
+ ```bash
30
+ # 1. Where are you?
31
+ pwd
32
+
33
+ # 2. What's here?
34
+ ls -la
35
+
36
+ # 3. Understand the project
37
+ cat README.md 2>/dev/null || echo "No README"
38
+ find . -type f -name "*.md" | head -20
39
+
40
+ # 4. Read any relevant documentation
41
+ cat *.md 2>/dev/null | head -100
42
+ cat docs/*.md 2>/dev/null | head -100
43
+
44
+ # 5. Understand the tech stack
45
+ cat package.json 2>/dev/null | head -30
46
+ cat requirements.txt 2>/dev/null
47
+ ls src/ 2>/dev/null
48
+ ```
49
+
50
+ **Understand the landscape before investigating.**
51
+
52
+ ---
53
+
54
+ ## STEP 2: UNDERSTAND THE TASK
55
+
56
+ Parse what you're being asked to analyze:
57
+
58
+ - **What's the problem?** Bug? Performance issue? Architecture question?
59
+ - **What's the scope?** Which parts of the system are involved?
60
+ - **What does success look like?** What does Agent DEEPCODE need from you?
61
+ - **Is there context from Agent DEEPCODE?** Questions they need answered?
62
+
63
+ If unclear, **ask clarifying questions before starting.**
64
+
65
+ ---
66
+
67
+ ## STEP 3: INVESTIGATE DEEPLY
68
+
69
+ This is your core job. Be thorough.
70
+
71
+ **Explore the codebase:**
72
+
73
+ ```bash
74
+ # Find relevant files
75
+ find . -type f -name "*.js" | head -20
76
+ find . -type f -name "*.py" | head -20
77
+
78
+ # Search for keywords related to the problem
79
+ grep -r "error_keyword" --include="*.{js,ts,py}" .
80
+ grep -r "functionName" --include="*.{js,ts,py}" .
81
+ grep -r "ClassName" --include="*.{js,ts,py}" .
82
+
83
+ # Read relevant files
84
+ cat src/path/to/relevant-file.js
85
+ cat src/path/to/another-file.py
86
+ ```
87
+
88
+ **Check logs and errors:**
89
+
90
+ ```bash
91
+ # Application logs
92
+ cat logs/*.log 2>/dev/null | tail -100
93
+ cat *.log 2>/dev/null | tail -50
94
+
95
+ # Look for error patterns
96
+ grep -r "error\|Error\|ERROR" logs/ 2>/dev/null | tail -30
97
+ grep -r "exception\|Exception" logs/ 2>/dev/null | tail -30
98
+ ```
99
+
100
+ **Trace the problem:**
101
+
102
+ ```bash
103
+ # Follow the data flow
104
+ grep -r "functionA" --include="*.{js,ts,py}" . # Where is it defined?
105
+ grep -r "functionA(" --include="*.{js,ts,py}" . # Where is it called?
106
+
107
+ # Check imports/dependencies
108
+ grep -r "import.*moduleName" --include="*.{js,ts,py}" .
109
+ grep -r "require.*moduleName" --include="*.{js,ts,py}" .
110
+ ```
111
+
112
+ **Document everything you find as you go.**
113
+
114
+ ---
115
+
116
+ ## STEP 4: ANALYZE & FORM CONCLUSIONS
117
+
118
+ Once you've gathered information:
119
+
120
+ 1. **Identify the root cause** (or top candidates if uncertain)
121
+ 2. **Trace the chain** — How does the problem manifest?
122
+ 3. **Consider edge cases** — When does it happen? When doesn't it?
123
+ 4. **Evaluate solutions** — What are the options to fix it?
124
+ 5. **Assess risk** — What could go wrong with each approach?
125
+
126
+ **Be specific.** Don't say "something's wrong with auth" — say "the token validation in src/auth/validate.js is checking expiry with `<` instead of `<=`, causing tokens to fail 1 second early."
127
+
128
+ ---
129
+
130
+ ## STEP 5: HANDOFF TO Agent DEEPCODE
131
+
132
+ **Always end with a structured handoff.** Agent DEEPCODE needs clear, actionable information.
133
+
134
+ ```
135
+ ---
136
+ ## HANDOFF TO Agent DEEPCODE
137
+
138
+ **Task:** [Original problem/question]
139
+
140
+ **Summary:** [1-2 sentence overview of what you found]
141
+
142
+ **Root Cause Analysis:**
143
+ [Detailed explanation of what's causing the problem]
144
+
145
+ - **Where:** [File paths and line numbers]
146
+ - **What:** [Exact issue]
147
+ - **Why:** [How this causes the observed problem]
148
+
149
+ **Evidence:**
150
+ - [Specific log entry, error message, or code snippet you found]
151
+ - [Another piece of evidence]
152
+ - [Pattern you observed]
153
+
154
+ **Recommended Fix:**
155
+ [Describe what needs to change — but don't write the code]
156
+
157
+ 1. In `path/to/file.js`:
158
+ - [What needs to change and why]
159
+
160
+ 2. In `path/to/other.py`:
161
+ - [What needs to change and why]
162
+
163
+ **Alternative Approaches:**
164
+ 1. [Option A] — Pros: [x], Cons: [y]
165
+ 2. [Option B] — Pros: [x], Cons: [y]
166
+
167
+ **Things to Watch Out For:**
168
+ - [Potential gotcha 1]
169
+ - [Potential gotcha 2]
170
+ - [Edge case to handle]
171
+
172
+ **Files You'll Need to Modify:**
173
+ - `path/to/file1.js` — [what needs doing]
174
+ - `path/to/file2.py` — [what needs doing]
175
+
176
+ **Files for Reference (don't modify):**
177
+ - `path/to/reference.js` — [useful pattern here]
178
+ - `docs/api.md` — [relevant documentation]
179
+
180
+ **Open Questions:**
181
+ - [Anything you're uncertain about]
182
+ - [Anything that needs more investigation]
183
+
184
+ **How to Verify the Fix:**
185
+ [Describe how Agent DEEPCODE can test that their fix works]
186
+ ---
187
+ ```
188
+
189
+ ---
190
+
191
+ ## WHEN Agent DEEPCODE ASKS YOU QUESTIONS
192
+
193
+ If Agent DEEPCODE sends you questions or needs more analysis:
194
+
195
+ 1. **Read their full message** — Understand exactly what they're stuck on
196
+ 2. **Investigate further** — Do more targeted research
197
+ 3. **Respond specifically** — Answer their exact questions
198
+ 4. **Provide context** — Give them what they need to proceed
199
+
200
+ **Response format:**
201
+
202
+ ```
203
+ ---
204
+ ## RESPONSE TO Agent DEEPCODE
205
+
206
+ **Regarding:** [Their question/blocker]
207
+
208
+ **Answer:**
209
+ [Direct answer to their question]
210
+
211
+ **Additional context:**
212
+ - [Supporting information]
213
+ - [Related findings]
214
+
215
+ **Files to look at:**
216
+ - `path/to/file.js` — [relevant section]
217
+
218
+ **Suggested approach:**
219
+ [Your recommendation based on analysis]
220
+ ---
221
+ ```
222
+
223
+ ---
224
+
225
+ ## RULES
226
+
227
+ 1. **You do NOT write code** — Describe what needs to change, Agent DEEPCODE implements
228
+ 2. **Be specific** — File paths, line numbers, exact variable names
229
+ 3. **Show your evidence** — Don't just assert, prove it with findings
230
+ 4. **Consider alternatives** — Give Agent DEEPCODE options when possible
231
+ 5. **Flag uncertainty** — If you're not sure, say so
232
+ 6. **Stay focused** — Analyze what was asked, note tangential issues separately
233
+
234
+ ---
235
+
236
+ ## WHAT GOOD ANALYSIS LOOKS LIKE
237
+
238
+ **Bad:**
239
+
240
+ > "The authentication is broken. Check the auth files."
241
+
242
+ **Good:**
243
+
244
+ > "The JWT validation fails for tokens expiring within 1 second. In `src/auth/validate.js` line 47, the expiry check uses `token.exp < now` but should use `token.exp <= now`. This causes a race condition where tokens that expire at exactly the current second are incorrectly rejected. You'll need to change the comparison operator. Also check `src/auth/refresh.js` line 23 which has the same pattern."
245
+
246
+ ---
247
+
248
+ ## REMEMBER
249
+
250
+ - Your job is to give Agent DEEPCODE everything they need to succeed
251
+ - Depth over speed — investigate thoroughly
252
+ - Be the expert who explains the "what" and "why"
253
+ - Agent DEEPCODE handles the "how" (implementation)
jules_branch/.claude/agents/security-vulnerability-scanner.md ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: security-vulnerability-scanner
3
+ description: Use this agent when you need to identify security vulnerabilities in code, perform security audits, or get a prioritized list of security issues to fix. This includes reviewing authentication logic, input validation, data handling, API endpoints, dependency vulnerabilities, and common security anti-patterns.\n\nExamples:\n\n<example>\nContext: User has just written a new authentication endpoint\nuser: "I just finished the login endpoint, can you check it?"\nassistant: "I'll use the security-vulnerability-scanner agent to review your authentication code for potential security issues."\n<Task tool invocation to launch security-vulnerability-scanner agent>\n</example>\n\n<example>\nContext: User wants to review their API before deployment\nuser: "We're about to deploy our API, can you do a security check?"\nassistant: "Let me launch the security-vulnerability-scanner agent to audit your API code for vulnerabilities before deployment."\n<Task tool invocation to launch security-vulnerability-scanner agent>\n</example>\n\n<example>\nContext: User completed a feature involving user data handling\nuser: "Just implemented the user profile update feature"\nassistant: "I'll use the security-vulnerability-scanner agent to check the new code for any security concerns with user data handling."\n<Task tool invocation to launch security-vulnerability-scanner agent>\n</example>
4
+ model: opus
5
+ color: yellow
6
+ ---
7
+
8
+ You are an elite application security researcher with deep expertise in vulnerability assessment, secure coding practices, and penetration testing. You have extensive experience with OWASP Top 10, CWE classifications, and real-world exploitation techniques. Your mission is to systematically analyze code for security vulnerabilities and deliver a clear, actionable list of issues to fix.
9
+
10
+ ## Your Approach
11
+
12
+ 1. **Systematic Analysis**: Methodically examine the code looking for:
13
+ - Injection vulnerabilities (SQL, NoSQL, Command, LDAP, XPath, etc.)
14
+ - Authentication and session management flaws
15
+ - Cross-Site Scripting (XSS) - reflected, stored, and DOM-based
16
+ - Insecure Direct Object References (IDOR)
17
+ - Security misconfigurations
18
+ - Sensitive data exposure
19
+ - Missing access controls
20
+ - Cross-Site Request Forgery (CSRF)
21
+ - Using components with known vulnerabilities
22
+ - Insufficient logging and monitoring
23
+ - Race conditions and TOCTOU issues
24
+ - Cryptographic weaknesses
25
+ - Path traversal vulnerabilities
26
+ - Deserialization vulnerabilities
27
+ - Server-Side Request Forgery (SSRF)
28
+
29
+ 2. **Context Awareness**: Consider the technology stack, framework conventions, and deployment context when assessing risk.
30
+
31
+ 3. **Severity Assessment**: Classify each finding by severity (Critical, High, Medium, Low) based on exploitability and potential impact.
32
+
33
+ ## Research Process
34
+
35
+ - Use available tools to read and explore the codebase
36
+ - Follow data flows from user input to sensitive operations
37
+ - Check configuration files for security settings
38
+ - Examine dependency files for known vulnerable packages
39
+ - Review authentication/authorization logic paths
40
+ - Analyze error handling and logging practices
41
+
42
+ ## Output Format
43
+
44
+ After your analysis, provide a concise, prioritized list in this format:
45
+
46
+ ### Security Vulnerabilities Found
47
+
48
+ **Critical:**
49
+
50
+ - [Brief description] — File: `path/to/file.ext` (line X)
51
+
52
+ **High:**
53
+
54
+ - [Brief description] — File: `path/to/file.ext` (line X)
55
+
56
+ **Medium:**
57
+
58
+ - [Brief description] — File: `path/to/file.ext` (line X)
59
+
60
+ **Low:**
61
+
62
+ - [Brief description] — File: `path/to/file.ext` (line X)
63
+
64
+ ---
65
+
66
+ **Summary:** X critical, X high, X medium, X low issues found.
67
+
68
+ ## Guidelines
69
+
70
+ - Be specific about the vulnerability type and exact location
71
+ - Keep descriptions concise (one line each)
72
+ - Only report actual vulnerabilities, not theoretical concerns or style issues
73
+ - If no vulnerabilities are found in a category, omit that category
74
+ - If the codebase is clean, clearly state that no significant vulnerabilities were identified
75
+ - Do not include lengthy explanations or remediation steps in the list (keep it scannable)
76
+ - Focus on recently modified or newly written code unless explicitly asked to scan the entire codebase
77
+
78
+ Your goal is to give the developer a quick, actionable checklist they can work through to improve their application's security posture.
jules_branch/.claude/commands/deepreview.md ADDED
@@ -0,0 +1,591 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code Review Command
2
+
3
+ Comprehensive code review using multiple deep dive agents to analyze git diff for correctness, security, code quality, and tech stack compliance, followed by automated fixes using deepcode agents.
4
+
5
+ ## Usage
6
+
7
+ This command analyzes all changes in the git diff and verifies:
8
+
9
+ 1. **Invalid code based on tech stack** (HIGHEST PRIORITY)
10
+ 2. Security vulnerabilities
11
+ 3. Code quality issues (dirty code)
12
+ 4. Implementation correctness
13
+
14
+ Then automatically fixes any issues found.
15
+
16
+ ### Optional Arguments
17
+
18
+ - **Target branch**: Optional branch name to compare against (defaults to `main` or `master` if not provided)
19
+ - Example: `@deepreview develop` - compares current branch against `develop`
20
+ - If not provided, automatically detects `main` or `master` as the target branch
21
+
22
+ ## Instructions
23
+
24
+ ### Phase 1: Get Git Diff
25
+
26
+ 1. **Determine the current branch and target branch**
27
+
28
+ ```bash
29
+ # Get current branch name
30
+ CURRENT_BRANCH=$(git branch --show-current)
31
+ echo "Current branch: $CURRENT_BRANCH"
32
+
33
+ # Get target branch from user argument or detect default
34
+ # If user provided a target branch as argument, use it
35
+ # Otherwise, detect main or master
36
+ TARGET_BRANCH="${1:-}" # First argument if provided
37
+
38
+ if [ -z "$TARGET_BRANCH" ]; then
39
+ # Check if main exists
40
+ if git show-ref --verify --quiet refs/heads/main || git show-ref --verify --quiet refs/remotes/origin/main; then
41
+ TARGET_BRANCH="main"
42
+ # Check if master exists
43
+ elif git show-ref --verify --quiet refs/heads/master || git show-ref --verify --quiet refs/remotes/origin/master; then
44
+ TARGET_BRANCH="master"
45
+ else
46
+ echo "Error: Could not find main or master branch. Please specify target branch."
47
+ exit 1
48
+ fi
49
+ fi
50
+
51
+ echo "Target branch: $TARGET_BRANCH"
52
+
53
+ # Verify target branch exists
54
+ if ! git show-ref --verify --quiet refs/heads/$TARGET_BRANCH && ! git show-ref --verify --quiet refs/remotes/origin/$TARGET_BRANCH; then
55
+ echo "Error: Target branch '$TARGET_BRANCH' does not exist."
56
+ exit 1
57
+ fi
58
+ ```
59
+
60
+ **Note:** The target branch can be provided as an optional argument. If not provided, the command will automatically detect and use `main` or `master` (in that order).
61
+
62
+ 2. **Compare current branch against target branch**
63
+
64
+ ```bash
65
+ # Fetch latest changes from remote (optional but recommended)
66
+ git fetch origin
67
+
68
+ # Try local branch first, fallback to remote if local doesn't exist
69
+ if git show-ref --verify --quiet refs/heads/$TARGET_BRANCH; then
70
+ TARGET_REF=$TARGET_BRANCH
71
+ elif git show-ref --verify --quiet refs/remotes/origin/$TARGET_BRANCH; then
72
+ TARGET_REF=origin/$TARGET_BRANCH
73
+ else
74
+ echo "Error: Target branch '$TARGET_BRANCH' not found locally or remotely."
75
+ exit 1
76
+ fi
77
+
78
+ # Get diff between current branch and target branch
79
+ git diff $TARGET_REF...HEAD
80
+ ```
81
+
82
+ **Note:** Use `...` (three dots) to show changes between the common ancestor and HEAD, or `..` (two dots) to show changes between the branches directly. The command uses `$TARGET_BRANCH` variable set in step 1.
83
+
84
+ 3. **Get list of changed files between branches**
85
+
86
+ ```bash
87
+ # List files changed between current branch and target branch
88
+ git diff --name-only $TARGET_REF...HEAD
89
+
90
+ # Get detailed file status
91
+ git diff --name-status $TARGET_REF...HEAD
92
+
93
+ # Show file changes with statistics
94
+ git diff --stat $TARGET_REF...HEAD
95
+ ```
96
+
97
+ 4. **Get the current working directory diff** (uncommitted changes)
98
+
99
+ ```bash
100
+ # Uncommitted changes in working directory
101
+ git diff HEAD
102
+
103
+ # Staged changes
104
+ git diff --cached
105
+
106
+ # All changes (staged + unstaged)
107
+ git diff HEAD
108
+ git diff --cached
109
+ ```
110
+
111
+ 5. **Combine branch comparison with uncommitted changes**
112
+
113
+ The review should analyze:
114
+ - **Changes between current branch and target branch** (committed changes)
115
+ - **Uncommitted changes** (if any)
116
+
117
+ ```bash
118
+ # Get all changes: branch diff + uncommitted
119
+ git diff $TARGET_REF...HEAD > branch-changes.diff
120
+ git diff HEAD >> branch-changes.diff
121
+ git diff --cached >> branch-changes.diff
122
+
123
+ # Or get combined diff (recommended approach)
124
+ git diff $TARGET_REF...HEAD
125
+ git diff HEAD
126
+ git diff --cached
127
+ ```
128
+
129
+ 6. **Verify branch relationship**
130
+
131
+ ```bash
132
+ # Check if current branch is ahead/behind target branch
133
+ git rev-list --left-right --count $TARGET_REF...HEAD
134
+
135
+ # Show commit log differences
136
+ git log $TARGET_REF..HEAD --oneline
137
+
138
+ # Show summary of branch relationship
139
+ AHEAD=$(git rev-list --left-right --count $TARGET_REF...HEAD | cut -f1)
140
+ BEHIND=$(git rev-list --left-right --count $TARGET_REF...HEAD | cut -f2)
141
+ echo "Branch is $AHEAD commits ahead and $BEHIND commits behind $TARGET_BRANCH"
142
+ ```
143
+
144
+ 7. **Understand the tech stack** (for validation):
145
+ - **Node.js**: >=22.0.0 <23.0.0
146
+ - **TypeScript**: 5.9.3
147
+ - **React**: 19.2.3
148
+ - **Express**: 5.2.1
149
+ - **Electron**: 39.2.7
150
+ - **Vite**: 7.3.0
151
+ - **Vitest**: 4.0.16
152
+ - Check `package.json` files for exact versions
153
+
154
+ ### Phase 2: Deep Dive Analysis (5 Agents)
155
+
156
+ Launch 5 separate deep dive agents, each with a specific focus area. Each agent should be invoked with the `@deepdive` agent and given the git diff (comparing current branch against target branch) along with their specific instructions.
157
+
158
+ **Important:** All agents should analyze the diff between the current branch and target branch (`git diff $TARGET_REF...HEAD`), plus any uncommitted changes. This ensures the review covers all changes that will be merged. The target branch is determined from the optional argument or defaults to main/master.
159
+
160
+ #### Agent 1: Tech Stack Validation (HIGHEST PRIORITY)
161
+
162
+ **Focus:** Verify code is valid for the tech stack
163
+
164
+ **Instructions for Agent 1:**
165
+
166
+ ```
167
+ Analyze the git diff for invalid code based on the tech stack:
168
+
169
+ 1. **TypeScript/JavaScript Syntax**
170
+ - Check for valid TypeScript syntax (no invalid type annotations, correct import/export syntax)
171
+ - Verify Node.js API usage is compatible with Node.js >=22.0.0 <23.0.0
172
+ - Check for deprecated APIs or features not available in the Node.js version
173
+ - Verify ES module syntax (type: "module" in package.json)
174
+
175
+ 2. **React 19.2.3 Compatibility**
176
+ - Check for deprecated React APIs or patterns
177
+ - Verify hooks usage is correct for React 19
178
+ - Check for invalid JSX syntax
179
+ - Verify component patterns match React 19 conventions
180
+
181
+ 3. **Express 5.2.1 Compatibility**
182
+ - Check for deprecated Express APIs
183
+ - Verify middleware usage is correct for Express 5
184
+ - Check request/response handling patterns
185
+
186
+ 4. **Type Safety**
187
+ - Verify TypeScript types are correctly used
188
+ - Check for `any` types that should be properly typed
189
+ - Verify type imports/exports are correct
190
+ - Check for missing type definitions
191
+
192
+ 5. **Build System Compatibility**
193
+ - Verify Vite-specific code (imports, config) is valid
194
+ - Check Electron-specific APIs are used correctly
195
+ - Verify module resolution paths are correct
196
+
197
+ 6. **Package Dependencies**
198
+ - Check for imports from packages not in package.json
199
+ - Verify version compatibility between dependencies
200
+ - Check for circular dependencies
201
+
202
+ Provide a detailed report with:
203
+ - File paths and line numbers of invalid code
204
+ - Specific error description (what's wrong and why)
205
+ - Expected vs actual behavior
206
+ - Priority level (CRITICAL for build-breaking issues)
207
+ ```
208
+
209
+ #### Agent 2: Security Vulnerability Scanner
210
+
211
+ **Focus:** Security issues and vulnerabilities
212
+
213
+ **Instructions for Agent 2:**
214
+
215
+ ```
216
+ Analyze the git diff for security vulnerabilities:
217
+
218
+ 1. **Injection Vulnerabilities**
219
+ - SQL injection (if applicable)
220
+ - Command injection (exec, spawn, etc.)
221
+ - Path traversal vulnerabilities
222
+ - XSS vulnerabilities in React components
223
+
224
+ 2. **Authentication & Authorization**
225
+ - Missing authentication checks
226
+ - Insecure token handling
227
+ - Authorization bypasses
228
+ - Session management issues
229
+
230
+ 3. **Data Handling**
231
+ - Unsafe deserialization
232
+ - Insecure file operations
233
+ - Missing input validation
234
+ - Sensitive data exposure (secrets, tokens, passwords)
235
+
236
+ 4. **Dependencies**
237
+ - Known vulnerable packages
238
+ - Insecure dependency versions
239
+ - Missing security patches
240
+
241
+ 5. **API Security**
242
+ - Missing CORS configuration
243
+ - Insecure API endpoints
244
+ - Missing rate limiting
245
+ - Insecure WebSocket connections
246
+
247
+ 6. **Electron-Specific**
248
+ - Insecure IPC communication
249
+ - Missing context isolation checks
250
+ - Insecure preload scripts
251
+ - Missing CSP headers
252
+
253
+ Provide a detailed report with:
254
+ - Vulnerability type and severity (CRITICAL, HIGH, MEDIUM, LOW)
255
+ - File paths and line numbers
256
+ - Attack vector description
257
+ - Recommended fix approach
258
+ ```
259
+
260
+ #### Agent 3: Code Quality & Clean Code
261
+
262
+ **Focus:** Dirty code, code smells, and quality issues
263
+
264
+ **Instructions for Agent 3:**
265
+
266
+ ```
267
+ Analyze the git diff for code quality issues:
268
+
269
+ 1. **Code Smells**
270
+ - Long functions/methods (>50 lines)
271
+ - High cyclomatic complexity
272
+ - Duplicate code
273
+ - Dead code
274
+ - Magic numbers/strings
275
+
276
+ 2. **Best Practices**
277
+ - Missing error handling
278
+ - Inconsistent naming conventions
279
+ - Poor separation of concerns
280
+ - Tight coupling
281
+ - Missing comments for complex logic
282
+
283
+ 3. **Performance Issues**
284
+ - Inefficient algorithms
285
+ - Memory leaks (event listeners, subscriptions)
286
+ - Unnecessary re-renders in React
287
+ - Missing memoization where needed
288
+ - Inefficient database queries (if applicable)
289
+
290
+ 4. **Maintainability**
291
+ - Hard-coded values
292
+ - Missing type definitions
293
+ - Inconsistent code style
294
+ - Poor file organization
295
+ - Missing tests for new code
296
+
297
+ 5. **React-Specific**
298
+ - Missing key props in lists
299
+ - Direct state mutations
300
+ - Missing cleanup in useEffect
301
+ - Unnecessary useState/useEffect
302
+ - Prop drilling issues
303
+
304
+ Provide a detailed report with:
305
+ - Issue type and severity
306
+ - File paths and line numbers
307
+ - Description of the problem
308
+ - Impact on maintainability/performance
309
+ - Recommended refactoring approach
310
+ ```
311
+
312
+ #### Agent 4: Implementation Correctness
313
+
314
+ **Focus:** Verify code implements requirements correctly
315
+
316
+ **Instructions for Agent 4:**
317
+
318
+ ```
319
+ Analyze the git diff for implementation correctness:
320
+
321
+ 1. **Logic Errors**
322
+ - Incorrect conditional logic
323
+ - Wrong variable usage
324
+ - Off-by-one errors
325
+ - Race conditions
326
+ - Missing null/undefined checks
327
+
328
+ 2. **Functional Requirements**
329
+ - Missing features from requirements
330
+ - Incorrect feature implementation
331
+ - Edge cases not handled
332
+ - Missing validation
333
+
334
+ 3. **Integration Issues**
335
+ - Incorrect API usage
336
+ - Wrong data format handling
337
+ - Missing error handling for external calls
338
+ - Incorrect state management
339
+
340
+ 4. **Type Errors**
341
+ - Type mismatches
342
+ - Missing type guards
343
+ - Incorrect type assertions
344
+ - Unsafe type operations
345
+
346
+ 5. **Testing Gaps**
347
+ - Missing unit tests
348
+ - Missing integration tests
349
+ - Tests don't cover edge cases
350
+ - Tests are incorrect
351
+
352
+ Provide a detailed report with:
353
+ - Issue description
354
+ - File paths and line numbers
355
+ - Expected vs actual behavior
356
+ - Steps to reproduce (if applicable)
357
+ - Recommended fix
358
+ ```
359
+
360
+ #### Agent 5: Architecture & Design Patterns
361
+
362
+ **Focus:** Architectural issues and design pattern violations
363
+
364
+ **Instructions for Agent 5:**
365
+
366
+ ```
367
+ Analyze the git diff for architectural and design issues:
368
+
369
+ 1. **Architecture Violations**
370
+ - Violation of project structure patterns
371
+ - Incorrect layer separation
372
+ - Missing abstractions
373
+ - Tight coupling between modules
374
+
375
+ 2. **Design Patterns**
376
+ - Incorrect pattern usage
377
+ - Missing patterns where needed
378
+ - Anti-patterns
379
+
380
+ 3. **Project-Specific Patterns**
381
+ - Check against project documentation (docs/ folder)
382
+ - Verify route organization (server routes)
383
+ - Check provider patterns (server providers)
384
+ - Verify component organization (UI components)
385
+
386
+ 4. **API Design**
387
+ - RESTful API violations
388
+ - Inconsistent response formats
389
+ - Missing error handling
390
+ - Incorrect status codes
391
+
392
+ 5. **State Management**
393
+ - Incorrect state management patterns
394
+ - Missing state normalization
395
+ - Inefficient state updates
396
+
397
+ Provide a detailed report with:
398
+ - Architectural issue description
399
+ - File paths and affected areas
400
+ - Impact on system design
401
+ - Recommended architectural changes
402
+ ```
403
+
404
+ ### Phase 3: Consolidate Findings
405
+
406
+ After all 5 deep dive agents complete their analysis:
407
+
408
+ 1. **Collect all findings** from each agent
409
+ 2. **Prioritize issues**:
410
+ - CRITICAL: Tech stack invalid code (build-breaking)
411
+ - HIGH: Security vulnerabilities, critical logic errors
412
+ - MEDIUM: Code quality issues, architectural problems
413
+ - LOW: Minor code smells, style issues
414
+
415
+ 3. **Group by file** to understand impact per file
416
+ 4. **Create a master report** summarizing all findings
417
+
418
+ ### Phase 4: Deepcode Fixes (5 Agents)
419
+
420
+ Launch 5 deepcode agents to fix the issues found. Each agent should be invoked with the `@deepcode` agent.
421
+
422
+ #### Deepcode Agent 1: Fix Tech Stack Invalid Code
423
+
424
+ **Priority:** CRITICAL - Fix first
425
+
426
+ **Instructions:**
427
+
428
+ ```
429
+ Fix all invalid code based on tech stack issues identified by Agent 1.
430
+
431
+ Focus on:
432
+ 1. Fixing TypeScript syntax errors
433
+ 2. Updating deprecated Node.js APIs
434
+ 3. Fixing React 19 compatibility issues
435
+ 4. Correcting Express 5 API usage
436
+ 5. Fixing type errors
437
+ 6. Resolving build-breaking issues
438
+
439
+ After fixes, verify:
440
+ - Code compiles without errors
441
+ - TypeScript types are correct
442
+ - No deprecated API usage
443
+ ```
444
+
445
+ #### Deepcode Agent 2: Fix Security Vulnerabilities
446
+
447
+ **Priority:** HIGH
448
+
449
+ **Instructions:**
450
+
451
+ ```
452
+ Fix all security vulnerabilities identified by Agent 2.
453
+
454
+ Focus on:
455
+ 1. Adding input validation
456
+ 2. Fixing injection vulnerabilities
457
+ 3. Securing authentication/authorization
458
+ 4. Fixing insecure data handling
459
+ 5. Updating vulnerable dependencies
460
+ 6. Securing Electron IPC
461
+
462
+ After fixes, verify:
463
+ - Security vulnerabilities are addressed
464
+ - No sensitive data exposure
465
+ - Proper authentication/authorization
466
+ ```
467
+
468
+ #### Deepcode Agent 3: Refactor Dirty Code
469
+
470
+ **Priority:** MEDIUM
471
+
472
+ **Instructions:**
473
+
474
+ ```
475
+ Refactor code quality issues identified by Agent 3.
476
+
477
+ Focus on:
478
+ 1. Extracting long functions
479
+ 2. Reducing complexity
480
+ 3. Removing duplicate code
481
+ 4. Adding error handling
482
+ 5. Improving React component structure
483
+ 6. Adding missing comments
484
+
485
+ After fixes, verify:
486
+ - Code follows best practices
487
+ - No code smells remain
488
+ - Performance optimizations applied
489
+ ```
490
+
491
+ #### Deepcode Agent 4: Fix Implementation Errors
492
+
493
+ **Priority:** HIGH
494
+
495
+ **Instructions:**
496
+
497
+ ```
498
+ Fix implementation correctness issues identified by Agent 4.
499
+
500
+ Focus on:
501
+ 1. Fixing logic errors
502
+ 2. Adding missing features
503
+ 3. Handling edge cases
504
+ 4. Fixing type errors
505
+ 5. Adding missing tests
506
+
507
+ After fixes, verify:
508
+ - Logic is correct
509
+ - Edge cases handled
510
+ - Tests pass
511
+ ```
512
+
513
+ #### Deepcode Agent 5: Fix Architectural Issues
514
+
515
+ **Priority:** MEDIUM
516
+
517
+ **Instructions:**
518
+
519
+ ```
520
+ Fix architectural issues identified by Agent 5.
521
+
522
+ Focus on:
523
+ 1. Correcting architecture violations
524
+ 2. Applying proper design patterns
525
+ 3. Fixing API design issues
526
+ 4. Improving state management
527
+ 5. Following project patterns
528
+
529
+ After fixes, verify:
530
+ - Architecture is sound
531
+ - Patterns are correctly applied
532
+ - Code follows project structure
533
+ ```
534
+
535
+ ### Phase 5: Verification
536
+
537
+ After all fixes are complete:
538
+
539
+ 1. **Run TypeScript compilation check**
540
+
541
+ ```bash
542
+ npm run build:packages
543
+ ```
544
+
545
+ 2. **Run linting**
546
+
547
+ ```bash
548
+ npm run lint
549
+ ```
550
+
551
+ 3. **Run tests** (if applicable)
552
+
553
+ ```bash
554
+ npm run test:server
555
+ npm run test
556
+ ```
557
+
558
+ 4. **Verify git diff** shows only intended changes
559
+
560
+ ```bash
561
+ git diff HEAD
562
+ ```
563
+
564
+ 5. **Create summary report**:
565
+ - Issues found by each agent
566
+ - Issues fixed by each agent
567
+ - Remaining issues (if any)
568
+ - Verification results
569
+
570
+ ## Workflow Summary
571
+
572
+ 1. ✅ Accept optional target branch argument (defaults to main/master if not provided)
573
+ 2. ✅ Determine current branch and target branch (from argument or auto-detect main/master)
574
+ 3. ✅ Get git diff comparing current branch against target branch (`git diff $TARGET_REF...HEAD`)
575
+ 4. ✅ Include uncommitted changes in analysis (`git diff HEAD`, `git diff --cached`)
576
+ 5. ✅ Launch 5 deep dive agents (parallel analysis) with branch diff
577
+ 6. ✅ Consolidate findings and prioritize
578
+ 7. ✅ Launch 5 deepcode agents (sequential fixes, priority order)
579
+ 8. ✅ Verify fixes with build/lint/test
580
+ 9. ✅ Report summary
581
+
582
+ ## Notes
583
+
584
+ - **Tech stack validation is HIGHEST PRIORITY** - invalid code must be fixed first
585
+ - **Target branch argument**: The command accepts an optional target branch name as the first argument. If not provided, it automatically detects and uses `main` or `master` (in that order)
586
+ - Each deep dive agent should work independently and provide comprehensive analysis
587
+ - Deepcode agents should fix issues in priority order
588
+ - All fixes should maintain existing functionality
589
+ - If an agent finds no issues in their domain, they should report "No issues found"
590
+ - If fixes introduce new issues, they should be caught in verification phase
591
+ - The target branch is validated to ensure it exists (locally or remotely) before proceeding with the review
jules_branch/.claude/commands/gh-issue.md ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # GitHub Issue Fix Command
2
+
3
+ Fetch a GitHub issue by number, verify it's a real issue, and fix it if valid.
4
+
5
+ ## Usage
6
+
7
+ This command accepts a GitHub issue number as input (e.g., `123`).
8
+
9
+ ## Instructions
10
+
11
+ 1. **Get the issue number from the user**
12
+ - The issue number should be provided as an argument to this command
13
+ - If no number is provided, ask the user for it
14
+
15
+ 2. **Fetch the GitHub issue**
16
+ - Determine the current project path (check if there's a current project context)
17
+ - Verify the project has a GitHub remote:
18
+ ```bash
19
+ git remote get-url origin
20
+ ```
21
+ - Fetch the issue details using GitHub CLI:
22
+ ```bash
23
+ gh issue view <ISSUE_NUMBER> --json number,title,state,author,createdAt,labels,url,body,assignees
24
+ ```
25
+ - If the command fails, report the error and stop
26
+
27
+ 3. **Verify the issue is real and valid**
28
+ - Check that the issue exists (not 404)
29
+ - Check the issue state:
30
+ - If **closed**: Inform the user and ask if they still want to proceed
31
+ - If **open**: Proceed with validation
32
+ - Review the issue content:
33
+ - Read the title and body to understand what needs to be fixed
34
+ - Check labels for context (bug, enhancement, etc.)
35
+ - Note any assignees or linked PRs
36
+
37
+ 4. **Validate the issue**
38
+ - Determine if this is a legitimate issue that needs fixing:
39
+ - Is the description clear and actionable?
40
+ - Does it describe a real problem or feature request?
41
+ - Are there any obvious signs it's spam or invalid?
42
+ - If the issue seems invalid or unclear:
43
+ - Report findings to the user
44
+ - Ask if they want to proceed anyway
45
+ - Stop if user confirms it's not valid
46
+
47
+ 5. **If the issue is valid, proceed to fix it**
48
+ - Analyze what needs to be done based on the issue description
49
+ - Check the current codebase state:
50
+ - Run relevant tests to see current behavior
51
+ - Check if the issue is already fixed
52
+ - Look for related code that might need changes
53
+ - Implement the fix:
54
+ - Make necessary code changes
55
+ - Update or add tests as needed
56
+ - Ensure the fix addresses the issue description
57
+ - Verify the fix:
58
+ - Run tests to ensure nothing broke
59
+ - If possible, manually verify the fix addresses the issue
60
+
61
+ 6. **Report summary**
62
+ - Issue number and title
63
+ - Issue state (open/closed)
64
+ - Whether the issue was validated as real
65
+ - What was fixed (if anything)
66
+ - Any tests that were updated or added
67
+ - Next steps (if any)
68
+
69
+ ## Error Handling
70
+
71
+ - If GitHub CLI (`gh`) is not installed or authenticated, report error and stop
72
+ - If the project doesn't have a GitHub remote, report error and stop
73
+ - If the issue number doesn't exist, report error and stop
74
+ - If the issue is unclear or invalid, report findings and ask user before proceeding
jules_branch/.claude/commands/release.md ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Release Command
2
+
3
+ Bump the package.json version (major, minor, or patch) and build the Electron app with the new version.
4
+
5
+ ## Usage
6
+
7
+ This command accepts a version bump type as input:
8
+
9
+ - `patch` - Bump patch version (0.1.0 -> 0.1.1)
10
+ - `minor` - Bump minor version (0.1.0 -> 0.2.0)
11
+ - `major` - Bump major version (0.1.0 -> 1.0.0)
12
+
13
+ ## Instructions
14
+
15
+ 1. **Get the bump type from the user**
16
+ - The bump type should be provided as an argument (patch, minor, or major)
17
+ - If no type is provided, ask the user which type they want
18
+
19
+ 2. **Bump the version**
20
+ - Run the version bump script:
21
+ ```bash
22
+ node apps/ui/scripts/bump-version.mjs <type>
23
+ ```
24
+ - This updates both `apps/ui/package.json` and `apps/server/package.json` with the new version (keeps them in sync)
25
+ - Verify the version was updated correctly by checking the output
26
+
27
+ 3. **Build the Electron app**
28
+ - Run the electron build:
29
+ ```bash
30
+ npm run build:electron --workspace=apps/ui
31
+ ```
32
+ - The build process automatically:
33
+ - Uses the version from `package.json` for artifact names (e.g., `Automaker-1.2.3-x64.zip`)
34
+ - Injects the version into the app via Vite's `__APP_VERSION__` constant
35
+ - Displays the version below the logo in the sidebar
36
+
37
+ 4. **Commit the version bump**
38
+ - Stage the updated package.json files:
39
+ ```bash
40
+ git add apps/ui/package.json apps/server/package.json
41
+ ```
42
+ - Commit with a release message:
43
+ ```bash
44
+ git commit -m "chore: release v<version>"
45
+ ```
46
+
47
+ 5. **Create and push the git tag**
48
+ - Create an annotated tag for the release:
49
+ ```bash
50
+ git tag -a v<version> -m "Release v<version>"
51
+ ```
52
+ - Push the commit and tag to remote:
53
+ ```bash
54
+ git push && git push --tags
55
+ ```
56
+
57
+ 6. **Verify the release**
58
+ - Check that the build completed successfully
59
+ - Confirm the version appears correctly in the built artifacts
60
+ - The version will be displayed in the app UI below the logo
61
+ - Verify the tag is visible on the remote repository
62
+
63
+ ## Version Centralization
64
+
65
+ The version is centralized and synchronized in both `apps/ui/package.json` and `apps/server/package.json`:
66
+
67
+ - **Electron builds**: Automatically read from `apps/ui/package.json` via electron-builder's `${version}` variable in `artifactName`
68
+ - **App display**: Injected at build time via Vite's `define` config as `__APP_VERSION__` constant (defined in `apps/ui/vite.config.mts`)
69
+ - **Server API**: Read from `apps/server/package.json` via `apps/server/src/lib/version.ts` utility (used in health check endpoints)
70
+ - **Type safety**: Defined in `apps/ui/src/vite-env.d.ts` as `declare const __APP_VERSION__: string`
71
+
72
+ This ensures consistency across:
73
+
74
+ - Build artifact names (e.g., `Automaker-1.2.3-x64.zip`)
75
+ - App UI display (shown as `v1.2.3` below the logo in `apps/ui/src/components/layout/sidebar/components/automaker-logo.tsx`)
76
+ - Server health endpoints (`/` and `/detailed`)
77
+ - Package metadata (both UI and server packages stay in sync)
jules_branch/.claude/commands/review.md ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code Review Command
2
+
3
+ Comprehensive code review using multiple deep dive agents to analyze git diff for correctness, security, code quality, and tech stack compliance, followed by automated fixes using deepcode agents.
4
+
5
+ ## Usage
6
+
7
+ This command analyzes all changes in the git diff and verifies:
8
+
9
+ 1. **Invalid code based on tech stack** (HIGHEST PRIORITY)
10
+ 2. Security vulnerabilities
11
+ 3. Code quality issues (dirty code)
12
+ 4. Implementation correctness
13
+
14
+ Then automatically fixes any issues found.
15
+
16
+ ## Instructions
17
+
18
+ ### Phase 1: Get Git Diff
19
+
20
+ 1. **Get the current git diff**
21
+
22
+ ```bash
23
+ git diff HEAD
24
+ ```
25
+
26
+ If you need staged changes instead:
27
+
28
+ ```bash
29
+ git diff --cached
30
+ ```
31
+
32
+ Or for a specific commit range:
33
+
34
+ ```bash
35
+ git diff <base-branch>
36
+ ```
37
+
38
+ 2. **Get list of changed files**
39
+
40
+ ```bash
41
+ git diff --name-only HEAD
42
+ ```
43
+
44
+ 3. **Understand the tech stack** (for validation):
45
+ - **Node.js**: >=22.0.0 <23.0.0
46
+ - **TypeScript**: 5.9.3
47
+ - **React**: 19.2.3
48
+ - **Express**: 5.2.1
49
+ - **Electron**: 39.2.7
50
+ - **Vite**: 7.3.0
51
+ - **Vitest**: 4.0.16
52
+ - Check `package.json` files for exact versions
53
+
54
+ ### Phase 2: Deep Dive Analysis (5 Agents)
55
+
56
+ Launch 5 separate deep dive agents, each with a specific focus area. Each agent should be invoked with the `@deepdive` agent and given the git diff along with their specific instructions.
57
+
58
+ #### Agent 1: Tech Stack Validation (HIGHEST PRIORITY)
59
+
60
+ **Focus:** Verify code is valid for the tech stack
61
+
62
+ **Instructions for Agent 1:**
63
+
64
+ ```
65
+ Analyze the git diff for invalid code based on the tech stack:
66
+
67
+ 1. **TypeScript/JavaScript Syntax**
68
+ - Check for valid TypeScript syntax (no invalid type annotations, correct import/export syntax)
69
+ - Verify Node.js API usage is compatible with Node.js >=22.0.0 <23.0.0
70
+ - Check for deprecated APIs or features not available in the Node.js version
71
+ - Verify ES module syntax (type: "module" in package.json)
72
+
73
+ 2. **React 19.2.3 Compatibility**
74
+ - Check for deprecated React APIs or patterns
75
+ - Verify hooks usage is correct for React 19
76
+ - Check for invalid JSX syntax
77
+ - Verify component patterns match React 19 conventions
78
+
79
+ 3. **Express 5.2.1 Compatibility**
80
+ - Check for deprecated Express APIs
81
+ - Verify middleware usage is correct for Express 5
82
+ - Check request/response handling patterns
83
+
84
+ 4. **Type Safety**
85
+ - Verify TypeScript types are correctly used
86
+ - Check for `any` types that should be properly typed
87
+ - Verify type imports/exports are correct
88
+ - Check for missing type definitions
89
+
90
+ 5. **Build System Compatibility**
91
+ - Verify Vite-specific code (imports, config) is valid
92
+ - Check Electron-specific APIs are used correctly
93
+ - Verify module resolution paths are correct
94
+
95
+ 6. **Package Dependencies**
96
+ - Check for imports from packages not in package.json
97
+ - Verify version compatibility between dependencies
98
+ - Check for circular dependencies
99
+
100
+ Provide a detailed report with:
101
+ - File paths and line numbers of invalid code
102
+ - Specific error description (what's wrong and why)
103
+ - Expected vs actual behavior
104
+ - Priority level (CRITICAL for build-breaking issues)
105
+ ```
106
+
107
+ #### Agent 2: Security Vulnerability Scanner
108
+
109
+ **Focus:** Security issues and vulnerabilities
110
+
111
+ **Instructions for Agent 2:**
112
+
113
+ ```
114
+ Analyze the git diff for security vulnerabilities:
115
+
116
+ 1. **Injection Vulnerabilities**
117
+ - SQL injection (if applicable)
118
+ - Command injection (exec, spawn, etc.)
119
+ - Path traversal vulnerabilities
120
+ - XSS vulnerabilities in React components
121
+
122
+ 2. **Authentication & Authorization**
123
+ - Missing authentication checks
124
+ - Insecure token handling
125
+ - Authorization bypasses
126
+ - Session management issues
127
+
128
+ 3. **Data Handling**
129
+ - Unsafe deserialization
130
+ - Insecure file operations
131
+ - Missing input validation
132
+ - Sensitive data exposure (secrets, tokens, passwords)
133
+
134
+ 4. **Dependencies**
135
+ - Known vulnerable packages
136
+ - Insecure dependency versions
137
+ - Missing security patches
138
+
139
+ 5. **API Security**
140
+ - Missing CORS configuration
141
+ - Insecure API endpoints
142
+ - Missing rate limiting
143
+ - Insecure WebSocket connections
144
+
145
+ 6. **Electron-Specific**
146
+ - Insecure IPC communication
147
+ - Missing context isolation checks
148
+ - Insecure preload scripts
149
+ - Missing CSP headers
150
+
151
+ Provide a detailed report with:
152
+ - Vulnerability type and severity (CRITICAL, HIGH, MEDIUM, LOW)
153
+ - File paths and line numbers
154
+ - Attack vector description
155
+ - Recommended fix approach
156
+ ```
157
+
158
+ #### Agent 3: Code Quality & Clean Code
159
+
160
+ **Focus:** Dirty code, code smells, and quality issues
161
+
162
+ **Instructions for Agent 3:**
163
+
164
+ ```
165
+ Analyze the git diff for code quality issues:
166
+
167
+ 1. **Code Smells**
168
+ - Long functions/methods (>50 lines)
169
+ - High cyclomatic complexity
170
+ - Duplicate code
171
+ - Dead code
172
+ - Magic numbers/strings
173
+
174
+ 2. **Best Practices**
175
+ - Missing error handling
176
+ - Inconsistent naming conventions
177
+ - Poor separation of concerns
178
+ - Tight coupling
179
+ - Missing comments for complex logic
180
+
181
+ 3. **Performance Issues**
182
+ - Inefficient algorithms
183
+ - Memory leaks (event listeners, subscriptions)
184
+ - Unnecessary re-renders in React
185
+ - Missing memoization where needed
186
+ - Inefficient database queries (if applicable)
187
+
188
+ 4. **Maintainability**
189
+ - Hard-coded values
190
+ - Missing type definitions
191
+ - Inconsistent code style
192
+ - Poor file organization
193
+ - Missing tests for new code
194
+
195
+ 5. **React-Specific**
196
+ - Missing key props in lists
197
+ - Direct state mutations
198
+ - Missing cleanup in useEffect
199
+ - Unnecessary useState/useEffect
200
+ - Prop drilling issues
201
+
202
+ Provide a detailed report with:
203
+ - Issue type and severity
204
+ - File paths and line numbers
205
+ - Description of the problem
206
+ - Impact on maintainability/performance
207
+ - Recommended refactoring approach
208
+ ```
209
+
210
+ #### Agent 4: Implementation Correctness
211
+
212
+ **Focus:** Verify code implements requirements correctly
213
+
214
+ **Instructions for Agent 4:**
215
+
216
+ ```
217
+ Analyze the git diff for implementation correctness:
218
+
219
+ 1. **Logic Errors**
220
+ - Incorrect conditional logic
221
+ - Wrong variable usage
222
+ - Off-by-one errors
223
+ - Race conditions
224
+ - Missing null/undefined checks
225
+
226
+ 2. **Functional Requirements**
227
+ - Missing features from requirements
228
+ - Incorrect feature implementation
229
+ - Edge cases not handled
230
+ - Missing validation
231
+
232
+ 3. **Integration Issues**
233
+ - Incorrect API usage
234
+ - Wrong data format handling
235
+ - Missing error handling for external calls
236
+ - Incorrect state management
237
+
238
+ 4. **Type Errors**
239
+ - Type mismatches
240
+ - Missing type guards
241
+ - Incorrect type assertions
242
+ - Unsafe type operations
243
+
244
+ 5. **Testing Gaps**
245
+ - Missing unit tests
246
+ - Missing integration tests
247
+ - Tests don't cover edge cases
248
+ - Tests are incorrect
249
+
250
+ Provide a detailed report with:
251
+ - Issue description
252
+ - File paths and line numbers
253
+ - Expected vs actual behavior
254
+ - Steps to reproduce (if applicable)
255
+ - Recommended fix
256
+ ```
257
+
258
+ #### Agent 5: Architecture & Design Patterns
259
+
260
+ **Focus:** Architectural issues and design pattern violations
261
+
262
+ **Instructions for Agent 5:**
263
+
264
+ ```
265
+ Analyze the git diff for architectural and design issues:
266
+
267
+ 1. **Architecture Violations**
268
+ - Violation of project structure patterns
269
+ - Incorrect layer separation
270
+ - Missing abstractions
271
+ - Tight coupling between modules
272
+
273
+ 2. **Design Patterns**
274
+ - Incorrect pattern usage
275
+ - Missing patterns where needed
276
+ - Anti-patterns
277
+
278
+ 3. **Project-Specific Patterns**
279
+ - Check against project documentation (docs/ folder)
280
+ - Verify route organization (server routes)
281
+ - Check provider patterns (server providers)
282
+ - Verify component organization (UI components)
283
+
284
+ 4. **API Design**
285
+ - RESTful API violations
286
+ - Inconsistent response formats
287
+ - Missing error handling
288
+ - Incorrect status codes
289
+
290
+ 5. **State Management**
291
+ - Incorrect state management patterns
292
+ - Missing state normalization
293
+ - Inefficient state updates
294
+
295
+ Provide a detailed report with:
296
+ - Architectural issue description
297
+ - File paths and affected areas
298
+ - Impact on system design
299
+ - Recommended architectural changes
300
+ ```
301
+
302
+ ### Phase 3: Consolidate Findings
303
+
304
+ After all 5 deep dive agents complete their analysis:
305
+
306
+ 1. **Collect all findings** from each agent
307
+ 2. **Prioritize issues**:
308
+ - CRITICAL: Tech stack invalid code (build-breaking)
309
+ - HIGH: Security vulnerabilities, critical logic errors
310
+ - MEDIUM: Code quality issues, architectural problems
311
+ - LOW: Minor code smells, style issues
312
+
313
+ 3. **Group by file** to understand impact per file
314
+ 4. **Create a master report** summarizing all findings
315
+
316
+ ### Phase 4: Deepcode Fixes (5 Agents)
317
+
318
+ Launch 5 deepcode agents to fix the issues found. Each agent should be invoked with the `@deepcode` agent.
319
+
320
+ #### Deepcode Agent 1: Fix Tech Stack Invalid Code
321
+
322
+ **Priority:** CRITICAL - Fix first
323
+
324
+ **Instructions:**
325
+
326
+ ```
327
+ Fix all invalid code based on tech stack issues identified by Agent 1.
328
+
329
+ Focus on:
330
+ 1. Fixing TypeScript syntax errors
331
+ 2. Updating deprecated Node.js APIs
332
+ 3. Fixing React 19 compatibility issues
333
+ 4. Correcting Express 5 API usage
334
+ 5. Fixing type errors
335
+ 6. Resolving build-breaking issues
336
+
337
+ After fixes, verify:
338
+ - Code compiles without errors
339
+ - TypeScript types are correct
340
+ - No deprecated API usage
341
+ ```
342
+
343
+ #### Deepcode Agent 2: Fix Security Vulnerabilities
344
+
345
+ **Priority:** HIGH
346
+
347
+ **Instructions:**
348
+
349
+ ```
350
+ Fix all security vulnerabilities identified by Agent 2.
351
+
352
+ Focus on:
353
+ 1. Adding input validation
354
+ 2. Fixing injection vulnerabilities
355
+ 3. Securing authentication/authorization
356
+ 4. Fixing insecure data handling
357
+ 5. Updating vulnerable dependencies
358
+ 6. Securing Electron IPC
359
+
360
+ After fixes, verify:
361
+ - Security vulnerabilities are addressed
362
+ - No sensitive data exposure
363
+ - Proper authentication/authorization
364
+ ```
365
+
366
+ #### Deepcode Agent 3: Refactor Dirty Code
367
+
368
+ **Priority:** MEDIUM
369
+
370
+ **Instructions:**
371
+
372
+ ```
373
+ Refactor code quality issues identified by Agent 3.
374
+
375
+ Focus on:
376
+ 1. Extracting long functions
377
+ 2. Reducing complexity
378
+ 3. Removing duplicate code
379
+ 4. Adding error handling
380
+ 5. Improving React component structure
381
+ 6. Adding missing comments
382
+
383
+ After fixes, verify:
384
+ - Code follows best practices
385
+ - No code smells remain
386
+ - Performance optimizations applied
387
+ ```
388
+
389
+ #### Deepcode Agent 4: Fix Implementation Errors
390
+
391
+ **Priority:** HIGH
392
+
393
+ **Instructions:**
394
+
395
+ ```
396
+ Fix implementation correctness issues identified by Agent 4.
397
+
398
+ Focus on:
399
+ 1. Fixing logic errors
400
+ 2. Adding missing features
401
+ 3. Handling edge cases
402
+ 4. Fixing type errors
403
+ 5. Adding missing tests
404
+
405
+ After fixes, verify:
406
+ - Logic is correct
407
+ - Edge cases handled
408
+ - Tests pass
409
+ ```
410
+
411
+ #### Deepcode Agent 5: Fix Architectural Issues
412
+
413
+ **Priority:** MEDIUM
414
+
415
+ **Instructions:**
416
+
417
+ ```
418
+ Fix architectural issues identified by Agent 5.
419
+
420
+ Focus on:
421
+ 1. Correcting architecture violations
422
+ 2. Applying proper design patterns
423
+ 3. Fixing API design issues
424
+ 4. Improving state management
425
+ 5. Following project patterns
426
+
427
+ After fixes, verify:
428
+ - Architecture is sound
429
+ - Patterns are correctly applied
430
+ - Code follows project structure
431
+ ```
432
+
433
+ ### Phase 5: Verification
434
+
435
+ After all fixes are complete:
436
+
437
+ 1. **Run TypeScript compilation check**
438
+
439
+ ```bash
440
+ npm run build:packages
441
+ ```
442
+
443
+ 2. **Run linting**
444
+
445
+ ```bash
446
+ npm run lint
447
+ ```
448
+
449
+ 3. **Run tests** (if applicable)
450
+
451
+ ```bash
452
+ npm run test:server
453
+ npm run test
454
+ ```
455
+
456
+ 4. **Verify git diff** shows only intended changes
457
+
458
+ ```bash
459
+ git diff HEAD
460
+ ```
461
+
462
+ 5. **Create summary report**:
463
+ - Issues found by each agent
464
+ - Issues fixed by each agent
465
+ - Remaining issues (if any)
466
+ - Verification results
467
+
468
+ ## Workflow Summary
469
+
470
+ 1. ✅ Get git diff
471
+ 2. ✅ Launch 5 deep dive agents (parallel analysis)
472
+ 3. ✅ Consolidate findings and prioritize
473
+ 4. ✅ Launch 5 deepcode agents (sequential fixes, priority order)
474
+ 5. ✅ Verify fixes with build/lint/test
475
+ 6. ✅ Report summary
476
+
477
+ ## Notes
478
+
479
+ - **Tech stack validation is HIGHEST PRIORITY** - invalid code must be fixed first
480
+ - Each deep dive agent should work independently and provide comprehensive analysis
481
+ - Deepcode agents should fix issues in priority order
482
+ - All fixes should maintain existing functionality
483
+ - If an agent finds no issues in their domain, they should report "No issues found"
484
+ - If fixes introduce new issues, they should be caught in verification phase
jules_branch/.claude/commands/thorough.md ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ When you think you are done, you are NOT done.
2
+
3
+ You must run a mandatory 3-pass verification before concluding:
4
+
5
+ ## Pass 1: Correctness & Functionality
6
+
7
+ - [ ] Verify logic matches requirements and specifications
8
+ - [ ] Check type safety (TypeScript types are correct and complete)
9
+ - [ ] Ensure imports are correct and follow project conventions
10
+ - [ ] Verify all functions/classes work as intended
11
+ - [ ] Check that return values and side effects are correct
12
+ - [ ] Run relevant tests if they exist, or verify testability
13
+ - [ ] Confirm integration with existing code works properly
14
+
15
+ ## Pass 2: Edge Cases & Safety
16
+
17
+ - [ ] Handle null/undefined inputs gracefully
18
+ - [ ] Validate all user inputs and external data
19
+ - [ ] Check error handling (try/catch, error boundaries, etc.)
20
+ - [ ] Verify security considerations (no sensitive data exposure, proper auth checks)
21
+ - [ ] Test boundary conditions (empty arrays, zero values, max lengths, etc.)
22
+ - [ ] Ensure resource cleanup (file handles, connections, timers)
23
+ - [ ] Check for potential race conditions or async issues
24
+ - [ ] Verify file path security (no directory traversal vulnerabilities)
25
+
26
+ ## Pass 3: Maintainability & Code Quality
27
+
28
+ - [ ] Code follows project style guide and conventions
29
+ - [ ] Functions/classes are single-purpose and well-named
30
+ - [ ] Remove dead code, unused imports, and console.logs
31
+ - [ ] Extract magic numbers/strings into named constants
32
+ - [ ] Check for code duplication (DRY principle)
33
+ - [ ] Verify appropriate abstraction levels (not over/under-engineered)
34
+ - [ ] Add necessary comments for complex logic
35
+ - [ ] Ensure consistent error messages and logging
36
+ - [ ] Check that code is readable and self-documenting
37
+ - [ ] Verify proper separation of concerns
38
+
39
+ **For each pass, explicitly report:**
40
+
41
+ - What you checked
42
+ - Any issues found and how they were fixed
43
+ - Any remaining concerns or trade-offs
44
+
45
+ Only after completing all three passes with explicit findings may you conclude the work is done.
jules_branch/.claude/commands/validate-build.md ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Project Build and Fix Command
2
+
3
+ Run all builds and intelligently fix any failures based on what changed.
4
+
5
+ ## Instructions
6
+
7
+ 1. **Run the build**
8
+
9
+ ```bash
10
+ npm run build
11
+ ```
12
+
13
+ This builds all packages and the UI application.
14
+
15
+ 2. **If the build succeeds**, report success and stop.
16
+
17
+ 3. **If the build fails**, analyze the failures:
18
+ - Note which build step failed and the error messages
19
+ - Check for TypeScript compilation errors, missing dependencies, or configuration issues
20
+ - Run `git diff main` to see what code has changed
21
+
22
+ 4. **Determine the nature of the failure**:
23
+ - **If the failure is due to intentional changes** (new features, refactoring, dependency updates):
24
+ - Fix any TypeScript type errors introduced by the changes
25
+ - Update build configuration if needed (e.g., tsconfig.json, vite.config.mts)
26
+ - Ensure all new dependencies are properly installed
27
+ - Fix import paths or module resolution issues
28
+
29
+ - **If the failure appears to be a regression** (broken imports, missing files, configuration errors):
30
+ - Fix the source code to restore the build
31
+ - Check for accidentally deleted files or broken references
32
+ - Verify build configuration files are correct
33
+
34
+ 5. **Common build issues to check**:
35
+ - **TypeScript errors**: Fix type mismatches, missing types, or incorrect imports
36
+ - **Missing dependencies**: Run `npm install` if packages are missing
37
+ - **Import/export errors**: Fix incorrect import paths or missing exports
38
+ - **Build configuration**: Check tsconfig.json, vite.config.mts, or other build configs
39
+ - **Package build order**: Ensure `build:packages` completes before building apps
40
+
41
+ 6. **How to decide if it's intentional vs regression**:
42
+ - Look at the git diff and commit messages
43
+ - If the change was deliberate and introduced new code that needs fixing → fix the new code
44
+ - If the change broke existing functionality that should still build → fix the regression
45
+ - When in doubt, ask the user
46
+
47
+ 7. **After making fixes**, re-run the build to verify everything compiles successfully.
48
+
49
+ 8. **Report summary** of what was fixed (TypeScript errors, configuration issues, missing dependencies, etc.).
jules_branch/.claude/commands/validate-tests.md ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Project Test and Fix Command
2
+
3
+ Run all tests and intelligently fix any failures based on what changed.
4
+
5
+ ## Instructions
6
+
7
+ 1. **Run all tests**
8
+
9
+ ```bash
10
+ npm run test:all
11
+ ```
12
+
13
+ 2. **If all tests pass**, report success and stop.
14
+
15
+ 3. **If any tests fail**, analyze the failures:
16
+ - Note which tests failed and their error messages
17
+ - Run `git diff main` to see what code has changed
18
+
19
+ 4. **Determine the nature of the change**:
20
+ - **If the logic change is intentional** (new feature, refactor, behavior change):
21
+ - Update the failing tests to match the new expected behavior
22
+ - The tests should reflect what the code NOW does correctly
23
+
24
+ - **If the logic change appears to be a bug** (regression, unintended side effect):
25
+ - Fix the source code to restore the expected behavior
26
+ - Do NOT modify the tests - they are catching a real bug
27
+
28
+ 5. **How to decide if it's a bug vs intentional change**:
29
+ - Look at the git diff and commit messages
30
+ - If the change was deliberate and the test expectations are now outdated → update tests
31
+ - If the change broke existing functionality that should still work → fix the code
32
+ - When in doubt, ask the user
33
+
34
+ 6. **After making fixes**, re-run the tests to verify everything passes.
35
+
36
+ 7. **Report summary** of what was fixed (tests updated vs code fixed).
jules_branch/.dockerignore ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dependencies
2
+ node_modules/
3
+ **/node_modules/
4
+
5
+ # Build outputs
6
+ dist/
7
+ **/dist/
8
+ dist-electron/
9
+ **/dist-electron/
10
+ build/
11
+ **/build/
12
+ .next/
13
+ **/.next/
14
+ .nuxt/
15
+ **/.nuxt/
16
+ out/
17
+ **/out/
18
+ .cache/
19
+ **/.cache/
jules_branch/.geminiignore ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Auto-generated by Automaker to speed up Gemini CLI startup
2
+ # Prevents Gemini CLI from scanning large directories during context discovery
3
+ .git
4
+ node_modules
5
+ dist
6
+ build
7
+ .next
8
+ .nuxt
9
+ coverage
10
+ .automaker
11
+ .worktrees
12
+ .vscode
13
+ .idea
14
+ *.lock
jules_branch/.github/ISSUE_TEMPLATE/bug_report.yml ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Bug Report
2
+ description: File a bug report to help us improve Automaker
3
+ title: '[Bug]: '
4
+ labels: ['bug']
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for taking the time to report a bug! Please fill out the form below with as much detail as possible.
10
+
11
+ - type: dropdown
12
+ id: operating-system
13
+ attributes:
14
+ label: Operating System
15
+ description: What operating system are you using?
16
+ options:
17
+ - macOS
18
+ - Windows
19
+ - Linux
20
+ - Other
21
+ default: 0
22
+ validations:
23
+ required: true
24
+
25
+ - type: dropdown
26
+ id: run-mode
27
+ attributes:
28
+ label: Run Mode
29
+ description: How are you running Automaker?
30
+ options:
31
+ - Electron (Desktop App)
32
+ - Web (Browser)
33
+ - Docker
34
+ default: 0
35
+ validations:
36
+ required: true
37
+
38
+ - type: input
39
+ id: app-version
40
+ attributes:
41
+ label: App Version
42
+ description: What version of Automaker are you using? (e.g., 0.1.0)
43
+ placeholder: '0.1.0'
44
+ validations:
45
+ required: true
46
+
47
+ - type: textarea
48
+ id: bug-description
49
+ attributes:
50
+ label: Bug Description
51
+ description: A clear and concise description of what the bug is.
52
+ placeholder: Describe the bug...
53
+ validations:
54
+ required: true
55
+
56
+ - type: textarea
57
+ id: steps-to-reproduce
58
+ attributes:
59
+ label: Steps to Reproduce
60
+ description: Steps to reproduce the behavior
61
+ placeholder: |
62
+ 1. Go to '...'
63
+ 2. Click on '...'
64
+ 3. Scroll down to '...'
65
+ 4. See error
66
+ validations:
67
+ required: true
68
+
69
+ - type: textarea
70
+ id: expected-behavior
71
+ attributes:
72
+ label: Expected Behavior
73
+ description: A clear and concise description of what you expected to happen.
74
+ placeholder: What should have happened?
75
+ validations:
76
+ required: true
77
+
78
+ - type: textarea
79
+ id: actual-behavior
80
+ attributes:
81
+ label: Actual Behavior
82
+ description: A clear and concise description of what actually happened.
83
+ placeholder: What actually happened?
84
+ validations:
85
+ required: true
86
+
87
+ - type: textarea
88
+ id: screenshots
89
+ attributes:
90
+ label: Screenshots
91
+ description: If applicable, add screenshots to help explain your problem.
92
+ placeholder: Drag and drop screenshots here or paste image URLs
93
+
94
+ - type: textarea
95
+ id: logs
96
+ attributes:
97
+ label: Relevant Logs
98
+ description: If applicable, paste relevant logs or error messages.
99
+ placeholder: Paste logs here...
100
+ render: shell
101
+
102
+ - type: textarea
103
+ id: additional-context
104
+ attributes:
105
+ label: Additional Context
106
+ description: Add any other context about the problem here.
107
+ placeholder: Any additional information that might be helpful...
108
+
109
+ - type: checkboxes
110
+ id: terms
111
+ attributes:
112
+ label: Checklist
113
+ options:
114
+ - label: I have searched existing issues to ensure this bug hasn't been reported already
115
+ required: true
116
+ - label: I have provided all required information above
117
+ required: true
jules_branch/.github/ISSUE_TEMPLATE/feature_request.yml ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Feature Request
2
+ description: Suggest a new feature or enhancement for Automaker
3
+ title: '[Feature]: '
4
+ labels: ['enhancement']
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for taking the time to suggest a feature! Please fill out the form below to help us understand your request.
10
+
11
+ - type: dropdown
12
+ id: feature-area
13
+ attributes:
14
+ label: Feature Area
15
+ description: Which area of Automaker does this feature relate to?
16
+ options:
17
+ - UI/UX (User Interface)
18
+ - Agent/AI
19
+ - Kanban Board
20
+ - Git/Worktree Management
21
+ - Project Management
22
+ - Settings/Configuration
23
+ - Documentation
24
+ - Performance
25
+ - Other
26
+ default: 0
27
+ validations:
28
+ required: true
29
+
30
+ - type: dropdown
31
+ id: priority
32
+ attributes:
33
+ label: Priority
34
+ description: How important is this feature to your workflow?
35
+ options:
36
+ - Nice to have
37
+ - Would improve my workflow
38
+ - Critical for my use case
39
+ default: 0
40
+ validations:
41
+ required: true
42
+
43
+ - type: textarea
44
+ id: problem-statement
45
+ attributes:
46
+ label: Problem Statement
47
+ description: Is your feature request related to a problem? Please describe the problem you're trying to solve.
48
+ placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when...
49
+ validations:
50
+ required: true
51
+
52
+ - type: textarea
53
+ id: proposed-solution
54
+ attributes:
55
+ label: Proposed Solution
56
+ description: Describe the solution you'd like to see implemented.
57
+ placeholder: A clear and concise description of what you want to happen.
58
+ validations:
59
+ required: true
60
+
61
+ - type: textarea
62
+ id: alternatives-considered
63
+ attributes:
64
+ label: Alternatives Considered
65
+ description: Describe any alternative solutions or workarounds you've considered.
66
+ placeholder: A clear and concise description of any alternative solutions or features you've considered.
67
+ validations:
68
+ required: false
69
+
70
+ - type: textarea
71
+ id: use-cases
72
+ attributes:
73
+ label: Use Cases
74
+ description: Describe specific scenarios where this feature would be useful.
75
+ placeholder: |
76
+ 1. When working on...
77
+ 2. As a user who needs to...
78
+ 3. In situations where...
79
+ validations:
80
+ required: false
81
+
82
+ - type: textarea
83
+ id: mockups
84
+ attributes:
85
+ label: Mockups/Screenshots
86
+ description: If applicable, add mockups, wireframes, or screenshots to help illustrate your feature request.
87
+ placeholder: Drag and drop images here or paste image URLs
88
+ validations:
89
+ required: false
90
+
91
+ - type: textarea
92
+ id: additional-context
93
+ attributes:
94
+ label: Additional Context
95
+ description: Add any other context, references, or examples about the feature request here.
96
+ placeholder: Any additional information that might be helpful...
97
+ validations:
98
+ required: false
99
+
100
+ - type: checkboxes
101
+ id: terms
102
+ attributes:
103
+ label: Checklist
104
+ options:
105
+ - label: I have searched existing issues to ensure this feature hasn't been requested already
106
+ required: true
107
+ - label: I have provided a clear description of the problem and proposed solution
108
+ required: true
jules_branch/.github/actions/setup-project/action.yml ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: 'Setup Project'
2
+ description: 'Common setup steps for CI workflows - checkout, Node.js, dependencies, and native modules'
3
+
4
+ inputs:
5
+ node-version:
6
+ description: 'Node.js version to use'
7
+ required: false
8
+ default: '22'
9
+ check-lockfile:
10
+ description: 'Run lockfile lint check for SSH URLs'
11
+ required: false
12
+ default: 'false'
13
+ rebuild-node-pty-path:
14
+ description: 'Working directory for node-pty rebuild (empty = root)'
15
+ required: false
16
+ default: ''
17
+
18
+ runs:
19
+ using: 'composite'
20
+ steps:
21
+ - name: Setup Node.js
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: ${{ inputs.node-version }}
25
+ cache: 'npm'
26
+ cache-dependency-path: package-lock.json
27
+
28
+ - name: Configure Git for HTTPS
29
+ shell: bash
30
+ # Convert SSH URLs to HTTPS for git dependencies (e.g., @electron/node-gyp)
31
+ # This is needed because SSH authentication isn't available in CI
32
+ run: git config --global url."https://github.com/".insteadOf "git@github.com:"
33
+
34
+ - name: Auto-fix SSH URLs in lockfile
35
+ if: inputs.check-lockfile == 'true'
36
+ shell: bash
37
+ # Auto-fix any git+ssh:// URLs in package-lock.json before linting
38
+ # This handles cases where npm reintroduces SSH URLs for git dependencies
39
+ run: node scripts/fix-lockfile-urls.mjs
40
+
41
+ - name: Check for SSH URLs in lockfile
42
+ if: inputs.check-lockfile == 'true'
43
+ shell: bash
44
+ run: npm run lint:lockfile
45
+
46
+ - name: Install dependencies
47
+ shell: bash
48
+ # Use npm install instead of npm ci to correctly resolve platform-specific
49
+ # optional dependencies (e.g., @tailwindcss/oxide, lightningcss binaries)
50
+ # Skip scripts to avoid electron-builder install-app-deps which uses too much memory
51
+ # Use --force to allow platform-specific dev dependencies like dmg-license on non-darwin platforms
52
+ run: npm install --ignore-scripts --force
53
+
54
+ - name: Install Linux native bindings
55
+ if: runner.os == 'Linux'
56
+ shell: bash
57
+ # Workaround for npm optional dependencies bug (npm/cli#4828)
58
+ # Explicitly install Linux bindings needed for build tools
59
+ run: |
60
+ npm install --no-save --force --ignore-scripts \
61
+ @rollup/rollup-linux-x64-gnu@4.53.3 \
62
+ @tailwindcss/oxide-linux-x64-gnu@4.1.17
63
+
64
+ - name: Build shared packages
65
+ shell: bash
66
+ # Build shared packages (types, utils, platform, etc.) before apps can use them
67
+ run: npm run build:packages
68
+
69
+ - name: Rebuild native modules (root)
70
+ if: inputs.rebuild-node-pty-path == ''
71
+ shell: bash
72
+ # Rebuild node-pty and other native modules for Electron
73
+ run: npm rebuild node-pty
74
+
75
+ - name: Rebuild native modules (workspace)
76
+ if: inputs.rebuild-node-pty-path != ''
77
+ shell: bash
78
+ # Rebuild node-pty and other native modules needed for server
79
+ run: npm rebuild node-pty
80
+ working-directory: ${{ inputs.rebuild-node-pty-path }}
jules_branch/.github/scripts/upload-to-r2.js ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { S3Client, PutObjectCommand, GetObjectCommand } = require('@aws-sdk/client-s3');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const https = require('https');
5
+ const { pipeline } = require('stream/promises');
6
+
7
+ const s3Client = new S3Client({
8
+ region: 'auto',
9
+ endpoint: process.env.R2_ENDPOINT,
10
+ credentials: {
11
+ accessKeyId: process.env.R2_ACCESS_KEY_ID,
12
+ secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
13
+ },
14
+ });
15
+
16
+ const BUCKET = process.env.R2_BUCKET_NAME;
17
+ const PUBLIC_URL = process.env.R2_PUBLIC_URL;
18
+ const VERSION = process.env.RELEASE_VERSION;
19
+ const RELEASE_TAG = process.env.RELEASE_TAG || `v${VERSION}`;
20
+ const GITHUB_REPO = process.env.GITHUB_REPOSITORY;
21
+
22
+ async function fetchExistingReleases() {
23
+ try {
24
+ const response = await s3Client.send(
25
+ new GetObjectCommand({
26
+ Bucket: BUCKET,
27
+ Key: 'releases.json',
28
+ })
29
+ );
30
+ const body = await response.Body.transformToString();
31
+ return JSON.parse(body);
32
+ } catch (error) {
33
+ if (error.name === 'NoSuchKey' || error.$metadata?.httpStatusCode === 404) {
34
+ console.log('No existing releases.json found, creating new one');
35
+ return { latestVersion: null, releases: [] };
36
+ }
37
+ throw error;
38
+ }
39
+ }
40
+
41
+ async function uploadFile(localPath, r2Key, contentType) {
42
+ const fileBuffer = fs.readFileSync(localPath);
43
+ const stats = fs.statSync(localPath);
44
+
45
+ await s3Client.send(
46
+ new PutObjectCommand({
47
+ Bucket: BUCKET,
48
+ Key: r2Key,
49
+ Body: fileBuffer,
50
+ ContentType: contentType,
51
+ })
52
+ );
53
+
54
+ console.log(`Uploaded: ${r2Key} (${stats.size} bytes)`);
55
+ return stats.size;
56
+ }
57
+
58
+ function findArtifacts(dir, pattern) {
59
+ if (!fs.existsSync(dir)) return [];
60
+ const files = fs.readdirSync(dir);
61
+ return files.filter((f) => pattern.test(f)).map((f) => path.join(dir, f));
62
+ }
63
+
64
+ async function checkUrlAccessible(url, maxRetries = 10, initialDelay = 1000) {
65
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
66
+ try {
67
+ const result = await new Promise((resolve, reject) => {
68
+ const request = https.get(url, { timeout: 10000 }, (response) => {
69
+ const statusCode = response.statusCode;
70
+
71
+ // Follow redirects
72
+ if (
73
+ statusCode === 302 ||
74
+ statusCode === 301 ||
75
+ statusCode === 307 ||
76
+ statusCode === 308
77
+ ) {
78
+ const redirectUrl = response.headers.location;
79
+ response.destroy();
80
+ if (!redirectUrl) {
81
+ resolve({
82
+ accessible: false,
83
+ statusCode,
84
+ error: 'Redirect without location header',
85
+ });
86
+ return;
87
+ }
88
+ // Follow the redirect URL
89
+ return https
90
+ .get(redirectUrl, { timeout: 10000 }, (redirectResponse) => {
91
+ const redirectStatus = redirectResponse.statusCode;
92
+ const contentType = redirectResponse.headers['content-type'] || '';
93
+ // Check if it's actually a file (zip/tar.gz) and not HTML
94
+ const isFile =
95
+ contentType.includes('application/zip') ||
96
+ contentType.includes('application/gzip') ||
97
+ contentType.includes('application/x-gzip') ||
98
+ contentType.includes('application/x-tar') ||
99
+ redirectUrl.includes('.zip') ||
100
+ redirectUrl.includes('.tar.gz');
101
+ const isGood = redirectStatus >= 200 && redirectStatus < 300 && isFile;
102
+ redirectResponse.destroy();
103
+ resolve({
104
+ accessible: isGood,
105
+ statusCode: redirectStatus,
106
+ finalUrl: redirectUrl,
107
+ contentType,
108
+ });
109
+ })
110
+ .on('error', (error) => {
111
+ resolve({
112
+ accessible: false,
113
+ statusCode,
114
+ error: error.message,
115
+ });
116
+ })
117
+ .on('timeout', function () {
118
+ this.destroy();
119
+ resolve({
120
+ accessible: false,
121
+ statusCode,
122
+ error: 'Timeout following redirect',
123
+ });
124
+ });
125
+ }
126
+
127
+ // Check if status is good (200-299 range) and it's actually a file
128
+ const contentType = response.headers['content-type'] || '';
129
+ const isFile =
130
+ contentType.includes('application/zip') ||
131
+ contentType.includes('application/gzip') ||
132
+ contentType.includes('application/x-gzip') ||
133
+ contentType.includes('application/x-tar') ||
134
+ url.includes('.zip') ||
135
+ url.includes('.tar.gz');
136
+ const isGood = statusCode >= 200 && statusCode < 300 && isFile;
137
+ response.destroy();
138
+ resolve({ accessible: isGood, statusCode, contentType });
139
+ });
140
+
141
+ request.on('error', (error) => {
142
+ resolve({
143
+ accessible: false,
144
+ statusCode: null,
145
+ error: error.message,
146
+ });
147
+ });
148
+
149
+ request.on('timeout', () => {
150
+ request.destroy();
151
+ resolve({
152
+ accessible: false,
153
+ statusCode: null,
154
+ error: 'Request timeout',
155
+ });
156
+ });
157
+ });
158
+
159
+ if (result.accessible) {
160
+ if (attempt > 0) {
161
+ console.log(
162
+ `✓ URL ${url} is now accessible after ${attempt} retries (status: ${result.statusCode})`
163
+ );
164
+ } else {
165
+ console.log(`✓ URL ${url} is accessible (status: ${result.statusCode})`);
166
+ }
167
+ return result.finalUrl || url; // Return the final URL (after redirects) if available
168
+ } else {
169
+ const errorMsg = result.error ? ` - ${result.error}` : '';
170
+ const statusMsg = result.statusCode ? ` (status: ${result.statusCode})` : '';
171
+ const contentTypeMsg = result.contentType ? ` [content-type: ${result.contentType}]` : '';
172
+ console.log(`✗ URL ${url} not accessible${statusMsg}${contentTypeMsg}${errorMsg}`);
173
+ }
174
+ } catch (error) {
175
+ console.log(`✗ URL ${url} check failed: ${error.message}`);
176
+ }
177
+
178
+ if (attempt < maxRetries - 1) {
179
+ const delay = initialDelay * Math.pow(2, attempt);
180
+ console.log(` Retrying in ${delay}ms... (attempt ${attempt + 1}/${maxRetries})`);
181
+ await new Promise((resolve) => setTimeout(resolve, delay));
182
+ }
183
+ }
184
+
185
+ throw new Error(`URL ${url} is not accessible after ${maxRetries} attempts`);
186
+ }
187
+
188
+ async function downloadFromGitHub(url, outputPath) {
189
+ return new Promise((resolve, reject) => {
190
+ const request = https.get(url, { timeout: 30000 }, (response) => {
191
+ const statusCode = response.statusCode;
192
+
193
+ // Follow redirects (all redirect types)
194
+ if (statusCode === 301 || statusCode === 302 || statusCode === 307 || statusCode === 308) {
195
+ const redirectUrl = response.headers.location;
196
+ response.destroy();
197
+ if (!redirectUrl) {
198
+ reject(new Error(`Redirect without location header for ${url}`));
199
+ return;
200
+ }
201
+ // Resolve relative redirects
202
+ const finalRedirectUrl = redirectUrl.startsWith('http')
203
+ ? redirectUrl
204
+ : new URL(redirectUrl, url).href;
205
+ console.log(` Following redirect: ${finalRedirectUrl}`);
206
+ return downloadFromGitHub(finalRedirectUrl, outputPath).then(resolve).catch(reject);
207
+ }
208
+
209
+ if (statusCode !== 200) {
210
+ response.destroy();
211
+ reject(new Error(`Failed to download ${url}: ${statusCode} ${response.statusMessage}`));
212
+ return;
213
+ }
214
+
215
+ const fileStream = fs.createWriteStream(outputPath);
216
+ response.pipe(fileStream);
217
+ fileStream.on('finish', () => {
218
+ fileStream.close();
219
+ resolve();
220
+ });
221
+ fileStream.on('error', (error) => {
222
+ response.destroy();
223
+ reject(error);
224
+ });
225
+ });
226
+
227
+ request.on('error', reject);
228
+ request.on('timeout', () => {
229
+ request.destroy();
230
+ reject(new Error(`Request timeout for ${url}`));
231
+ });
232
+ });
233
+ }
234
+
235
+ async function main() {
236
+ const artifactsDir = 'artifacts';
237
+ const tempDir = path.join(artifactsDir, 'temp');
238
+
239
+ // Create temp directory for downloaded GitHub archives
240
+ if (!fs.existsSync(tempDir)) {
241
+ fs.mkdirSync(tempDir, { recursive: true });
242
+ }
243
+
244
+ // Download source archives from GitHub
245
+ const githubZipUrl = `https://github.com/${GITHUB_REPO}/archive/refs/tags/${RELEASE_TAG}.zip`;
246
+ const githubTarGzUrl = `https://github.com/${GITHUB_REPO}/archive/refs/tags/${RELEASE_TAG}.tar.gz`;
247
+
248
+ const sourceZipPath = path.join(tempDir, `automaker-${VERSION}.zip`);
249
+ const sourceTarGzPath = path.join(tempDir, `automaker-${VERSION}.tar.gz`);
250
+
251
+ console.log(`Waiting for source archives to be available on GitHub...`);
252
+ console.log(` ZIP: ${githubZipUrl}`);
253
+ console.log(` TAR.GZ: ${githubTarGzUrl}`);
254
+
255
+ // Wait for archives to be accessible with exponential backoff
256
+ // This returns the final URL after following redirects
257
+ const finalZipUrl = await checkUrlAccessible(githubZipUrl);
258
+ const finalTarGzUrl = await checkUrlAccessible(githubTarGzUrl);
259
+
260
+ console.log(`Downloading source archives from GitHub...`);
261
+ await downloadFromGitHub(finalZipUrl, sourceZipPath);
262
+ await downloadFromGitHub(finalTarGzUrl, sourceTarGzPath);
263
+
264
+ console.log(`Downloaded source archives successfully`);
265
+
266
+ // Find all artifacts
267
+ const artifacts = {
268
+ windows: findArtifacts(path.join(artifactsDir, 'windows-builds'), /\.exe$/),
269
+ macos: findArtifacts(path.join(artifactsDir, 'macos-builds'), /-x64\.dmg$/),
270
+ macosArm: findArtifacts(path.join(artifactsDir, 'macos-builds'), /-arm64\.dmg$/),
271
+ linux: findArtifacts(path.join(artifactsDir, 'linux-builds'), /\.AppImage$/),
272
+ sourceZip: [sourceZipPath],
273
+ sourceTarGz: [sourceTarGzPath],
274
+ };
275
+
276
+ console.log('Found artifacts:');
277
+ for (const [platform, files] of Object.entries(artifacts)) {
278
+ console.log(
279
+ ` ${platform}: ${files.length > 0 ? files.map((f) => path.basename(f)).join(', ') : 'none'}`
280
+ );
281
+ }
282
+
283
+ // Upload each artifact to R2
284
+ const assets = {};
285
+ const contentTypes = {
286
+ windows: 'application/x-msdownload',
287
+ macos: 'application/x-apple-diskimage',
288
+ macosArm: 'application/x-apple-diskimage',
289
+ linux: 'application/x-executable',
290
+ sourceZip: 'application/zip',
291
+ sourceTarGz: 'application/gzip',
292
+ };
293
+
294
+ for (const [platform, files] of Object.entries(artifacts)) {
295
+ if (files.length === 0) {
296
+ console.warn(`Warning: No artifact found for ${platform}`);
297
+ continue;
298
+ }
299
+
300
+ // Use the first matching file for each platform
301
+ const localPath = files[0];
302
+ const filename = path.basename(localPath);
303
+ const r2Key = `releases/${VERSION}/${filename}`;
304
+ const size = await uploadFile(localPath, r2Key, contentTypes[platform]);
305
+
306
+ assets[platform] = {
307
+ url: `${PUBLIC_URL}/releases/${VERSION}/${filename}`,
308
+ filename,
309
+ size,
310
+ arch:
311
+ platform === 'macosArm'
312
+ ? 'arm64'
313
+ : platform === 'sourceZip' || platform === 'sourceTarGz'
314
+ ? 'source'
315
+ : 'x64',
316
+ };
317
+ }
318
+
319
+ // Fetch and update releases.json
320
+ const releasesData = await fetchExistingReleases();
321
+
322
+ const newRelease = {
323
+ version: VERSION,
324
+ date: new Date().toISOString(),
325
+ assets,
326
+ githubReleaseUrl: `https://github.com/${GITHUB_REPO}/releases/tag/${RELEASE_TAG}`,
327
+ };
328
+
329
+ // Remove existing entry for this version if re-running
330
+ releasesData.releases = releasesData.releases.filter((r) => r.version !== VERSION);
331
+
332
+ // Prepend new release
333
+ releasesData.releases.unshift(newRelease);
334
+ releasesData.latestVersion = VERSION;
335
+
336
+ // Upload updated releases.json
337
+ await s3Client.send(
338
+ new PutObjectCommand({
339
+ Bucket: BUCKET,
340
+ Key: 'releases.json',
341
+ Body: JSON.stringify(releasesData, null, 2),
342
+ ContentType: 'application/json',
343
+ CacheControl: 'public, max-age=60',
344
+ })
345
+ );
346
+
347
+ console.log('Successfully updated releases.json');
348
+ console.log(`Latest version: ${VERSION}`);
349
+ console.log(`Total releases: ${releasesData.releases.length}`);
350
+ }
351
+
352
+ main().catch((err) => {
353
+ console.error('Failed to upload to R2:', err);
354
+ process.exit(1);
355
+ });
jules_branch/.github/workflows/claude.yml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@v1
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44
+ # prompt: 'Update the pull request description to include a summary of changes.'
45
+
46
+ # Optional: Add claude_args to customize behavior and configuration
47
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48
+ # or https://code.claude.com/docs/en/cli-reference for available options
49
+ # claude_args: '--allowed-tools Bash(gh pr:*)'
jules_branch/.github/workflows/e2e-tests.yml ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: E2E Tests
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - '*'
7
+ push:
8
+ branches:
9
+ - main
10
+ - master
11
+
12
+ jobs:
13
+ e2e:
14
+ runs-on: ubuntu-latest
15
+ timeout-minutes: 15
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ # shardIndex: [1, 2, 3]
20
+ # shardTotal: [3]
21
+ shardIndex: [1]
22
+ shardTotal: [1]
23
+
24
+ steps:
25
+ - name: Checkout code
26
+ uses: actions/checkout@v4
27
+
28
+ - name: Setup project
29
+ uses: ./.github/actions/setup-project
30
+ with:
31
+ check-lockfile: 'true'
32
+ rebuild-node-pty-path: 'apps/server'
33
+
34
+ - name: Install Playwright browsers
35
+ run: npx playwright install --with-deps chromium
36
+ working-directory: apps/ui
37
+
38
+ - name: Build server
39
+ run: npm run build --workspace=apps/server
40
+
41
+ - name: Set up Git user
42
+ run: |
43
+ git config --global user.name "GitHub CI"
44
+ git config --global user.email "ci@example.com"
45
+
46
+ - name: Start backend server
47
+ run: |
48
+ echo "Starting backend server..."
49
+ # Start server in background and save PID
50
+ npm run start --workspace=apps/server > backend.log 2>&1 &
51
+ SERVER_PID=$!
52
+ echo "Server started with PID: $SERVER_PID"
53
+ echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV
54
+
55
+ env:
56
+ PORT: 3108
57
+ TEST_SERVER_PORT: 3108
58
+ NODE_ENV: test
59
+ # Use a deterministic API key so Playwright can log in reliably
60
+ AUTOMAKER_API_KEY: test-api-key-for-e2e-tests
61
+ # Reduce log noise in CI
62
+ AUTOMAKER_HIDE_API_KEY: 'true'
63
+ # Avoid real API calls during CI
64
+ AUTOMAKER_MOCK_AGENT: 'true'
65
+ # Simulate containerized environment to skip sandbox confirmation dialogs
66
+ IS_CONTAINERIZED: 'true'
67
+
68
+ - name: Wait for backend server
69
+ run: |
70
+ echo "Waiting for backend server to be ready..."
71
+
72
+ # Check if server process is running
73
+ if [ -z "$SERVER_PID" ]; then
74
+ echo "ERROR: Server PID not found in environment"
75
+ cat backend.log 2>/dev/null || echo "No backend log found"
76
+ exit 1
77
+ fi
78
+
79
+ # Check if process is actually running
80
+ if ! kill -0 $SERVER_PID 2>/dev/null; then
81
+ echo "ERROR: Server process $SERVER_PID is not running!"
82
+ echo "=== Backend logs ==="
83
+ cat backend.log
84
+ echo ""
85
+ echo "=== Recent system logs ==="
86
+ dmesg 2>/dev/null | tail -20 || echo "No dmesg available"
87
+ exit 1
88
+ fi
89
+
90
+ # Wait for health endpoint
91
+ for i in {1..60}; do
92
+ if curl -s -f http://localhost:3108/api/health > /dev/null 2>&1; then
93
+ echo "Backend server is ready!"
94
+ echo "=== Backend logs ==="
95
+ cat backend.log
96
+ echo ""
97
+ echo "Health check response:"
98
+ curl -s http://localhost:3108/api/health | jq . 2>/dev/null || echo "Health check: $(curl -s http://localhost:3108/api/health 2>/dev/null || echo 'No response')"
99
+ exit 0
100
+ fi
101
+
102
+ # Check if server process is still running
103
+ if ! kill -0 $SERVER_PID 2>/dev/null; then
104
+ echo "ERROR: Server process died during wait!"
105
+ echo "=== Backend logs ==="
106
+ cat backend.log
107
+ exit 1
108
+ fi
109
+
110
+ echo "Waiting... ($i/60)"
111
+ sleep 1
112
+ done
113
+
114
+ echo "ERROR: Backend server failed to start within 60 seconds!"
115
+ echo "=== Backend logs ==="
116
+ cat backend.log
117
+ echo ""
118
+ echo "=== Process status ==="
119
+ ps aux | grep -E "(node|tsx)" | grep -v grep || echo "No node processes found"
120
+ echo ""
121
+ echo "=== Port status ==="
122
+ netstat -tlnp 2>/dev/null | grep :3108 || echo "Port 3108 not listening"
123
+ lsof -i :3108 2>/dev/null || echo "lsof not available or port not in use"
124
+ echo ""
125
+ echo "=== Health endpoint test ==="
126
+ curl -v http://localhost:3108/api/health 2>&1 || echo "Health endpoint failed"
127
+
128
+ # Kill the server process if it's still hanging
129
+ if kill -0 $SERVER_PID 2>/dev/null; then
130
+ echo ""
131
+ echo "Killing stuck server process..."
132
+ kill -9 $SERVER_PID 2>/dev/null || true
133
+ fi
134
+
135
+ exit 1
136
+
137
+ - name: Run E2E tests (shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
138
+ # Playwright automatically starts the Vite frontend via webServer config
139
+ # (see apps/ui/playwright.config.ts) - no need to start it manually
140
+ run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
141
+ working-directory: apps/ui
142
+ env:
143
+ CI: true
144
+ VITE_SKIP_SETUP: 'true'
145
+ # Keep UI-side login/defaults consistent
146
+ AUTOMAKER_API_KEY: test-api-key-for-e2e-tests
147
+ # Backend is already started above - Playwright config sets
148
+ # AUTOMAKER_SERVER_PORT so the Vite proxy forwards /api/* to the backend.
149
+ # Do NOT set VITE_SERVER_URL here: it bypasses the Vite proxy and causes
150
+ # a cookie domain mismatch (cookies are bound to 127.0.0.1, but
151
+ # VITE_SERVER_URL=http://localhost:3108 makes the frontend call localhost).
152
+ TEST_USE_EXTERNAL_BACKEND: 'true'
153
+ TEST_SERVER_PORT: 3108
154
+
155
+ - name: Print backend logs on failure
156
+ if: failure()
157
+ run: |
158
+ echo "=== E2E Tests Failed - Backend Logs ==="
159
+ cat backend.log 2>/dev/null || echo "No backend log found"
160
+ echo ""
161
+ echo "=== Process status at failure ==="
162
+ ps aux | grep -E "(node|tsx)" | grep -v grep || echo "No node processes found"
163
+ echo ""
164
+ echo "=== Port status ==="
165
+ netstat -tlnp 2>/dev/null | grep :3108 || echo "Port 3108 not listening"
166
+
167
+ - name: Upload Playwright report
168
+ uses: actions/upload-artifact@v4
169
+ if: always()
170
+ with:
171
+ name: playwright-report-shard-${{ matrix.shardIndex }}-of-${{ matrix.shardTotal }}
172
+ path: apps/ui/playwright-report/
173
+ retention-days: 7
174
+
175
+ - name: Upload test results (screenshots, traces, videos)
176
+ uses: actions/upload-artifact@v4
177
+ if: always()
178
+ with:
179
+ name: test-results-shard-${{ matrix.shardIndex }}-of-${{ matrix.shardTotal }}
180
+ path: |
181
+ apps/ui/test-results/
182
+ retention-days: 7
183
+ if-no-files-found: ignore
184
+
185
+ - name: Upload blob report for merging
186
+ uses: actions/upload-artifact@v4
187
+ if: always()
188
+ with:
189
+ name: blob-report-shard-${{ matrix.shardIndex }}-of-${{ matrix.shardTotal }}
190
+ path: apps/ui/blob-report/
191
+ retention-days: 1
192
+ if-no-files-found: ignore
193
+
194
+ - name: Cleanup - Kill backend server
195
+ if: always()
196
+ run: |
197
+ if [ -n "$SERVER_PID" ]; then
198
+ echo "Cleaning up backend server (PID: $SERVER_PID)..."
199
+ kill $SERVER_PID 2>/dev/null || true
200
+ kill -9 $SERVER_PID 2>/dev/null || true
201
+ echo "Backend server cleanup complete"
202
+ fi
jules_branch/.github/workflows/format-check.yml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Format Check
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - '*'
7
+ push:
8
+ branches:
9
+ - main
10
+ - master
11
+
12
+ jobs:
13
+ format:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup Node.js
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ node-version: '22'
24
+ cache: 'npm'
25
+ cache-dependency-path: package-lock.json
26
+
27
+ - name: Install dependencies
28
+ run: npm install --ignore-scripts --force
29
+
30
+ - name: Check formatting
31
+ run: npm run format:check
jules_branch/.github/workflows/pr-check.yml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: PR Build Check
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - '*'
7
+ push:
8
+ branches:
9
+ - main
10
+ - master
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup project
21
+ uses: ./.github/actions/setup-project
22
+ with:
23
+ check-lockfile: 'true'
24
+
25
+ - name: Run build:electron (dir only - faster CI)
26
+ run: npm run build:electron:dir
jules_branch/.github/workflows/release.yml ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Release Build
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: write
9
+
10
+ jobs:
11
+ build:
12
+ strategy:
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ runs-on: ${{ matrix.os }}
16
+
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Extract version from tag
22
+ id: version
23
+ shell: bash
24
+ run: |
25
+ # Remove 'v' prefix if present (e.g., "v1.2.3" -> "1.2.3")
26
+ VERSION="${{ github.event.release.tag_name }}"
27
+ VERSION="${VERSION#v}"
28
+ echo "version=${VERSION}" >> $GITHUB_OUTPUT
29
+ echo "Extracted version: ${VERSION}"
30
+
31
+ - name: Update package.json version
32
+ shell: bash
33
+ run: |
34
+ node apps/ui/scripts/update-version.mjs "${{ steps.version.outputs.version }}"
35
+
36
+ - name: Setup project
37
+ uses: ./.github/actions/setup-project
38
+ with:
39
+ check-lockfile: 'true'
40
+
41
+ - name: Install RPM build tools (Linux)
42
+ if: matrix.os == 'ubuntu-latest'
43
+ shell: bash
44
+ run: sudo apt-get update && sudo apt-get install -y rpm
45
+
46
+ - name: Build Electron app (macOS)
47
+ if: matrix.os == 'macos-latest'
48
+ shell: bash
49
+ run: npm run build:electron:mac --workspace=apps/ui
50
+ env:
51
+ CSC_IDENTITY_AUTO_DISCOVERY: false
52
+
53
+ - name: Build Electron app (Windows)
54
+ if: matrix.os == 'windows-latest'
55
+ shell: bash
56
+ run: npm run build:electron:win --workspace=apps/ui
57
+
58
+ - name: Build Electron app (Linux)
59
+ if: matrix.os == 'ubuntu-latest'
60
+ shell: bash
61
+ run: npm run build:electron:linux --workspace=apps/ui
62
+
63
+ - name: Upload macOS artifacts
64
+ if: matrix.os == 'macos-latest'
65
+ uses: actions/upload-artifact@v4
66
+ with:
67
+ name: macos-builds
68
+ path: |
69
+ apps/ui/release/*.dmg
70
+ apps/ui/release/*.zip
71
+ if-no-files-found: error
72
+ retention-days: 30
73
+
74
+ - name: Upload Windows artifacts
75
+ if: matrix.os == 'windows-latest'
76
+ uses: actions/upload-artifact@v4
77
+ with:
78
+ name: windows-builds
79
+ path: apps/ui/release/*.exe
80
+ if-no-files-found: error
81
+ retention-days: 30
82
+
83
+ - name: Upload Linux artifacts
84
+ if: matrix.os == 'ubuntu-latest'
85
+ uses: actions/upload-artifact@v4
86
+ with:
87
+ name: linux-builds
88
+ path: |
89
+ apps/ui/release/*.AppImage
90
+ apps/ui/release/*.deb
91
+ apps/ui/release/*.rpm
92
+ if-no-files-found: error
93
+ retention-days: 30
94
+
95
+ upload:
96
+ needs: build
97
+ runs-on: ubuntu-latest
98
+
99
+ steps:
100
+ - name: Checkout code
101
+ uses: actions/checkout@v4
102
+
103
+ - name: Download macOS artifacts
104
+ uses: actions/download-artifact@v4
105
+ with:
106
+ name: macos-builds
107
+ path: artifacts/macos-builds
108
+
109
+ - name: Download Windows artifacts
110
+ uses: actions/download-artifact@v4
111
+ with:
112
+ name: windows-builds
113
+ path: artifacts/windows-builds
114
+
115
+ - name: Download Linux artifacts
116
+ uses: actions/download-artifact@v4
117
+ with:
118
+ name: linux-builds
119
+ path: artifacts/linux-builds
120
+
121
+ - name: Upload to GitHub Release
122
+ uses: softprops/action-gh-release@v2
123
+ with:
124
+ fail_on_unmatched_files: true
125
+ files: |
126
+ artifacts/macos-builds/*.dmg
127
+ artifacts/macos-builds/*.zip
128
+ artifacts/windows-builds/*.exe
129
+ artifacts/linux-builds/*.AppImage
130
+ artifacts/linux-builds/*.deb
131
+ artifacts/linux-builds/*.rpm
132
+ env:
133
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jules_branch/.github/workflows/security-audit.yml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Security Audit
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - '*'
7
+ push:
8
+ branches:
9
+ - main
10
+ - master
11
+ schedule:
12
+ # Run weekly on Mondays at 9 AM UTC
13
+ - cron: '0 9 * * 1'
14
+
15
+ jobs:
16
+ audit:
17
+ runs-on: ubuntu-latest
18
+
19
+ steps:
20
+ - name: Checkout code
21
+ uses: actions/checkout@v4
22
+
23
+ - name: Setup project
24
+ uses: ./.github/actions/setup-project
25
+ with:
26
+ check-lockfile: 'true'
27
+
28
+ - name: Run npm audit
29
+ run: npm audit --audit-level=critical
30
+ continue-on-error: false
jules_branch/.github/workflows/test.yml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Test Suite
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - '*'
7
+ push:
8
+ branches:
9
+ - main
10
+ - master
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Setup project
21
+ uses: ./.github/actions/setup-project
22
+ with:
23
+ check-lockfile: 'true'
24
+ rebuild-node-pty-path: 'apps/server'
25
+
26
+ - name: Run package tests
27
+ run: npm run test:packages
28
+ env:
29
+ NODE_ENV: test
30
+
31
+ - name: Run server tests with coverage
32
+ run: npm run test:server:coverage
33
+ env:
34
+ NODE_ENV: test
35
+
36
+ # - name: Upload coverage reports
37
+ # uses: codecov/codecov-action@v4
38
+ # if: always()
39
+ # with:
40
+ # files: ./apps/server/coverage/coverage-final.json
41
+ # flags: server
42
+ # name: server-coverage
43
+ # env:
44
+ # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
jules_branch/.gitignore ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #added by trueheads > will remove once supercombo adds multi-os support
2
+ launch.sh
3
+
4
+ # Dependencies
5
+ node_modules/
6
+
7
+ # Build outputs
8
+ dist/
9
+ build/
10
+ out/
11
+ .next/
12
+ .turbo/
13
+
14
+ # Automaker
15
+ .automaker/images/
16
+ .automaker/
17
+ /.automaker/*
18
+ /.automaker/
19
+
20
+ .worktrees/
21
+
22
+ /logs
23
+ # Logs
24
+ logs/
25
+ *.log
26
+ npm-debug.log*
27
+ yarn-debug.log*
28
+ yarn-error.log*
29
+ pnpm-debug.log*
30
+
31
+ # OS-specific files
32
+ .DS_Store
33
+ .DS_Store?
34
+ ._*
35
+ Thumbs.db
36
+ ehthumbs.db
37
+ Desktop.ini
38
+
39
+ # IDE/Editor configs
40
+ .vscode/
41
+ .idea/
42
+ *.sublime-workspace
43
+ *.sublime-project
44
+
45
+ # Editor backup/temp files
46
+ *~
47
+ *.bak
48
+ *.backup
49
+ *.orig
50
+ *.swp
51
+ *.swo
52
+ *.tmp
53
+ *.temp
54
+
55
+ # Local settings (user-specific)
56
+ *.local.json
57
+
58
+ # Application state/backup
59
+ backup.json
60
+
61
+ # Test artifacts
62
+ test-results/
63
+ coverage/
64
+ .nyc_output/
65
+ *.lcov
66
+ playwright-report/
67
+ blob-report/
68
+ test/**/test-project-[0-9]*/
69
+ test/opus-thinking-*/
70
+ test/agent-session-test-*/
71
+ test/feature-backlog-test-*/
72
+ test/running-task-display-test-*/
73
+ test/agent-output-modal-responsive-*/
74
+ test/fixtures/
75
+ test/board-bg-test-*/
76
+ test/edit-feature-test-*/
77
+ test/open-project-test-*/
78
+
79
+
80
+ # Environment files (keep .example)
81
+ .env
82
+ .env.local
83
+ .env.*.local
84
+ !.env.example
85
+ !.env.local.example
86
+
87
+ # Codex config (contains API keys)
88
+ .codex/config.toml
89
+
90
+ # TypeScript
91
+ *.tsbuildinfo
92
+
93
+ # Misc
94
+ *.pem
95
+
96
+ docker-compose.override.yml
97
+ .claude/docker-compose.override.yml
98
+ .claude/hans/
99
+
100
+ pnpm-lock.yaml
101
+ yarn.lock
102
+
103
+ # Fork-specific workflow files (should never be committed)
104
+ DEVELOPMENT_WORKFLOW.md
105
+ check-sync.sh
106
+ # API key files
107
+ data/.api-key
108
+ data/credentials.json
109
+ data/
110
+ .codex/
111
+
112
+ # GSD planning docs (local-only)
113
+ .planning/
114
+ .mcp.json
115
+ .planning
116
+ .bg-shell/
jules_branch/.husky/pre-commit ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env sh
2
+
3
+ # Try to load nvm if available (optional - works without it too)
4
+ if [ -z "$NVM_DIR" ]; then
5
+ # Check for Herd's nvm first (macOS with Herd)
6
+ if [ -s "$HOME/Library/Application Support/Herd/config/nvm/nvm.sh" ]; then
7
+ export NVM_DIR="$HOME/Library/Application Support/Herd/config/nvm"
8
+ # Then check standard nvm location
9
+ elif [ -s "$HOME/.nvm/nvm.sh" ]; then
10
+ export NVM_DIR="$HOME/.nvm"
11
+ fi
12
+ fi
13
+
14
+ # Source nvm if found (silently skip if not available)
15
+ [ -n "$NVM_DIR" ] && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" 2>/dev/null
16
+
17
+ # Load node version from .nvmrc if using nvm (silently skip if nvm not available or fails)
18
+ if [ -f .nvmrc ] && command -v nvm >/dev/null 2>&1; then
19
+ # Check if Unix nvm was sourced (it's a shell function with NVM_DIR set)
20
+ if [ -n "$NVM_DIR" ] && type nvm 2>/dev/null | grep -q "function"; then
21
+ # Unix nvm: reads .nvmrc automatically
22
+ nvm use >/dev/null 2>&1 || true
23
+ else
24
+ # nvm-windows: needs explicit version from .nvmrc
25
+ NODE_VERSION=$(cat .nvmrc | tr -d '[:space:]')
26
+ if [ -n "$NODE_VERSION" ]; then
27
+ nvm use "$NODE_VERSION" >/dev/null 2>&1 || true
28
+ fi
29
+ fi
30
+ fi
31
+
32
+ # Ensure common system paths are in PATH (for systems without nvm)
33
+ # This helps find node/npm installed via Homebrew, system packages, etc.
34
+ if [ -n "$WINDIR" ]; then
35
+ export PATH="$PATH:/c/Program Files/nodejs:/c/Program Files (x86)/nodejs"
36
+ export PATH="$PATH:$APPDATA/npm:$LOCALAPPDATA/Programs/nodejs"
37
+ else
38
+ export PATH="$PATH:/usr/local/bin:/opt/homebrew/bin:/usr/bin"
39
+ fi
40
+
41
+ # Auto-fix git+ssh:// URLs in package-lock.json if it's being committed
42
+ # This prevents CI failures from SSH URLs that npm introduces for git dependencies
43
+ if git diff --cached --name-only | grep -q "^package-lock.json$"; then
44
+ if command -v node >/dev/null 2>&1; then
45
+ if grep -q "git+ssh://" package-lock.json 2>/dev/null; then
46
+ echo "Fixing git+ssh:// URLs in package-lock.json..."
47
+ node scripts/fix-lockfile-urls.mjs
48
+ git add package-lock.json
49
+ fi
50
+ fi
51
+ fi
52
+
53
+ # Run lint-staged - works with or without nvm
54
+ # Prefer npx, fallback to npm exec, both work with system-installed Node.js
55
+ if command -v npx >/dev/null 2>&1; then
56
+ npx lint-staged
57
+ elif command -v npm >/dev/null 2>&1; then
58
+ npm exec -- lint-staged
59
+ else
60
+ echo "Error: Neither npx nor npm found in PATH."
61
+ echo "Please ensure Node.js is installed (via nvm, Homebrew, system package manager, etc.)"
62
+ exit 1
63
+ fi
jules_branch/.npmrc ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cross-platform compatibility for Tailwind CSS v4 and lightningcss
2
+ # These packages use platform-specific optional dependencies that npm
3
+ # automatically resolves based on your OS (macOS, Linux, Windows, WSL)
4
+ #
5
+ # IMPORTANT: When switching platforms or getting platform mismatch errors:
6
+ # 1. Delete node_modules: rm -rf node_modules apps/*/node_modules
7
+ # 2. Run: npm install
8
+ #
9
+ # In CI/CD: Use "npm install" instead of "npm ci" to allow npm to resolve
10
+ # the correct platform-specific binaries at install time.
11
+
12
+ # Include bindings for all platforms in package-lock.json to support CI/CD
13
+ # This ensures Linux, macOS, and Windows bindings are all present
14
+ # NOTE: Only enable when regenerating package-lock.json, then comment out to keep installs fast
15
+ # supportedArchitectures.os=linux,darwin,win32
16
+ # supportedArchitectures.cpu=x64,arm64
jules_branch/.nvmrc ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ 22
2
+
jules_branch/.prettierignore ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build outputs
5
+ dist/
6
+ build/
7
+ out/
8
+ .next/
9
+ .turbo/
10
+ release/
11
+
12
+ # Automaker
13
+ .automaker/
14
+
15
+ # Logs
16
+ logs/
17
+ *.log
18
+
19
+ # Lock files
20
+ package-lock.json
21
+ pnpm-lock.yaml
22
+
23
+ # Generated files
24
+ *.min.js
25
+ *.min.css
26
+ routeTree.gen.ts
27
+ apps/ui/src/routeTree.gen.ts
28
+
29
+ # Test artifacts
30
+ test-results/
31
+ coverage/
32
+ playwright-report/
33
+ blob-report/
34
+
35
+ # IDE/Editor
36
+ .vscode/
37
+ .idea/
38
+
39
+ # Electron
40
+ dist-electron/
41
+ server-bundle/
jules_branch/.prettierrc ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "trailingComma": "es5",
6
+ "printWidth": 100,
7
+ "bracketSpacing": true,
8
+ "arrowParens": "always",
9
+ "endOfLine": "lf"
10
+ }
jules_branch/CLAUDE.md ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Automaker is an autonomous AI development studio built as an npm workspace monorepo. It provides a Kanban-based workflow where AI agents (powered by Claude Agent SDK) implement features in isolated git worktrees.
8
+
9
+ ## Common Commands
10
+
11
+ ```bash
12
+ # Development
13
+ npm run dev # Interactive launcher (choose web or electron)
14
+ npm run dev:web # Web browser mode (localhost:3007)
15
+ npm run dev:electron # Desktop app mode
16
+ npm run dev:electron:debug # Desktop with DevTools open
17
+
18
+ # Building
19
+ npm run build # Build web application
20
+ npm run build:packages # Build all shared packages (required before other builds)
21
+ npm run build:electron # Build desktop app for current platform
22
+ npm run build:server # Build server only
23
+
24
+ # Testing
25
+ npm run test # E2E tests (Playwright, headless)
26
+ npm run test:headed # E2E tests with browser visible
27
+ npm run test:server # Server unit tests (Vitest)
28
+ npm run test:packages # All shared package tests
29
+ npm run test:all # All tests (packages + server)
30
+
31
+ # Single test file
32
+ npm run test:server -- tests/unit/specific.test.ts
33
+
34
+ # Linting and formatting
35
+ npm run lint # ESLint
36
+ npm run format # Prettier write
37
+ npm run format:check # Prettier check
38
+ ```
39
+
40
+ ## Architecture
41
+
42
+ ### Monorepo Structure
43
+
44
+ ```
45
+ automaker/
46
+ ├── apps/
47
+ │ ├── ui/ # React + Vite + Electron frontend (port 3007)
48
+ │ └── server/ # Express + WebSocket backend (port 3008)
49
+ └── libs/ # Shared packages (@automaker/*)
50
+ ├── types/ # Core TypeScript definitions (no dependencies)
51
+ ├── utils/ # Logging, errors, image processing, context loading
52
+ ├── prompts/ # AI prompt templates
53
+ ├── platform/ # Path management, security, process spawning
54
+ ├── model-resolver/ # Claude model alias resolution
55
+ ├── dependency-resolver/ # Feature dependency ordering
56
+ └── git-utils/ # Git operations & worktree management
57
+ ```
58
+
59
+ ### Package Dependency Chain
60
+
61
+ Packages can only depend on packages above them:
62
+
63
+ ```
64
+ @automaker/types (no dependencies)
65
+
66
+ @automaker/utils, @automaker/prompts, @automaker/platform, @automaker/model-resolver, @automaker/dependency-resolver
67
+
68
+ @automaker/git-utils
69
+
70
+ @automaker/server, @automaker/ui
71
+ ```
72
+
73
+ ### Key Technologies
74
+
75
+ - **Frontend**: React 19, Vite 7, Electron 39, TanStack Router, Zustand 5, Tailwind CSS 4
76
+ - **Backend**: Express 5, WebSocket (ws), Claude Agent SDK, node-pty
77
+ - **Testing**: Playwright (E2E), Vitest (unit)
78
+
79
+ ### Server Architecture
80
+
81
+ The server (`apps/server/src/`) follows a modular pattern:
82
+
83
+ - `routes/` - Express route handlers organized by feature (agent, features, auto-mode, worktree, etc.)
84
+ - `services/` - Business logic (AgentService, AutoModeService, FeatureLoader, TerminalService)
85
+ - `providers/` - AI provider abstraction (currently Claude via Claude Agent SDK)
86
+ - `lib/` - Utilities (events, auth, worktree metadata)
87
+
88
+ ### Frontend Architecture
89
+
90
+ The UI (`apps/ui/src/`) uses:
91
+
92
+ - `routes/` - TanStack Router file-based routing
93
+ - `components/views/` - Main view components (board, settings, terminal, etc.)
94
+ - `store/` - Zustand stores with persistence (app-store.ts, setup-store.ts)
95
+ - `hooks/` - Custom React hooks
96
+ - `lib/` - Utilities and API client
97
+
98
+ ## Data Storage
99
+
100
+ ### Per-Project Data (`.automaker/`)
101
+
102
+ ```
103
+ .automaker/
104
+ ├── features/ # Feature JSON files and images
105
+ │ └── {featureId}/
106
+ │ ├── feature.json
107
+ │ ├── agent-output.md
108
+ │ └── images/
109
+ ├── context/ # Context files for AI agents (CLAUDE.md, etc.)
110
+ ├── settings.json # Project-specific settings
111
+ ├── spec.md # Project specification
112
+ └── analysis.json # Project structure analysis
113
+ ```
114
+
115
+ ### Global Data (`DATA_DIR`, default `./data`)
116
+
117
+ ```
118
+ data/
119
+ ├── settings.json # Global settings, profiles, shortcuts
120
+ ├── credentials.json # API keys
121
+ ├── sessions-metadata.json # Chat session metadata
122
+ └── agent-sessions/ # Conversation histories
123
+ ```
124
+
125
+ ## Import Conventions
126
+
127
+ Always import from shared packages, never from old paths:
128
+
129
+ ```typescript
130
+ // ✅ Correct
131
+ import type { Feature, ExecuteOptions } from '@automaker/types';
132
+ import { createLogger, classifyError } from '@automaker/utils';
133
+ import { getEnhancementPrompt } from '@automaker/prompts';
134
+ import { getFeatureDir, ensureAutomakerDir } from '@automaker/platform';
135
+ import { resolveModelString } from '@automaker/model-resolver';
136
+ import { resolveDependencies } from '@automaker/dependency-resolver';
137
+ import { getGitRepositoryDiffs } from '@automaker/git-utils';
138
+
139
+ // ❌ Never import from old paths
140
+ import { Feature } from '../services/feature-loader'; // Wrong
141
+ import { createLogger } from '../lib/logger'; // Wrong
142
+ ```
143
+
144
+ ## Key Patterns
145
+
146
+ ### Event-Driven Architecture
147
+
148
+ All server operations emit events that stream to the frontend via WebSocket. Events are created using `createEventEmitter()` from `lib/events.ts`.
149
+
150
+ ### Git Worktree Isolation
151
+
152
+ Each feature executes in an isolated git worktree, created via `@automaker/git-utils`. This protects the main branch during AI agent execution.
153
+
154
+ ### Context Files
155
+
156
+ Project-specific rules are stored in `.automaker/context/` and automatically loaded into agent prompts via `loadContextFiles()` from `@automaker/utils`.
157
+
158
+ ### Model Resolution
159
+
160
+ Use `resolveModelString()` from `@automaker/model-resolver` to convert model aliases:
161
+
162
+ - `haiku` → `claude-haiku-4-5`
163
+ - `sonnet` → `claude-sonnet-4-20250514`
164
+ - `opus` → `claude-opus-4-6`
165
+
166
+ ## Environment Variables
167
+
168
+ - `ANTHROPIC_API_KEY` - Anthropic API key (or use Claude Code CLI auth)
169
+ - `HOST` - Host to bind server to (default: 0.0.0.0)
170
+ - `HOSTNAME` - Hostname for user-facing URLs (default: localhost)
171
+ - `PORT` - Server port (default: 3008)
172
+ - `DATA_DIR` - Data storage directory (default: ./data)
173
+ - `ALLOWED_ROOT_DIRECTORY` - Restrict file operations to specific directory
174
+ - `AUTOMAKER_MOCK_AGENT=true` - Enable mock agent mode for CI testing
175
+ - `AUTOMAKER_AUTO_LOGIN=true` - Skip login prompt in development (disabled when NODE_ENV=production)
176
+ - `VITE_HOSTNAME` - Hostname for frontend API URLs (default: localhost)
jules_branch/CONTRIBUTING.md ADDED
@@ -0,0 +1,740 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing to Automaker
2
+
3
+ Thank you for your interest in contributing to Automaker! We're excited to have you join our community of developers building the future of autonomous AI development.
4
+
5
+ Automaker is an autonomous AI development studio that provides a Kanban-based workflow where AI agents implement features in isolated git worktrees. Whether you're fixing bugs, adding features, improving documentation, or suggesting ideas, your contributions help make this project better for everyone.
6
+
7
+ This guide will help you get started with contributing to Automaker. Please take a moment to read through these guidelines to ensure a smooth contribution process.
8
+
9
+ ## Contribution License Agreement
10
+
11
+ **Important:** By submitting, pushing, or contributing any code, documentation, pull requests, issues, or other materials to the Automaker project, you agree to assign all right, title, and interest in and to your contributions, including all copyrights, patents, and other intellectual property rights, to the Core Contributors of Automaker. This assignment is irrevocable and includes the right to use, modify, distribute, and monetize your contributions in any manner.
12
+
13
+ **You understand and agree that you will have no right to receive any royalties, compensation, or other financial benefits from any revenue, income, or commercial use generated from your contributed code or any derivative works thereof.** All contributions are made without expectation of payment or financial return.
14
+
15
+ For complete details on contribution terms and rights assignment, please review [Section 5 (CONTRIBUTIONS AND RIGHTS ASSIGNMENT) of the LICENSE](LICENSE#5-contributions-and-rights-assignment).
16
+
17
+ ## Table of Contents
18
+
19
+ - [Contributing to Automaker](#contributing-to-automaker)
20
+ - [Table of Contents](#table-of-contents)
21
+ - [Getting Started](#getting-started)
22
+ - [Prerequisites](#prerequisites)
23
+ - [Fork and Clone](#fork-and-clone)
24
+ - [Development Setup](#development-setup)
25
+ - [Project Structure](#project-structure)
26
+ - [Pull Request Process](#pull-request-process)
27
+ - [Branching Strategy (RC Branches)](#branching-strategy-rc-branches)
28
+ - [Branch Naming Convention](#branch-naming-convention)
29
+ - [Commit Message Format](#commit-message-format)
30
+ - [Submitting a Pull Request](#submitting-a-pull-request)
31
+ - [1. Prepare Your Changes](#1-prepare-your-changes)
32
+ - [2. Run Pre-submission Checks](#2-run-pre-submission-checks)
33
+ - [3. Push Your Changes](#3-push-your-changes)
34
+ - [4. Open a Pull Request](#4-open-a-pull-request)
35
+ - [PR Requirements Checklist](#pr-requirements-checklist)
36
+ - [Review Process](#review-process)
37
+ - [What to Expect](#what-to-expect)
38
+ - [Review Focus Areas](#review-focus-areas)
39
+ - [Responding to Feedback](#responding-to-feedback)
40
+ - [Approval Criteria](#approval-criteria)
41
+ - [Getting Help](#getting-help)
42
+ - [Code Style Guidelines](#code-style-guidelines)
43
+ - [Testing Requirements](#testing-requirements)
44
+ - [Running Tests](#running-tests)
45
+ - [Test Frameworks](#test-frameworks)
46
+ - [End-to-End Tests (Playwright)](#end-to-end-tests-playwright)
47
+ - [Unit Tests (Vitest)](#unit-tests-vitest)
48
+ - [Writing Tests](#writing-tests)
49
+ - [When to Write Tests](#when-to-write-tests)
50
+ - [CI/CD Pipeline](#cicd-pipeline)
51
+ - [CI Checks](#ci-checks)
52
+ - [CI Testing Environment](#ci-testing-environment)
53
+ - [Viewing CI Results](#viewing-ci-results)
54
+ - [Common CI Failures](#common-ci-failures)
55
+ - [Coverage Requirements](#coverage-requirements)
56
+ - [Issue Reporting](#issue-reporting)
57
+ - [Bug Reports](#bug-reports)
58
+ - [Before Reporting](#before-reporting)
59
+ - [Bug Report Template](#bug-report-template)
60
+ - [Feature Requests](#feature-requests)
61
+ - [Before Requesting](#before-requesting)
62
+ - [Feature Request Template](#feature-request-template)
63
+ - [Security Issues](#security-issues)
64
+
65
+ ---
66
+
67
+ ## Getting Started
68
+
69
+ ### Prerequisites
70
+
71
+ Before contributing to Automaker, ensure you have the following installed on your system:
72
+
73
+ - **Node.js 18+** (tested with Node.js 22)
74
+ - Download from [nodejs.org](https://nodejs.org/)
75
+ - Verify installation: `node --version`
76
+ - **npm** (comes with Node.js)
77
+ - Verify installation: `npm --version`
78
+ - **Git** for version control
79
+ - Verify installation: `git --version`
80
+ - **Claude Code CLI** or **Anthropic API Key** (for AI agent functionality)
81
+ - Required to run the AI development features
82
+
83
+ **Optional but recommended:**
84
+
85
+ - A code editor with TypeScript support (VS Code recommended)
86
+ - GitHub CLI (`gh`) for easier PR management
87
+
88
+ ### Fork and Clone
89
+
90
+ 1. **Fork the repository** on GitHub
91
+ - Navigate to [https://github.com/AutoMaker-Org/automaker](https://github.com/AutoMaker-Org/automaker)
92
+ - Click the "Fork" button in the top-right corner
93
+ - This creates your own copy of the repository
94
+
95
+ 2. **Clone your fork locally**
96
+
97
+ ```bash
98
+ git clone https://github.com/YOUR_USERNAME/automaker.git
99
+ cd automaker
100
+ ```
101
+
102
+ 3. **Add the upstream remote** to keep your fork in sync
103
+
104
+ ```bash
105
+ git remote add upstream https://github.com/AutoMaker-Org/automaker.git
106
+ ```
107
+
108
+ 4. **Verify remotes**
109
+ ```bash
110
+ git remote -v
111
+ # Should show:
112
+ # origin https://github.com/YOUR_USERNAME/automaker.git (fetch)
113
+ # origin https://github.com/YOUR_USERNAME/automaker.git (push)
114
+ # upstream https://github.com/AutoMaker-Org/automaker.git (fetch)
115
+ # upstream https://github.com/AutoMaker-Org/automaker.git (push)
116
+ ```
117
+
118
+ ### Development Setup
119
+
120
+ 1. **Install dependencies**
121
+
122
+ ```bash
123
+ npm install
124
+ ```
125
+
126
+ 2. **Build shared packages** (required before running the app)
127
+
128
+ ```bash
129
+ npm run build:packages
130
+ ```
131
+
132
+ 3. **Start the development server**
133
+ ```bash
134
+ npm run dev # Interactive launcher - choose mode
135
+ npm run dev:web # Browser mode (web interface)
136
+ npm run dev:electron # Desktop app mode
137
+ ```
138
+
139
+ **Common development commands:**
140
+
141
+ | Command | Description |
142
+ | ------------------------ | -------------------------------- |
143
+ | `npm run dev` | Interactive development launcher |
144
+ | `npm run dev:web` | Start in browser mode |
145
+ | `npm run dev:electron` | Start desktop app |
146
+ | `npm run build` | Build all packages and apps |
147
+ | `npm run build:packages` | Build shared packages only |
148
+ | `npm run lint` | Run ESLint checks |
149
+ | `npm run format` | Format code with Prettier |
150
+ | `npm run format:check` | Check formatting without changes |
151
+ | `npm run test` | Run E2E tests (Playwright) |
152
+ | `npm run test:server` | Run server unit tests |
153
+ | `npm run test:packages` | Run package tests |
154
+ | `npm run test:all` | Run all tests |
155
+
156
+ ### Project Structure
157
+
158
+ Automaker is organized as an npm workspace monorepo:
159
+
160
+ ```
161
+ automaker/
162
+ ├── apps/
163
+ │ ├── ui/ # React + Vite + Electron frontend
164
+ │ └── server/ # Express + WebSocket backend
165
+ ├── libs/
166
+ │ ├── @automaker/types/ # Shared TypeScript types
167
+ │ ├── @automaker/utils/ # Utility functions
168
+ │ ├── @automaker/prompts/ # AI prompt templates
169
+ │ ├── @automaker/platform/ # Platform abstractions
170
+ │ ├── @automaker/model-resolver/ # AI model resolution
171
+ │ ├── @automaker/dependency-resolver/ # Dependency management
172
+ │ └── @automaker/git-utils/ # Git operations
173
+ ├── docs/ # Documentation
174
+ └── package.json # Root package configuration
175
+ ```
176
+
177
+ **Key conventions:**
178
+
179
+ - Always import from `@automaker/*` shared packages, never use relative paths to `libs/`
180
+ - Frontend code lives in `apps/ui/`
181
+ - Backend code lives in `apps/server/`
182
+ - Shared logic should be in the appropriate `libs/` package
183
+
184
+ ---
185
+
186
+ ## Pull Request Process
187
+
188
+ This section covers everything you need to know about contributing changes through pull requests, from creating your branch to getting your code merged.
189
+
190
+ ### Branching Strategy (RC Branches)
191
+
192
+ Automaker uses **Release Candidate (RC) branches** for all development work. Understanding this workflow is essential before contributing.
193
+
194
+ **How it works:**
195
+
196
+ 1. **All development happens on RC branches** - We maintain version-specific RC branches (e.g., `v0.10.0rc`, `v0.11.0rc`) where all active development occurs
197
+ 2. **RC branches are eventually merged to main** - Once an RC branch is stable and ready for release, it gets merged into `main`
198
+ 3. **Main branch is for releases only** - The `main` branch contains only released, stable code
199
+
200
+ **Before creating a PR:**
201
+
202
+ 1. **Check for the latest RC branch** - Before starting work, check the repository for the current RC branch:
203
+
204
+ ```bash
205
+ git fetch upstream
206
+ git branch -r | grep rc
207
+ ```
208
+
209
+ 2. **Base your work on the RC branch** - Create your feature branch from the latest RC branch, not from `main`:
210
+
211
+ ```bash
212
+ # Find the latest RC branch (e.g., v0.11.0rc)
213
+ git checkout upstream/v0.11.0rc
214
+ git checkout -b feature/your-feature-name
215
+ ```
216
+
217
+ 3. **Target the RC branch in your PR** - When opening your pull request, set the base branch to the current RC branch, not `main`
218
+
219
+ **Example workflow:**
220
+
221
+ ```bash
222
+ # 1. Fetch latest changes
223
+ git fetch upstream
224
+
225
+ # 2. Check for RC branches
226
+ git branch -r | grep rc
227
+ # Output: upstream/v0.11.0rc
228
+
229
+ # 3. Create your branch from the RC
230
+ git checkout -b feature/add-dark-mode upstream/v0.11.0rc
231
+
232
+ # 4. Make your changes and commit
233
+ git commit -m "feat: Add dark mode support"
234
+
235
+ # 5. Push to your fork
236
+ git push origin feature/add-dark-mode
237
+
238
+ # 6. Open PR targeting the RC branch (v0.11.0rc), NOT main
239
+ ```
240
+
241
+ **Important:** PRs opened directly against `main` will be asked to retarget to the current RC branch.
242
+
243
+ ### Branch Naming Convention
244
+
245
+ We use a consistent branch naming pattern to keep our repository organized:
246
+
247
+ ```
248
+ <type>/<description>
249
+ ```
250
+
251
+ **Branch types:**
252
+
253
+ | Type | Purpose | Example |
254
+ | ---------- | ------------------------ | --------------------------------- |
255
+ | `feature` | New functionality | `feature/add-user-authentication` |
256
+ | `fix` | Bug fixes | `fix/resolve-memory-leak` |
257
+ | `docs` | Documentation changes | `docs/update-contributing-guide` |
258
+ | `refactor` | Code restructuring | `refactor/simplify-api-handlers` |
259
+ | `test` | Adding or updating tests | `test/add-utils-unit-tests` |
260
+ | `chore` | Maintenance tasks | `chore/update-dependencies` |
261
+
262
+ **Guidelines:**
263
+
264
+ - Use lowercase letters and hyphens (no underscores or spaces)
265
+ - Keep descriptions short but descriptive
266
+ - Include issue number when applicable: `feature/123-add-login`
267
+
268
+ ```bash
269
+ # Create and checkout a new feature branch
270
+ git checkout -b feature/add-dark-mode
271
+
272
+ # Create a fix branch with issue reference
273
+ git checkout -b fix/456-resolve-login-error
274
+ ```
275
+
276
+ ### Commit Message Format
277
+
278
+ We follow the **Conventional Commits** style for clear, readable commit history:
279
+
280
+ ```
281
+ <type>: <description>
282
+
283
+ [optional body]
284
+ ```
285
+
286
+ **Commit types:**
287
+
288
+ | Type | Purpose |
289
+ | ---------- | --------------------------- |
290
+ | `feat` | New feature |
291
+ | `fix` | Bug fix |
292
+ | `docs` | Documentation only |
293
+ | `style` | Formatting (no code change) |
294
+ | `refactor` | Code restructuring |
295
+ | `test` | Adding or updating tests |
296
+ | `chore` | Maintenance tasks |
297
+
298
+ **Guidelines:**
299
+
300
+ - Use **imperative mood** ("Add feature" not "Added feature")
301
+ - Keep first line under **72 characters**
302
+ - Capitalize the first letter after the type prefix
303
+ - No period at the end of the subject line
304
+ - Add a blank line before the body for detailed explanations
305
+
306
+ **Examples:**
307
+
308
+ ```bash
309
+ # Simple commit
310
+ git commit -m "feat: Add user authentication flow"
311
+
312
+ # Commit with body for more context
313
+ git commit -m "fix: Resolve memory leak in WebSocket handler
314
+
315
+ The connection cleanup was not being called when clients
316
+ disconnected unexpectedly. Added proper cleanup in the
317
+ error handler to prevent memory accumulation."
318
+
319
+ # Documentation update
320
+ git commit -m "docs: Update API documentation"
321
+
322
+ # Refactoring
323
+ git commit -m "refactor: Simplify state management logic"
324
+ ```
325
+
326
+ ### Submitting a Pull Request
327
+
328
+ Follow these steps to submit your contribution:
329
+
330
+ #### 1. Prepare Your Changes
331
+
332
+ Ensure you've synced with the latest upstream changes from the RC branch:
333
+
334
+ ```bash
335
+ # Fetch latest changes from upstream
336
+ git fetch upstream
337
+
338
+ # Rebase your branch on the current RC branch (if needed)
339
+ git rebase upstream/v0.11.0rc # Use the current RC branch name
340
+ ```
341
+
342
+ #### 2. Run Pre-submission Checks
343
+
344
+ Before opening your PR, verify everything passes locally:
345
+
346
+ ```bash
347
+ # Run all tests
348
+ npm run test:all
349
+
350
+ # Check formatting
351
+ npm run format:check
352
+
353
+ # Run linter
354
+ npm run lint
355
+
356
+ # Build to verify no compile errors
357
+ npm run build
358
+ ```
359
+
360
+ #### 3. Push Your Changes
361
+
362
+ ```bash
363
+ # Push your branch to your fork
364
+ git push origin feature/your-feature-name
365
+ ```
366
+
367
+ #### 4. Open a Pull Request
368
+
369
+ 1. Go to your fork on GitHub
370
+ 2. Click "Compare & pull request" for your branch
371
+ 3. **Important:** Set the base repository to `AutoMaker-Org/automaker` and the base branch to the **current RC branch** (e.g., `v0.11.0rc`), not `main`
372
+ 4. Fill out the PR template completely
373
+
374
+ #### PR Requirements Checklist
375
+
376
+ Your PR should include:
377
+
378
+ - [ ] **Targets the current RC branch** (not `main`) - see [Branching Strategy](#branching-strategy-rc-branches)
379
+ - [ ] **Clear title** describing the change (use conventional commit format)
380
+ - [ ] **Description** explaining what changed and why
381
+ - [ ] **Link to related issue** (if applicable): `Closes #123` or `Fixes #456`
382
+ - [ ] **All CI checks passing** (format, lint, build, tests)
383
+ - [ ] **No merge conflicts** with the RC branch
384
+ - [ ] **Tests included** for new functionality
385
+ - [ ] **Documentation updated** if adding/changing public APIs
386
+
387
+ **Example PR Description:**
388
+
389
+ ```markdown
390
+ ## Summary
391
+
392
+ This PR adds dark mode support to the Automaker UI.
393
+
394
+ - Implements theme toggle in settings panel
395
+ - Adds CSS custom properties for theme colors
396
+ - Persists theme preference to localStorage
397
+
398
+ ## Related Issue
399
+
400
+ Closes #123
401
+
402
+ ## Testing
403
+
404
+ - [x] Tested toggle functionality in Chrome and Firefox
405
+ - [x] Verified theme persists across page reloads
406
+ - [x] Checked accessibility contrast ratios
407
+
408
+ ## Screenshots
409
+
410
+ [Include before/after screenshots for UI changes]
411
+ ```
412
+
413
+ ### Review Process
414
+
415
+ All contributions go through code review to maintain quality:
416
+
417
+ #### What to Expect
418
+
419
+ 1. **CI Checks Run First** - Automated checks (format, lint, build, tests) must pass before review
420
+ 2. **Maintainer Review** - The project maintainers will review your PR and decide whether to merge it
421
+ 3. **Feedback & Discussion** - The reviewer may ask questions or request changes
422
+ 4. **Iteration** - Make requested changes and push updates to the same branch
423
+ 5. **Approval & Merge** - Once approved and checks pass, your PR will be merged
424
+
425
+ #### Review Focus Areas
426
+
427
+ The reviewer checks for:
428
+
429
+ - **Correctness** - Does the code work as intended?
430
+ - **Clean Code** - Does it follow our [code style guidelines](#code-style-guidelines)?
431
+ - **Test Coverage** - Are new features properly tested?
432
+ - **Documentation** - Are public APIs documented?
433
+ - **Breaking Changes** - Are any breaking changes discussed first?
434
+
435
+ #### Responding to Feedback
436
+
437
+ - Respond to **all** review comments, even if just to acknowledge
438
+ - Ask questions if feedback is unclear
439
+ - Push additional commits to address feedback (don't force-push during review)
440
+ - Mark conversations as resolved once addressed
441
+
442
+ #### Approval Criteria
443
+
444
+ Your PR is ready to merge when:
445
+
446
+ - ✅ All CI checks pass
447
+ - ✅ The maintainer has approved the changes
448
+ - ✅ All review comments are addressed
449
+ - ✅ No unresolved merge conflicts
450
+
451
+ #### Getting Help
452
+
453
+ If your PR seems stuck:
454
+
455
+ - Comment asking for status update (mention @webdevcody if needed)
456
+ - Reach out on [Discord](https://discord.gg/jjem7aEDKU)
457
+ - Make sure all checks are passing and you've responded to all feedback
458
+
459
+ ---
460
+
461
+ ## Code Style Guidelines
462
+
463
+ Automaker uses automated tooling to enforce code style. Run `npm run format` to format code and `npm run lint` to check for issues. Pre-commit hooks automatically format staged files before committing.
464
+
465
+ ---
466
+
467
+ ## Testing Requirements
468
+
469
+ Testing helps prevent regressions. Automaker uses **Playwright** for end-to-end testing and **Vitest** for unit tests.
470
+
471
+ ### Running Tests
472
+
473
+ Use these commands to run tests locally:
474
+
475
+ | Command | Description |
476
+ | ------------------------------ | ------------------------------------- |
477
+ | `npm run test` | Run E2E tests (Playwright) |
478
+ | `npm run test:server` | Run server unit tests (Vitest) |
479
+ | `npm run test:packages` | Run shared package tests |
480
+ | `npm run test:all` | Run all tests |
481
+ | `npm run test:server:coverage` | Run server tests with coverage report |
482
+
483
+ **Before submitting a PR**, always run the full test suite:
484
+
485
+ ```bash
486
+ npm run test:all
487
+ ```
488
+
489
+ ### Test Frameworks
490
+
491
+ #### End-to-End Tests (Playwright)
492
+
493
+ E2E tests verify the entire application works correctly from a user's perspective.
494
+
495
+ - **Framework:** [Playwright](https://playwright.dev/)
496
+ - **Location:** `e2e/` directory
497
+ - **Test ports:** UI on port 3007, Server on port 3008
498
+
499
+ **Running E2E tests:**
500
+
501
+ ```bash
502
+ # Run all E2E tests
503
+ npm run test
504
+
505
+ # Run with headed browser (useful for debugging)
506
+ npx playwright test --headed
507
+
508
+ # Run a specific test file
509
+ npm test --workspace=@automaker/ui -- tests/example.spec.ts
510
+ ```
511
+
512
+ **E2E Test Guidelines:**
513
+
514
+ - Write tests from a user's perspective
515
+ - Use descriptive test names that explain the scenario
516
+ - Clean up test data after each test
517
+ - Use appropriate timeouts for async operations
518
+ - Prefer `locator` over direct selectors for resilience
519
+
520
+ #### Unit Tests (Vitest)
521
+
522
+ Unit tests verify individual functions and modules work correctly in isolation.
523
+
524
+ - **Framework:** [Vitest](https://vitest.dev/)
525
+ - **Location:** In the `tests/` directory within each package (e.g., `apps/server/tests/`)
526
+
527
+ **Running unit tests:**
528
+
529
+ ```bash
530
+ # Run all server unit tests
531
+ npm run test:server
532
+
533
+ # Run with coverage report
534
+ npm run test:server:coverage
535
+
536
+ # Run package tests
537
+ npm run test:packages
538
+
539
+ # Run in watch mode during development
540
+ npx vitest --watch
541
+ ```
542
+
543
+ **Unit Test Guidelines:**
544
+
545
+ - Keep tests small and focused on one behavior
546
+ - Use descriptive test names: `it('should return null when user is not found')`
547
+ - Follow the AAA pattern: Arrange, Act, Assert
548
+ - Mock external dependencies to isolate the unit under test
549
+ - Aim for meaningful coverage, not just line coverage
550
+
551
+ ### Writing Tests
552
+
553
+ #### When to Write Tests
554
+
555
+ - **New features:** All new features should include tests
556
+ - **Bug fixes:** Add a test that reproduces the bug before fixing
557
+ - **Refactoring:** Ensure existing tests pass after refactoring
558
+ - **Public APIs:** All public APIs must have test coverage
559
+
560
+ ### CI/CD Pipeline
561
+
562
+ Automaker uses **GitHub Actions** for continuous integration. Every pull request triggers automated checks.
563
+
564
+ #### CI Checks
565
+
566
+ The following checks must pass before your PR can be merged:
567
+
568
+ | Check | Description |
569
+ | ----------------- | --------------------------------------------- |
570
+ | **Format** | Verifies code is formatted with Prettier |
571
+ | **Build** | Ensures the project compiles without errors |
572
+ | **Package Tests** | Runs tests for shared `@automaker/*` packages |
573
+ | **Server Tests** | Runs server unit tests with coverage |
574
+
575
+ #### CI Testing Environment
576
+
577
+ For CI environments, Automaker supports a mock agent mode:
578
+
579
+ ```bash
580
+ # Enable mock agent mode for CI testing
581
+ AUTOMAKER_MOCK_AGENT=true npm run test
582
+ ```
583
+
584
+ This allows tests to run without requiring a real Claude API connection.
585
+
586
+ #### Viewing CI Results
587
+
588
+ 1. Go to your PR on GitHub
589
+ 2. Scroll to the "Checks" section at the bottom
590
+ 3. Click on any failed check to see detailed logs
591
+ 4. Fix issues locally and push updates
592
+
593
+ #### Common CI Failures
594
+
595
+ | Issue | Solution |
596
+ | ------------------- | --------------------------------------------- |
597
+ | Format check failed | Run `npm run format` locally |
598
+ | Build failed | Run `npm run build` and fix TypeScript errors |
599
+ | Tests failed | Run `npm run test:all` locally to reproduce |
600
+ | Coverage decreased | Add tests for new code paths |
601
+
602
+ ### Coverage Requirements
603
+
604
+ While we don't enforce strict coverage percentages, we expect:
605
+
606
+ - **New features:** Should include comprehensive tests
607
+ - **Bug fixes:** Should include a regression test
608
+ - **Critical paths:** Must have test coverage (authentication, data persistence, etc.)
609
+
610
+ To view coverage reports locally:
611
+
612
+ ```bash
613
+ npm run test:server:coverage
614
+ ```
615
+
616
+ This generates an HTML report you can open in your browser to see which lines are covered.
617
+
618
+ ---
619
+
620
+ ## Issue Reporting
621
+
622
+ Found a bug or have an idea for a new feature? We'd love to hear from you! This section explains how to report issues effectively.
623
+
624
+ ### Bug Reports
625
+
626
+ When reporting a bug, please provide as much information as possible to help us understand and reproduce the issue.
627
+
628
+ #### Before Reporting
629
+
630
+ 1. **Search existing issues** - Check if the bug has already been reported
631
+ 2. **Try the latest version** - Make sure you're running the latest version of Automaker
632
+ 3. **Reproduce the issue** - Verify you can consistently reproduce the bug
633
+
634
+ #### Bug Report Template
635
+
636
+ When creating a bug report, include:
637
+
638
+ - **Title:** A clear, descriptive title summarizing the issue
639
+ - **Environment:**
640
+ - Operating System and version
641
+ - Node.js version (`node --version`)
642
+ - Automaker version or commit hash
643
+ - **Steps to Reproduce:** Numbered list of steps to reproduce the bug
644
+ - **Expected Behavior:** What you expected to happen
645
+ - **Actual Behavior:** What actually happened
646
+ - **Logs/Screenshots:** Any relevant error messages, console output, or screenshots
647
+
648
+ **Example Bug Report:**
649
+
650
+ ```markdown
651
+ ## Bug: WebSocket connection drops after 5 minutes of inactivity
652
+
653
+ ### Environment
654
+
655
+ - OS: Windows 11
656
+ - Node.js: 22.11.0
657
+ - Automaker: commit abc1234
658
+
659
+ ### Steps to Reproduce
660
+
661
+ 1. Start the application with `npm run dev:web`
662
+ 2. Open the Kanban board
663
+ 3. Leave the browser tab open for 5+ minutes without interaction
664
+ 4. Try to move a card
665
+
666
+ ### Expected Behavior
667
+
668
+ The card should move to the new column.
669
+
670
+ ### Actual Behavior
671
+
672
+ The UI shows "Connection lost" and the card doesn't move.
673
+
674
+ ### Logs
675
+
676
+ [WebSocket] Connection closed: 1006
677
+ ```
678
+
679
+ ### Feature Requests
680
+
681
+ We welcome ideas for improving Automaker! Here's how to submit a feature request:
682
+
683
+ #### Before Requesting
684
+
685
+ 1. **Check existing issues** - Your idea may already be proposed or in development
686
+ 2. **Consider scope** - Think about whether the feature fits Automaker's mission as an autonomous AI development studio
687
+
688
+ #### Feature Request Template
689
+
690
+ A good feature request includes:
691
+
692
+ - **Title:** A brief, descriptive title
693
+ - **Problem Statement:** What problem does this feature solve?
694
+ - **Proposed Solution:** How do you envision this working?
695
+ - **Alternatives Considered:** What other approaches did you consider?
696
+ - **Additional Context:** Mockups, examples, or references that help explain your idea
697
+
698
+ **Example Feature Request:**
699
+
700
+ ```markdown
701
+ ## Feature: Dark Mode Support
702
+
703
+ ### Problem Statement
704
+
705
+ Working late at night, the bright UI causes eye strain and doesn't match
706
+ my system's dark theme preference.
707
+
708
+ ### Proposed Solution
709
+
710
+ Add a theme toggle in the settings panel that allows switching between
711
+ light and dark modes. Ideally, it should also detect system preference.
712
+
713
+ ### Alternatives Considered
714
+
715
+ - Browser extension to force dark mode (doesn't work well with custom styling)
716
+ - Custom CSS override (breaks with updates)
717
+
718
+ ### Additional Context
719
+
720
+ Similar to how VS Code handles themes - a dropdown in settings with
721
+ immediate preview.
722
+ ```
723
+
724
+ ### Security Issues
725
+
726
+ **Important:** If you discover a security vulnerability, please do NOT open a public issue. Instead:
727
+
728
+ 1. Join our [Discord server](https://discord.gg/jjem7aEDKU) and send a direct message to the user `@webdevcody`
729
+ 2. Include detailed steps to reproduce
730
+ 3. Allow time for us to address the issue before public disclosure
731
+
732
+ We take security seriously and appreciate responsible disclosure.
733
+
734
+ ---
735
+
736
+ For license and contribution terms, see the [LICENSE](LICENSE) file in the repository root and the [README.md](README.md#license) for more details.
737
+
738
+ ---
739
+
740
+ Thank you for contributing to Automaker!
jules_branch/DISCLAIMER.md ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Security Disclaimer
2
+
3
+ ## Important Warning
4
+
5
+ **Automaker uses AI-powered tooling that has access to your operating system and can read, modify, and delete files. Use at your own risk.**
6
+
7
+ ## Risk Assessment
8
+
9
+ This software utilizes AI agents (such as Claude) that can:
10
+
11
+ - **Read files** from your file system
12
+ - **Write and modify files** in your projects
13
+ - **Delete files** when instructed
14
+ - **Execute commands** on your operating system
15
+ - **Access environment variables** and configuration files
16
+
17
+ While we have made efforts to review this codebase for security vulnerabilities and implement safeguards, **you assume all risk** when running this software.
18
+
19
+ ## Recommendations
20
+
21
+ ### 1. Review the Code First
22
+
23
+ Before running Automaker, we strongly recommend reviewing the source code yourself to understand what operations it performs and ensure you are comfortable with its behavior.
24
+
25
+ ### 2. Use Sandboxing (Highly Recommended)
26
+
27
+ **We do not recommend running Automaker directly on your local computer** due to the risk of AI agents having access to your entire file system. Instead, consider:
28
+
29
+ - **Docker**: Run Automaker in a Docker container to isolate it from your host system
30
+ - **Virtual Machine**: Use a VM (such as VirtualBox, VMware, or Parallels) to create an isolated environment
31
+ - **Cloud Development Environment**: Use a cloud-based development environment that provides isolation
32
+
33
+ #### Running in Isolated Docker Container
34
+
35
+ For maximum security, run Automaker in an isolated Docker container that **cannot access your laptop's files**:
36
+
37
+ ```bash
38
+ # 1. Set your API key (bash/Linux/Mac - creates UTF-8 file)
39
+ echo "ANTHROPIC_API_KEY=your-api-key-here" > .env
40
+
41
+ # On Windows PowerShell, use instead:
42
+ Set-Content -Path .env -Value "ANTHROPIC_API_KEY=your-api-key-here" -Encoding UTF8
43
+
44
+ # 2. Build and run isolated container
45
+ docker-compose up -d
46
+
47
+ # 3. Access the UI at http://localhost:3007
48
+ # API at http://localhost:3008/api/health
49
+ ```
50
+
51
+ The container uses only Docker-managed volumes and has no access to your host filesystem. See [docker-isolation.md](docs/docker-isolation.md) for full documentation.
52
+
53
+ ### 3. Limit Access
54
+
55
+ If you must run locally:
56
+
57
+ - Create a dedicated user account with limited permissions
58
+ - Only grant access to specific project directories
59
+ - Avoid running with administrator/root privileges
60
+ - Keep sensitive files and credentials outside of project directories
61
+
62
+ ### 4. Monitor Activity
63
+
64
+ - Review the agent's actions in the output logs
65
+ - Pay attention to file modifications and command executions
66
+ - Stop the agent immediately if you notice unexpected behavior
67
+
68
+ ## No Warranty & Limitation of Liability
69
+
70
+ THE SOFTWARE UTILIZES ARTIFICIAL INTELLIGENCE TO GENERATE CODE, EXECUTE COMMANDS, AND INTERACT WITH YOUR FILE SYSTEM. YOU ACKNOWLEDGE THAT AI SYSTEMS CAN BE UNPREDICTABLE, MAY GENERATE INCORRECT, INSECURE, OR DESTRUCTIVE CODE, AND MAY TAKE ACTIONS THAT COULD DAMAGE YOUR SYSTEM, FILES, OR HARDWARE.
71
+
72
+ This software is provided "as is", without warranty of any kind, express or implied. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, including but not limited to hardware damage, data loss, financial loss, or business interruption, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
73
+
74
+ ## Acknowledgment
75
+
76
+ By using Automaker, you acknowledge that:
77
+
78
+ 1. You have read and understood this disclaimer
79
+ 2. You accept full responsibility for any consequences of using this software
80
+ 3. You understand the risks of AI agents having access to your operating system
81
+ 4. You agree to take appropriate precautions as outlined above
82
+
83
+ ---
84
+
85
+ **If you are not comfortable with these risks, do not use this software.**
jules_branch/Dockerfile ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Automaker Multi-Stage Dockerfile
2
+ # Single Dockerfile for both server and UI builds
3
+ # Usage:
4
+ # docker build --target server -t automaker-server .
5
+ # docker build --target ui -t automaker-ui .
6
+ # Or use docker-compose which selects targets automatically
7
+
8
+ # =============================================================================
9
+ # BASE STAGE - Common setup for all builds (DRY: defined once, used by all)
10
+ # =============================================================================
11
+ FROM node:22-slim AS base
12
+
13
+ # Install build dependencies for native modules (node-pty)
14
+ RUN apt-get update && apt-get install -y --no-install-recommends \
15
+ python3 make g++ \
16
+ && rm -rf /var/lib/apt/lists/*
17
+
18
+ WORKDIR /app
19
+
20
+ # Copy root package files
21
+ COPY package*.json ./
22
+
23
+ # Copy all libs package.json files (centralized - add new libs here)
24
+ COPY libs/types/package*.json ./libs/types/
25
+ COPY libs/utils/package*.json ./libs/utils/
26
+ COPY libs/prompts/package*.json ./libs/prompts/
27
+ COPY libs/platform/package*.json ./libs/platform/
28
+ COPY libs/spec-parser/package*.json ./libs/spec-parser/
29
+ COPY libs/model-resolver/package*.json ./libs/model-resolver/
30
+ COPY libs/dependency-resolver/package*.json ./libs/dependency-resolver/
31
+ COPY libs/git-utils/package*.json ./libs/git-utils/
32
+ COPY libs/spec-parser/package*.json ./libs/spec-parser/
33
+
34
+ # Copy scripts (needed by npm workspace)
35
+ COPY scripts ./scripts
36
+
37
+ # =============================================================================
38
+ # SERVER BUILD STAGE
39
+ # =============================================================================
40
+ FROM base AS server-builder
41
+
42
+ # Copy server-specific package.json
43
+ COPY apps/server/package*.json ./apps/server/
44
+
45
+ # Install dependencies (--ignore-scripts to skip husky/prepare, then rebuild native modules)
46
+ RUN npm ci --ignore-scripts && npm rebuild node-pty
47
+
48
+ # Copy all source files
49
+ COPY libs ./libs
50
+ COPY apps/server ./apps/server
51
+
52
+ # Build packages in dependency order, then build server
53
+ RUN npm run build:packages && npm run build --workspace=apps/server
54
+
55
+ # =============================================================================
56
+ # SERVER PRODUCTION STAGE
57
+ # =============================================================================
58
+ FROM node:22-slim AS server
59
+
60
+ # Build argument for tracking which commit this image was built from
61
+ ARG GIT_COMMIT_SHA=unknown
62
+ LABEL automaker.git.commit.sha="${GIT_COMMIT_SHA}"
63
+
64
+ # Build arguments for user ID matching (allows matching host user for mounted volumes)
65
+ # Override at build time: docker build --build-arg UID=$(id -u) --build-arg GID=$(id -g) ...
66
+ ARG UID=1001
67
+ ARG GID=1001
68
+
69
+ # Install git, curl, bash (for terminal), gosu (for user switching), and GitHub CLI (pinned version, multi-arch)
70
+ # Also install Playwright/Chromium system dependencies (aligns with playwright install-deps on Debian/Ubuntu)
71
+ RUN apt-get update && apt-get install -y --no-install-recommends \
72
+ git curl bash gosu ca-certificates openssh-client \
73
+ # Playwright/Chromium dependencies
74
+ libglib2.0-0 libnss3 libnspr4 libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 \
75
+ libcups2 libdrm2 libxkbcommon0 libatspi2.0-0 libxcomposite1 libxdamage1 \
76
+ libxfixes3 libxrandr2 libgbm1 libasound2 libpango-1.0-0 libcairo2 \
77
+ libx11-6 libx11-xcb1 libxcb1 libxext6 libxrender1 libxss1 libxtst6 \
78
+ libxshmfence1 libgtk-3-0 libexpat1 libfontconfig1 fonts-liberation \
79
+ xdg-utils libpangocairo-1.0-0 libpangoft2-1.0-0 libu2f-udev libvulkan1 \
80
+ && GH_VERSION="2.63.2" \
81
+ && ARCH=$(uname -m) \
82
+ && case "$ARCH" in \
83
+ x86_64) GH_ARCH="amd64" ;; \
84
+ aarch64|arm64) GH_ARCH="arm64" ;; \
85
+ *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \
86
+ esac \
87
+ && curl -L "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${GH_ARCH}.tar.gz" -o gh.tar.gz \
88
+ && tar -xzf gh.tar.gz \
89
+ && mv gh_${GH_VERSION}_linux_${GH_ARCH}/bin/gh /usr/local/bin/gh \
90
+ && rm -rf gh.tar.gz gh_${GH_VERSION}_linux_${GH_ARCH} \
91
+ && rm -rf /var/lib/apt/lists/*
92
+
93
+ # Install Claude CLI globally (available to all users via npm global bin)
94
+ RUN npm install -g @anthropic-ai/claude-code
95
+
96
+ # Create non-root user with home directory BEFORE installing Cursor CLI
97
+ # Uses UID/GID build args to match host user for mounted volume permissions
98
+ # Use -o flag to allow non-unique IDs (GID 1000 may already exist as 'node' group)
99
+ RUN groupadd -o -g ${GID} automaker && \
100
+ useradd -o -u ${UID} -g automaker -m -d /home/automaker -s /bin/bash automaker && \
101
+ mkdir -p /home/automaker/.local/bin && \
102
+ mkdir -p /home/automaker/.cursor && \
103
+ chown -R automaker:automaker /home/automaker && \
104
+ chmod 700 /home/automaker/.cursor
105
+
106
+ # Install Cursor CLI as the automaker user
107
+ # Set HOME explicitly and install to /home/automaker/.local/bin/
108
+ USER automaker
109
+ ENV HOME=/home/automaker
110
+ RUN curl https://cursor.com/install -fsS | bash && \
111
+ echo "=== Checking Cursor CLI installation ===" && \
112
+ ls -la /home/automaker/.local/bin/ && \
113
+ echo "=== PATH is: $PATH ===" && \
114
+ (which cursor-agent && cursor-agent --version) || echo "cursor-agent installed (may need auth setup)"
115
+
116
+ # Install OpenCode CLI (for multi-provider AI model access)
117
+ RUN curl -fsSL https://opencode.ai/install | bash && \
118
+ echo "=== Checking OpenCode CLI installation ===" && \
119
+ ls -la /home/automaker/.local/bin/ && \
120
+ (which opencode && opencode --version) || echo "opencode installed (may need auth setup)"
121
+
122
+ USER root
123
+
124
+ # Add PATH to profile so it's available in all interactive shells (for login shells)
125
+ RUN mkdir -p /etc/profile.d && \
126
+ echo 'export PATH="/home/automaker/.local/bin:$PATH"' > /etc/profile.d/cursor-cli.sh && \
127
+ chmod +x /etc/profile.d/cursor-cli.sh
128
+
129
+ # Add to automaker's .bashrc for bash interactive shells
130
+ RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /home/automaker/.bashrc && \
131
+ chown automaker:automaker /home/automaker/.bashrc
132
+
133
+ # Also add to root's .bashrc since docker exec defaults to root
134
+ RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /root/.bashrc
135
+
136
+ WORKDIR /app
137
+
138
+ # Copy root package.json (needed for workspace resolution)
139
+ COPY --from=server-builder /app/package*.json ./
140
+
141
+ # Copy built libs (workspace packages are symlinked in node_modules)
142
+ COPY --from=server-builder /app/libs ./libs
143
+
144
+ # Copy built server
145
+ COPY --from=server-builder /app/apps/server/dist ./apps/server/dist
146
+ COPY --from=server-builder /app/apps/server/package*.json ./apps/server/
147
+
148
+ # Copy node_modules (includes symlinks to libs)
149
+ COPY --from=server-builder /app/node_modules ./node_modules
150
+
151
+ # Install Playwright Chromium browser for AI agent verification tests
152
+ # This adds ~300MB to the image but enables automated testing mode out of the box
153
+ # Using the locally installed playwright ensures we use the pinned version from package-lock.json
154
+ USER automaker
155
+ RUN ./node_modules/.bin/playwright install chromium && \
156
+ echo "=== Playwright Chromium installed ===" && \
157
+ ls -la /home/automaker/.cache/ms-playwright/
158
+ USER root
159
+
160
+ # Create data and projects directories
161
+ RUN mkdir -p /data /projects && chown automaker:automaker /data /projects
162
+
163
+ # Configure git for mounted volumes and authentication
164
+ # Use --system so it's not overwritten by mounted user .gitconfig
165
+ RUN git config --system --add safe.directory '*' && \
166
+ # Use gh as credential helper (works with GH_TOKEN env var)
167
+ git config --system credential.helper '!gh auth git-credential'
168
+
169
+ # Copy entrypoint script for fixing permissions on mounted volumes
170
+ COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
171
+ RUN chmod +x /usr/local/bin/docker-entrypoint.sh
172
+
173
+ # Note: We stay as root here so entrypoint can fix permissions
174
+ # The entrypoint script will switch to automaker user before running the command
175
+
176
+ # Environment variables
177
+ ENV PORT=3008
178
+ ENV DATA_DIR=/data
179
+ ENV HOME=/home/automaker
180
+ # Add user's local bin to PATH for cursor-agent
181
+ ENV PATH="/home/automaker/.local/bin:${PATH}"
182
+
183
+ # Expose port
184
+ EXPOSE 3008
185
+
186
+ # Health check (using curl since it's already installed, more reliable than busybox wget)
187
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
188
+ CMD curl -f http://localhost:3008/api/health || exit 1
189
+
190
+ # Use entrypoint to fix permissions before starting
191
+ ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
192
+
193
+ # Start server
194
+ CMD ["node", "apps/server/dist/index.js"]
195
+
196
+ # =============================================================================
197
+ # UI BUILD STAGE
198
+ # =============================================================================
199
+ FROM base AS ui-builder
200
+
201
+ # Copy UI-specific package.json
202
+ COPY apps/ui/package*.json ./apps/ui/
203
+
204
+ # Install dependencies (--ignore-scripts to skip husky and build:packages in prepare script)
205
+ RUN npm ci --ignore-scripts
206
+
207
+ # Copy all source files
208
+ COPY libs ./libs
209
+ COPY apps/ui ./apps/ui
210
+
211
+ # Build packages in dependency order, then build UI
212
+ # When VITE_SERVER_URL is empty, the UI uses relative URLs (e.g., /api/...) which nginx proxies
213
+ # to the server container. This avoids CORS issues entirely in Docker Compose setups.
214
+ # Override at build time if needed: --build-arg VITE_SERVER_URL=http://api.example.com
215
+ ARG VITE_SERVER_URL=
216
+ ENV VITE_SKIP_ELECTRON=true
217
+ ENV VITE_SERVER_URL=${VITE_SERVER_URL}
218
+ RUN npm run build:packages && npm run build --workspace=apps/ui
219
+
220
+ # =============================================================================
221
+ # UI PRODUCTION STAGE
222
+ # =============================================================================
223
+ FROM nginx:alpine AS ui
224
+
225
+ # Build argument for tracking which commit this image was built from
226
+ ARG GIT_COMMIT_SHA=unknown
227
+ LABEL automaker.git.commit.sha="${GIT_COMMIT_SHA}"
228
+
229
+ # Copy built files
230
+ COPY --from=ui-builder /app/apps/ui/dist /usr/share/nginx/html
231
+
232
+ # Copy nginx config for SPA routing
233
+ COPY apps/ui/nginx.conf /etc/nginx/conf.d/default.conf
234
+
235
+ EXPOSE 80
236
+
237
+ CMD ["nginx", "-g", "daemon off;"]
jules_branch/Dockerfile.dev ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Automaker Development Dockerfile
2
+ # For development with live reload via volume mounting
3
+ # Source code is NOT copied - it's mounted as a volume
4
+ #
5
+ # Usage:
6
+ # docker compose -f docker-compose.dev.yml up
7
+
8
+ FROM node:22-slim
9
+
10
+ # Install build dependencies for native modules (node-pty) and runtime tools
11
+ # Also install Playwright/Chromium system dependencies (aligns with playwright install-deps on Debian/Ubuntu)
12
+ RUN apt-get update && apt-get install -y --no-install-recommends \
13
+ python3 make g++ \
14
+ git curl bash gosu ca-certificates openssh-client \
15
+ # Playwright/Chromium dependencies
16
+ libglib2.0-0 libnss3 libnspr4 libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 \
17
+ libcups2 libdrm2 libxkbcommon0 libatspi2.0-0 libxcomposite1 libxdamage1 \
18
+ libxfixes3 libxrandr2 libgbm1 libasound2 libpango-1.0-0 libcairo2 \
19
+ libx11-6 libx11-xcb1 libxcb1 libxext6 libxrender1 libxss1 libxtst6 \
20
+ libxshmfence1 libgtk-3-0 libexpat1 libfontconfig1 fonts-liberation \
21
+ xdg-utils libpangocairo-1.0-0 libpangoft2-1.0-0 libu2f-udev libvulkan1 \
22
+ && GH_VERSION="2.63.2" \
23
+ && ARCH=$(uname -m) \
24
+ && case "$ARCH" in \
25
+ x86_64) GH_ARCH="amd64" ;; \
26
+ aarch64|arm64) GH_ARCH="arm64" ;; \
27
+ *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \
28
+ esac \
29
+ && curl -L "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_${GH_ARCH}.tar.gz" -o gh.tar.gz \
30
+ && tar -xzf gh.tar.gz \
31
+ && mv gh_${GH_VERSION}_linux_${GH_ARCH}/bin/gh /usr/local/bin/gh \
32
+ && rm -rf gh.tar.gz gh_${GH_VERSION}_linux_${GH_ARCH} \
33
+ && rm -rf /var/lib/apt/lists/*
34
+
35
+ # Install Claude CLI globally
36
+ RUN npm install -g @anthropic-ai/claude-code
37
+
38
+ # Build arguments for user ID matching (allows matching host user for mounted volumes)
39
+ # Override at build time: docker-compose build --build-arg UID=$(id -u) --build-arg GID=$(id -g)
40
+ ARG UID=1001
41
+ ARG GID=1001
42
+
43
+ # Create non-root user with configurable UID/GID
44
+ # Use -o flag to allow non-unique IDs (GID 1000 may already exist as 'node' group)
45
+ RUN groupadd -o -g ${GID} automaker && \
46
+ useradd -o -u ${UID} -g automaker -m -d /home/automaker -s /bin/bash automaker && \
47
+ mkdir -p /home/automaker/.local/bin && \
48
+ mkdir -p /home/automaker/.cursor && \
49
+ chown -R automaker:automaker /home/automaker && \
50
+ chmod 700 /home/automaker/.cursor
51
+
52
+ # Install Cursor CLI as automaker user
53
+ USER automaker
54
+ ENV HOME=/home/automaker
55
+ RUN curl https://cursor.com/install -fsS | bash || true
56
+ USER root
57
+
58
+ # Add PATH to profile for Cursor CLI
59
+ RUN mkdir -p /etc/profile.d && \
60
+ echo 'export PATH="/home/automaker/.local/bin:$PATH"' > /etc/profile.d/cursor-cli.sh && \
61
+ chmod +x /etc/profile.d/cursor-cli.sh
62
+
63
+ # Add to user bashrc files
64
+ RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /home/automaker/.bashrc && \
65
+ chown automaker:automaker /home/automaker/.bashrc
66
+ RUN echo 'export PATH="/home/automaker/.local/bin:$PATH"' >> /root/.bashrc
67
+
68
+ WORKDIR /app
69
+
70
+ # Create directories with proper permissions
71
+ RUN mkdir -p /data /projects && chown automaker:automaker /data /projects
72
+
73
+ # Configure git for mounted volumes
74
+ RUN git config --system --add safe.directory '*' && \
75
+ git config --system credential.helper '!gh auth git-credential'
76
+
77
+ # Copy entrypoint script
78
+ COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
79
+ RUN chmod +x /usr/local/bin/docker-entrypoint.sh
80
+
81
+ # Environment variables
82
+ ENV PORT=3008
83
+ ENV DATA_DIR=/data
84
+ ENV HOME=/home/automaker
85
+ ENV PATH="/home/automaker/.local/bin:${PATH}"
86
+
87
+ # Expose both dev ports
88
+ EXPOSE 3007 3008
89
+
90
+ # Use entrypoint for permission handling
91
+ ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
92
+
93
+ # Default command - will be overridden by docker-compose
94
+ CMD ["npm", "run", "dev:web"]
jules_branch/LICENSE ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Project Status
2
+
3
+ **This project is no longer actively maintained.** The codebase is provided as-is for those who wish to use, study, or fork it. No bug fixes, security updates, or new features are being developed. Community contributions may still be accepted, but there is no guarantee of review or merge.
4
+
5
+ ---
6
+
7
+ MIT License
8
+
9
+ Copyright (c) 2025 Automaker Core Contributors
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
jules_branch/OPENCODE_CONFIG_CONTENT ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",}
jules_branch/README.md ADDED
@@ -0,0 +1,714 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <p align="center">
2
+ <img src="apps/ui/public/readme_logo.svg" alt="Automaker Logo" height="80" />
3
+ </p>
4
+
5
+ > **[!TIP]**
6
+ >
7
+ > **Learn more about Agentic Coding!**
8
+ >
9
+ > Automaker itself was built by a group of engineers using AI and agentic coding techniques to build features faster than ever. By leveraging tools like Cursor IDE and Claude Code CLI, the team orchestrated AI agents to implement complex functionality in days instead of weeks.
10
+ >
11
+ > **Learn how:** Master these same techniques and workflows in the [Agentic Jumpstart course](https://agenticjumpstart.com/?utm=automaker-gh).
12
+
13
+ # Automaker
14
+
15
+ **Stop typing code. Start directing AI agents.**
16
+
17
+ <details open>
18
+ <summary><h2>Table of Contents</h2></summary>
19
+
20
+ - [What Makes Automaker Different?](#what-makes-automaker-different)
21
+ - [The Workflow](#the-workflow)
22
+ - [Powered by Claude Agent SDK](#powered-by-claude-agent-sdk)
23
+ - [Why This Matters](#why-this-matters)
24
+ - [Security Disclaimer](#security-disclaimer)
25
+ - [Community & Support](#community--support)
26
+ - [Getting Started](#getting-started)
27
+ - [Prerequisites](#prerequisites)
28
+ - [Quick Start](#quick-start)
29
+ - [How to Run](#how-to-run)
30
+ - [Development Mode](#development-mode)
31
+ - [Interactive TUI Launcher](#interactive-tui-launcher-recommended-for-new-users)
32
+ - [Building for Production](#building-for-production)
33
+ - [Testing](#testing)
34
+ - [Linting](#linting)
35
+ - [Environment Configuration](#environment-configuration)
36
+ - [Authentication Setup](#authentication-setup)
37
+ - [Features](#features)
38
+ - [Core Workflow](#core-workflow)
39
+ - [AI & Planning](#ai--planning)
40
+ - [Project Management](#project-management)
41
+ - [Collaboration & Review](#collaboration--review)
42
+ - [Developer Tools](#developer-tools)
43
+ - [Advanced Features](#advanced-features)
44
+ - [Tech Stack](#tech-stack)
45
+ - [Frontend](#frontend)
46
+ - [Backend](#backend)
47
+ - [Testing & Quality](#testing--quality)
48
+ - [Shared Libraries](#shared-libraries)
49
+ - [Available Views](#available-views)
50
+ - [Architecture](#architecture)
51
+ - [Monorepo Structure](#monorepo-structure)
52
+ - [How It Works](#how-it-works)
53
+ - [Key Architectural Patterns](#key-architectural-patterns)
54
+ - [Security & Isolation](#security--isolation)
55
+ - [Data Storage](#data-storage)
56
+ - [Learn More](#learn-more)
57
+ - [License](#license)
58
+
59
+ </details>
60
+
61
+ Automaker is an autonomous AI development studio that transforms how you build software. Instead of manually writing every line of code, you describe features on a Kanban board and watch as AI agents powered by Claude Agent SDK automatically implement them. Built with React, Vite, Electron, and Express, Automaker provides a complete workflow for managing AI agents through a desktop application (or web browser), with features like real-time streaming, git worktree isolation, plan approval, and multi-agent task execution.
62
+
63
+ ![Automaker UI](https://i.imgur.com/jdwKydM.png)
64
+
65
+ ## What Makes Automaker Different?
66
+
67
+ Traditional development tools help you write code. Automaker helps you **orchestrate AI agents** to build entire features autonomously. Think of it as having a team of AI developers working for you—you define what needs to be built, and Automaker handles the implementation.
68
+
69
+ ### The Workflow
70
+
71
+ 1. **Add Features** - Describe features you want built (with text, images, or screenshots)
72
+ 2. **Move to "In Progress"** - Automaker automatically assigns an AI agent to implement the feature
73
+ 3. **Watch It Build** - See real-time progress as the agent writes code, runs tests, and makes changes
74
+ 4. **Review & Verify** - Review the changes, run tests, and approve when ready
75
+ 5. **Ship Faster** - Build entire applications in days, not weeks
76
+
77
+ ### Powered by Claude Agent SDK
78
+
79
+ Automaker leverages the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) to give AI agents full access to your codebase. Agents can read files, write code, execute commands, run tests, and make git commits—all while working in isolated git worktrees to keep your main branch safe. The SDK provides autonomous AI agents that can use tools, make decisions, and complete complex multi-step tasks without constant human intervention.
80
+
81
+ ### Why This Matters
82
+
83
+ The future of software development is **agentic coding**—where developers become architects directing AI agents rather than manual coders. Automaker puts this future in your hands today, letting you experience what it's like to build software 10x faster with AI agents handling the implementation while you focus on architecture and business logic.
84
+
85
+ ## Community & Support
86
+
87
+ Join the **Agentic Jumpstart** to connect with other builders exploring **agentic coding** and autonomous development workflows.
88
+
89
+ In the Discord, you can:
90
+
91
+ - 💬 Discuss agentic coding patterns and best practices
92
+ - 🧠 Share ideas for AI-driven development workflows
93
+ - 🛠️ Get help setting up or extending Automaker
94
+ - 🚀 Show off projects built with AI agents
95
+ - 🤝 Collaborate with other developers and contributors
96
+
97
+ 👉 **Join the Discord:** [Agentic Jumpstart Discord](https://discord.gg/jjem7aEDKU)
98
+
99
+ ---
100
+
101
+ ## Getting Started
102
+
103
+ ### Prerequisites
104
+
105
+ - **Node.js 22+** (required: >=22.0.0 <23.0.0)
106
+ - **npm** (comes with Node.js)
107
+ - **[Claude Code CLI](https://code.claude.com/docs/en/overview)** - Install and authenticate with your Anthropic subscription. Automaker integrates with your authenticated Claude Code CLI to access Claude models.
108
+
109
+ ### Quick Start
110
+
111
+ ```bash
112
+ # 1. Clone the repository
113
+ git clone https://github.com/AutoMaker-Org/automaker.git
114
+ cd automaker
115
+
116
+ # 2. Install dependencies
117
+ npm install
118
+
119
+ # 3. Start Automaker
120
+ npm run dev
121
+ # Choose between:
122
+ # 1. Web Application (browser at localhost:3007)
123
+ # 2. Desktop Application (Electron - recommended)
124
+ ```
125
+
126
+ **Authentication:** Automaker integrates with your authenticated Claude Code CLI. Make sure you have [installed and authenticated](https://code.claude.com/docs/en/quickstart) the Claude Code CLI before running Automaker. Your CLI credentials will be detected automatically.
127
+
128
+ **For Development:** `npm run dev` starts the development server with Vite live reload and hot module replacement for fast refresh and instant updates as you make changes.
129
+
130
+ ## How to Run
131
+
132
+ ### Development Mode
133
+
134
+ Start Automaker in development mode:
135
+
136
+ ```bash
137
+ npm run dev
138
+ ```
139
+
140
+ This will prompt you to choose your run mode, or you can specify a mode directly:
141
+
142
+ #### Electron Desktop App (Recommended)
143
+
144
+ ```bash
145
+ # Standard development mode
146
+ npm run dev:electron
147
+
148
+ # With DevTools open automatically
149
+ npm run dev:electron:debug
150
+
151
+ # For WSL (Windows Subsystem for Linux)
152
+ npm run dev:electron:wsl
153
+
154
+ # For WSL with GPU acceleration
155
+ npm run dev:electron:wsl:gpu
156
+ ```
157
+
158
+ #### Web Browser Mode
159
+
160
+ ```bash
161
+ # Run in web browser (http://localhost:3007)
162
+ npm run dev:web
163
+ ```
164
+
165
+ ### Interactive TUI Launcher (Recommended for New Users)
166
+
167
+ For a user-friendly interactive menu, use the built-in TUI launcher script:
168
+
169
+ ```bash
170
+ # Show interactive menu with all launch options
171
+ ./start-automaker.sh
172
+
173
+ # Or launch directly without menu
174
+ ./start-automaker.sh web # Web browser
175
+ ./start-automaker.sh electron # Desktop app
176
+ ./start-automaker.sh electron-debug # Desktop + DevTools
177
+
178
+ # Additional options
179
+ ./start-automaker.sh --help # Show all available options
180
+ ./start-automaker.sh --version # Show version information
181
+ ./start-automaker.sh --check-deps # Verify project dependencies
182
+ ./start-automaker.sh --no-colors # Disable colored output
183
+ ./start-automaker.sh --no-history # Don't remember last choice
184
+ ```
185
+
186
+ **Features:**
187
+
188
+ - 🎨 Beautiful terminal UI with gradient colors and ASCII art
189
+ - ⌨️ Interactive menu (press 1-3 to select, Q to exit)
190
+ - 💾 Remembers your last choice
191
+ - ✅ Pre-flight checks (validates Node.js, npm, dependencies)
192
+ - 📏 Responsive layout (adapts to terminal size)
193
+ - ⏱️ 30-second timeout for hands-free selection
194
+ - 🌐 Cross-shell compatible (bash/zsh)
195
+
196
+ **History File:**
197
+ Your last selected mode is saved in `~/.automaker_launcher_history` for quick re-runs.
198
+
199
+ ### Building for Production
200
+
201
+ #### Web Application
202
+
203
+ ```bash
204
+ # Build for web deployment (uses Vite)
205
+ npm run build
206
+ ```
207
+
208
+ #### Desktop Application
209
+
210
+ ```bash
211
+ # Build for current platform (macOS/Windows/Linux)
212
+ npm run build:electron
213
+
214
+ # Platform-specific builds
215
+ npm run build:electron:mac # macOS (DMG + ZIP, x64 + arm64)
216
+ npm run build:electron:win # Windows (NSIS installer, x64)
217
+ npm run build:electron:linux # Linux (AppImage + DEB + RPM, x64)
218
+
219
+ # Output directory: apps/ui/release/
220
+ ```
221
+
222
+ **Linux Distribution Packages:**
223
+
224
+ - **AppImage**: Universal format, works on any Linux distribution
225
+ - **DEB**: Ubuntu, Debian, Linux Mint, Pop!\_OS
226
+ - **RPM**: Fedora, RHEL, Rocky Linux, AlmaLinux, openSUSE
227
+
228
+ **Installing on Fedora/RHEL:**
229
+
230
+ ```bash
231
+ # Download the RPM package
232
+ wget https://github.com/AutoMaker-Org/automaker/releases/latest/download/Automaker-<version>-x86_64.rpm
233
+
234
+ # Install with dnf (Fedora)
235
+ sudo dnf install ./Automaker-<version>-x86_64.rpm
236
+
237
+ # Or with yum (RHEL/CentOS)
238
+ sudo yum localinstall ./Automaker-<version>-x86_64.rpm
239
+ ```
240
+
241
+ #### Docker Deployment
242
+
243
+ Docker provides the most secure way to run Automaker by isolating it from your host filesystem.
244
+
245
+ ```bash
246
+ # Build and run with Docker Compose
247
+ docker-compose up -d
248
+
249
+ # Access UI at http://localhost:3007
250
+ # API at http://localhost:3008
251
+
252
+ # View logs
253
+ docker-compose logs -f
254
+
255
+ # Stop containers
256
+ docker-compose down
257
+ ```
258
+
259
+ ##### Authentication
260
+
261
+ Automaker integrates with your authenticated Claude Code CLI. To use CLI authentication in Docker, mount your Claude CLI config directory (see [Claude CLI Authentication](#claude-cli-authentication) below).
262
+
263
+ ##### Working with Projects (Host Directory Access)
264
+
265
+ By default, the container is isolated from your host filesystem. To work on projects from your host machine, create a `docker-compose.override.yml` file (gitignored):
266
+
267
+ ```yaml
268
+ services:
269
+ server:
270
+ volumes:
271
+ # Mount your project directories
272
+ - /path/to/your/project:/projects/your-project
273
+ ```
274
+
275
+ ##### Claude CLI Authentication
276
+
277
+ Mount your Claude CLI config directory to use your authenticated CLI credentials:
278
+
279
+ ```yaml
280
+ services:
281
+ server:
282
+ volumes:
283
+ # Linux/macOS
284
+ - ~/.claude:/home/automaker/.claude
285
+ # Windows
286
+ - C:/Users/YourName/.claude:/home/automaker/.claude
287
+ ```
288
+
289
+ **Note:** The Claude CLI config must be writable (do not use `:ro` flag) as the CLI writes debug files.
290
+
291
+ > **⚠️ Important: Linux/WSL Users**
292
+ >
293
+ > The container runs as UID 1001 by default. If your host user has a different UID (common on Linux/WSL where the first user is UID 1000), you must create a `.env` file to match your host user:
294
+ >
295
+ > ```bash
296
+ > # Check your UID/GID
297
+ > id -u # outputs your UID (e.g., 1000)
298
+ > id -g # outputs your GID (e.g., 1000)
299
+ > ```
300
+ >
301
+ > Create a `.env` file in the automaker directory:
302
+ >
303
+ > ```
304
+ > UID=1000
305
+ > GID=1000
306
+ > ```
307
+ >
308
+ > Then rebuild the images:
309
+ >
310
+ > ```bash
311
+ > docker compose build
312
+ > ```
313
+ >
314
+ > Without this, files written by the container will be inaccessible to your host user.
315
+
316
+ ##### GitHub CLI Authentication (For Git Push/PR Operations)
317
+
318
+ To enable git push and GitHub CLI operations inside the container:
319
+
320
+ ```yaml
321
+ services:
322
+ server:
323
+ volumes:
324
+ # Mount GitHub CLI config
325
+ # Linux/macOS
326
+ - ~/.config/gh:/home/automaker/.config/gh
327
+ # Windows
328
+ - 'C:/Users/YourName/AppData/Roaming/GitHub CLI:/home/automaker/.config/gh'
329
+
330
+ # Mount git config for user identity (name, email)
331
+ - ~/.gitconfig:/home/automaker/.gitconfig:ro
332
+ environment:
333
+ # GitHub token (required on Windows where tokens are in Credential Manager)
334
+ # Get your token with: gh auth token
335
+ - GH_TOKEN=${GH_TOKEN}
336
+ ```
337
+
338
+ Then add `GH_TOKEN` to your `.env` file:
339
+
340
+ ```bash
341
+ GH_TOKEN=gho_your_github_token_here
342
+ ```
343
+
344
+ ##### Complete docker-compose.override.yml Example
345
+
346
+ ```yaml
347
+ services:
348
+ server:
349
+ volumes:
350
+ # Your projects
351
+ - /path/to/project1:/projects/project1
352
+ - /path/to/project2:/projects/project2
353
+
354
+ # Authentication configs
355
+ - ~/.claude:/home/automaker/.claude
356
+ - ~/.config/gh:/home/automaker/.config/gh
357
+ - ~/.gitconfig:/home/automaker/.gitconfig:ro
358
+ environment:
359
+ - GH_TOKEN=${GH_TOKEN}
360
+ ```
361
+
362
+ ##### Architecture Support
363
+
364
+ The Docker image supports both AMD64 and ARM64 architectures. The GitHub CLI and Claude CLI are automatically downloaded for the correct architecture during build.
365
+
366
+ ##### Playwright for Automated Testing
367
+
368
+ The Docker image includes **Playwright Chromium pre-installed** for AI agent verification tests. When agents implement features in automated testing mode, they use Playwright to verify the implementation works correctly.
369
+
370
+ **No additional setup required** - Playwright verification works out of the box.
371
+
372
+ #### Optional: Persist browsers for manual updates
373
+
374
+ By default, Playwright Chromium is pre-installed in the Docker image. If you need to manually update browsers or want to persist browser installations across container restarts (not image rebuilds), you can mount a volume.
375
+
376
+ **Important:** When you first add this volume mount to an existing setup, the empty volume will override the pre-installed browsers. You must re-install them:
377
+
378
+ ```bash
379
+ # After adding the volume mount for the first time
380
+ docker exec --user automaker -w /app automaker-server npx playwright install chromium
381
+ ```
382
+
383
+ Add this to your `docker-compose.override.yml`:
384
+
385
+ ```yaml
386
+ services:
387
+ server:
388
+ volumes:
389
+ - playwright-cache:/home/automaker/.cache/ms-playwright
390
+
391
+ volumes:
392
+ playwright-cache:
393
+ name: automaker-playwright-cache
394
+ ```
395
+
396
+ **Updating browsers manually:**
397
+
398
+ ```bash
399
+ docker exec --user automaker -w /app automaker-server npx playwright install chromium
400
+ ```
401
+
402
+ ### Testing
403
+
404
+ #### End-to-End Tests (Playwright)
405
+
406
+ ```bash
407
+ npm run test # Headless E2E tests
408
+ npm run test:headed # Browser visible E2E tests
409
+ ```
410
+
411
+ #### Unit Tests (Vitest)
412
+
413
+ ```bash
414
+ npm run test:server # Server unit tests
415
+ npm run test:server:coverage # Server tests with coverage
416
+ npm run test:packages # All shared package tests
417
+ npm run test:all # Packages + server tests
418
+ ```
419
+
420
+ #### Test Configuration
421
+
422
+ - E2E tests run on ports 3007 (UI) and 3008 (server)
423
+ - Automatically starts test servers before running
424
+ - Uses Chromium browser via Playwright
425
+ - Mock agent mode available in CI with `AUTOMAKER_MOCK_AGENT=true`
426
+
427
+ ### Linting
428
+
429
+ ```bash
430
+ # Run ESLint
431
+ npm run lint
432
+ ```
433
+
434
+ ### Environment Configuration
435
+
436
+ #### Optional - Server
437
+
438
+ - `PORT` - Server port (default: 3008)
439
+ - `DATA_DIR` - Data storage directory (default: ./data)
440
+ - `ENABLE_REQUEST_LOGGING` - HTTP request logging (default: true)
441
+
442
+ #### Optional - Security
443
+
444
+ - `AUTOMAKER_API_KEY` - Optional API authentication for the server
445
+ - `ALLOWED_ROOT_DIRECTORY` - Restrict file operations to specific directory
446
+ - `CORS_ORIGIN` - CORS allowed origins (comma-separated list; defaults to localhost only)
447
+
448
+ #### Optional - Development
449
+
450
+ - `VITE_SKIP_ELECTRON` - Skip Electron in dev mode
451
+ - `OPEN_DEVTOOLS` - Auto-open DevTools in Electron
452
+ - `AUTOMAKER_SKIP_SANDBOX_WARNING` - Skip sandbox warning dialog (useful for dev/CI)
453
+ - `AUTOMAKER_AUTO_LOGIN=true` - Skip login prompt in development (ignored when NODE_ENV=production)
454
+
455
+ ### Authentication Setup
456
+
457
+ Automaker integrates with your authenticated Claude Code CLI and uses your Anthropic subscription.
458
+
459
+ Install and authenticate the Claude Code CLI following the [official quickstart guide](https://code.claude.com/docs/en/quickstart).
460
+
461
+ Once authenticated, Automaker will automatically detect and use your CLI credentials. No additional configuration needed!
462
+
463
+ ## Features
464
+
465
+ ### Core Workflow
466
+
467
+ - 📋 **Kanban Board** - Visual drag-and-drop board to manage features through backlog, in progress, waiting approval, and verified stages
468
+ - 🤖 **AI Agent Integration** - Automatic AI agent assignment to implement features when moved to "In Progress"
469
+ - 🔀 **Git Worktree Isolation** - Each feature executes in isolated git worktrees to protect your main branch
470
+ - 📡 **Real-time Streaming** - Watch AI agents work in real-time with live tool usage, progress updates, and task completion
471
+ - 🔄 **Follow-up Instructions** - Send additional instructions to running agents without stopping them
472
+
473
+ ### AI & Planning
474
+
475
+ - 🧠 **Multi-Model Support** - Choose from Claude Opus, Sonnet, and Haiku per feature
476
+ - 💭 **Extended Thinking** - Enable thinking modes (none, medium, deep, ultra) for complex problem-solving
477
+ - 📝 **Planning Modes** - Four planning levels: skip (direct implementation), lite (quick plan), spec (task breakdown), full (phased execution)
478
+ - ✅ **Plan Approval** - Review and approve AI-generated plans before implementation begins
479
+ - 📊 **Multi-Agent Task Execution** - Spec mode spawns dedicated agents per task for focused implementation
480
+
481
+ ### Project Management
482
+
483
+ - 🔍 **Project Analysis** - AI-powered codebase analysis to understand your project structure
484
+ - 💡 **Feature Suggestions** - AI-generated feature suggestions based on project analysis
485
+ - 📁 **Context Management** - Add markdown, images, and documentation files that agents automatically reference
486
+ - 🔗 **Dependency Blocking** - Features can depend on other features, enforcing execution order
487
+ - 🌳 **Graph View** - Visualize feature dependencies with interactive graph visualization
488
+ - 📋 **GitHub Integration** - Import issues, validate feasibility, and convert to tasks automatically
489
+
490
+ ### Collaboration & Review
491
+
492
+ - 🧪 **Verification Workflow** - Features move to "Waiting Approval" for review and testing
493
+ - 💬 **Agent Chat** - Interactive chat sessions with AI agents for exploratory work
494
+ - 👤 **AI Profiles** - Create custom agent configurations with different prompts, models, and settings
495
+ - 📜 **Session History** - Persistent chat sessions across restarts with full conversation history
496
+ - 🔍 **Git Diff Viewer** - Review changes made by agents before approving
497
+
498
+ ### Developer Tools
499
+
500
+ - 🖥️ **Integrated Terminal** - Full terminal access with tabs, splits, and persistent sessions
501
+ - 🖼️ **Image Support** - Attach screenshots and diagrams to feature descriptions for visual context
502
+ - ⚡ **Concurrent Execution** - Configure how many features can run simultaneously (default: 3)
503
+ - ⌨️ **Keyboard Shortcuts** - Fully customizable shortcuts for navigation and actions
504
+ - 🎨 **Theme System** - 25+ themes including Dark, Light, Dracula, Nord, Catppuccin, and more
505
+ - 🖥️ **Cross-Platform** - Desktop app for macOS (x64, arm64), Windows (x64), and Linux (x64)
506
+ - 🌐 **Web Mode** - Run in browser or as Electron desktop app
507
+
508
+ ### Advanced Features
509
+
510
+ - 🔐 **Docker Isolation** - Security-focused Docker deployment with no host filesystem access
511
+ - 🎯 **Worktree Management** - Create, switch, commit, and create PRs from worktrees
512
+ - 📊 **Usage Tracking** - Monitor Claude API usage with detailed metrics
513
+ - 🔊 **Audio Notifications** - Optional completion sounds (mutable in settings)
514
+ - 💾 **Auto-save** - All work automatically persisted to `.automaker/` directory
515
+
516
+ ## Tech Stack
517
+
518
+ ### Frontend
519
+
520
+ - **React 19** - UI framework
521
+ - **Vite 7** - Build tool and development server
522
+ - **Electron 39** - Desktop application framework
523
+ - **TypeScript 5.9** - Type safety
524
+ - **TanStack Router** - File-based routing
525
+ - **Zustand 5** - State management with persistence
526
+ - **Tailwind CSS 4** - Utility-first styling with 25+ themes
527
+ - **Radix UI** - Accessible component primitives
528
+ - **dnd-kit** - Drag and drop for Kanban board
529
+ - **@xyflow/react** - Graph visualization for dependencies
530
+ - **xterm.js** - Integrated terminal emulator
531
+ - **CodeMirror 6** - Code editor for XML/syntax highlighting
532
+ - **Lucide Icons** - Icon library
533
+
534
+ ### Backend
535
+
536
+ - **Node.js** - JavaScript runtime with ES modules
537
+ - **Express 5** - HTTP server framework
538
+ - **TypeScript 5.9** - Type safety
539
+ - **Claude Agent SDK** - AI agent integration (@anthropic-ai/claude-agent-sdk)
540
+ - **WebSocket (ws)** - Real-time event streaming
541
+ - **node-pty** - PTY terminal sessions
542
+
543
+ ### Testing & Quality
544
+
545
+ - **Playwright** - End-to-end testing
546
+ - **Vitest** - Unit testing framework
547
+ - **ESLint 9** - Code linting
548
+ - **Prettier 3** - Code formatting
549
+ - **Husky** - Git hooks for pre-commit formatting
550
+
551
+ ### Shared Libraries
552
+
553
+ - **@automaker/types** - Shared TypeScript definitions
554
+ - **@automaker/utils** - Logging, error handling, image processing
555
+ - **@automaker/prompts** - AI prompt templates
556
+ - **@automaker/platform** - Path management and security
557
+ - **@automaker/model-resolver** - Claude model alias resolution
558
+ - **@automaker/dependency-resolver** - Feature dependency ordering
559
+ - **@automaker/git-utils** - Git operations and worktree management
560
+
561
+ ## Available Views
562
+
563
+ Automaker provides several specialized views accessible via the sidebar or keyboard shortcuts:
564
+
565
+ | View | Shortcut | Description |
566
+ | ------------------ | -------- | ------------------------------------------------------------------------------------------------ |
567
+ | **Board** | `K` | Kanban board for managing feature workflow (Backlog → In Progress → Waiting Approval → Verified) |
568
+ | **Agent** | `A` | Interactive chat sessions with AI agents for exploratory work and questions |
569
+ | **Spec** | `D` | Project specification editor with AI-powered generation and feature suggestions |
570
+ | **Context** | `C` | Manage context files (markdown, images) that AI agents automatically reference |
571
+ | **Settings** | `S` | Configure themes, shortcuts, defaults, authentication, and more |
572
+ | **Terminal** | `T` | Integrated terminal with tabs, splits, and persistent sessions |
573
+ | **Graph** | `H` | Visualize feature dependencies with interactive graph visualization |
574
+ | **Ideation** | `I` | Brainstorm and generate ideas with AI assistance |
575
+ | **Memory** | `Y` | View and manage agent memory and conversation history |
576
+ | **GitHub Issues** | `G` | Import and validate GitHub issues, convert to tasks |
577
+ | **GitHub PRs** | `R` | View and manage GitHub pull requests |
578
+ | **Running Agents** | - | View all active agents across projects with status and progress |
579
+
580
+ ### Keyboard Navigation
581
+
582
+ All shortcuts are customizable in Settings. Default shortcuts:
583
+
584
+ - **Navigation:** `K` (Board), `A` (Agent), `D` (Spec), `C` (Context), `S` (Settings), `T` (Terminal), `H` (Graph), `I` (Ideation), `Y` (Memory), `G` (GitHub Issues), `R` (GitHub PRs)
585
+ - **UI:** `` ` `` (Toggle sidebar)
586
+ - **Actions:** `N` (New item in current view), `O` (Open project), `P` (Project picker)
587
+ - **Projects:** `Q`/`E` (Cycle previous/next project)
588
+ - **Terminal:** `Alt+D` (Split right), `Alt+S` (Split down), `Alt+W` (Close), `Alt+T` (New tab)
589
+
590
+ ## Architecture
591
+
592
+ ### Monorepo Structure
593
+
594
+ Automaker is built as an npm workspace monorepo with two main applications and seven shared packages:
595
+
596
+ ```text
597
+ automaker/
598
+ ├── apps/
599
+ │ ├── ui/ # React + Vite + Electron frontend
600
+ │ └── server/ # Express + WebSocket backend
601
+ └── libs/ # Shared packages
602
+ ├── types/ # Core TypeScript definitions
603
+ ├── utils/ # Logging, errors, utilities
604
+ ├── prompts/ # AI prompt templates
605
+ ├── platform/ # Path management, security
606
+ ├── model-resolver/ # Claude model aliasing
607
+ ├── dependency-resolver/ # Feature dependency ordering
608
+ └── git-utils/ # Git operations & worktree management
609
+ ```
610
+
611
+ ### How It Works
612
+
613
+ 1. **Feature Definition** - Users create feature cards on the Kanban board with descriptions, images, and configuration
614
+ 2. **Git Worktree Creation** - When a feature starts, a git worktree is created for isolated development
615
+ 3. **Agent Execution** - Claude Agent SDK executes in the worktree with full file system and command access
616
+ 4. **Real-time Streaming** - Agent output streams via WebSocket to the frontend for live monitoring
617
+ 5. **Plan Approval** (optional) - For spec/full planning modes, agents generate plans that require user approval
618
+ 6. **Multi-Agent Tasks** (spec mode) - Each task in the spec gets a dedicated agent for focused implementation
619
+ 7. **Verification** - Features move to "Waiting Approval" where changes can be reviewed via git diff
620
+ 8. **Integration** - After approval, changes can be committed and PRs created from the worktree
621
+
622
+ ### Key Architectural Patterns
623
+
624
+ - **Event-Driven Architecture** - All server operations emit events that stream to the frontend
625
+ - **Provider Pattern** - Extensible AI provider system (currently Claude, designed for future providers)
626
+ - **Service-Oriented Backend** - Modular services for agent management, features, terminals, settings
627
+ - **State Management** - Zustand with persistence for frontend state across restarts
628
+ - **File-Based Storage** - No database; features stored as JSON files in `.automaker/` directory
629
+
630
+ ### Security & Isolation
631
+
632
+ - **Git Worktrees** - Each feature executes in an isolated git worktree, protecting your main branch
633
+ - **Path Sandboxing** - Optional `ALLOWED_ROOT_DIRECTORY` restricts file access
634
+ - **Docker Isolation** - Recommended deployment uses Docker with no host filesystem access
635
+ - **Plan Approval** - Optional plan review before implementation prevents unwanted changes
636
+
637
+ ### Data Storage
638
+
639
+ Automaker uses a file-based storage system (no database required):
640
+
641
+ #### Per-Project Data
642
+
643
+ Stored in `{projectPath}/.automaker/`:
644
+
645
+ ```text
646
+ .automaker/
647
+ ├── features/ # Feature JSON files and images
648
+ │ └── {featureId}/
649
+ │ ├── feature.json # Feature metadata
650
+ │ ├── agent-output.md # AI agent output log
651
+ │ └── images/ # Attached images
652
+ ├── context/ # Context files for AI agents
653
+ ├── worktrees/ # Git worktree metadata
654
+ ├── validations/ # GitHub issue validation results
655
+ ├── ideation/ # Brainstorming and analysis data
656
+ │ └── analysis.json # Project structure analysis
657
+ ├── board/ # Board-related data
658
+ ├── images/ # Project-level images
659
+ ├── settings.json # Project-specific settings
660
+ ├── app_spec.txt # Project specification (XML format)
661
+ ├── active-branches.json # Active git branches tracking
662
+ └── execution-state.json # Auto-mode execution state
663
+ ```
664
+
665
+ #### Global Data
666
+
667
+ Stored in `DATA_DIR` (default `./data`):
668
+
669
+ ```text
670
+ data/
671
+ ├── settings.json # Global settings, profiles, shortcuts
672
+ ├── credentials.json # API keys (encrypted)
673
+ ├── sessions-metadata.json # Chat session metadata
674
+ └── agent-sessions/ # Conversation histories
675
+ └── {sessionId}.json
676
+ ```
677
+
678
+ ---
679
+
680
+ > **[!CAUTION]**
681
+ >
682
+ > ## Security Disclaimer
683
+ >
684
+ > **This software uses AI-powered tooling that has access to your operating system and can read, modify, and delete files. Use at your own risk.**
685
+ >
686
+ > We have reviewed this codebase for security vulnerabilities, but you assume all risk when running this software. You should review the code yourself before running it.
687
+ >
688
+ > **We do not recommend running Automaker directly on your local computer** due to the risk of AI agents having access to your entire file system. Please sandbox this application using Docker or a virtual machine.
689
+ >
690
+ > **[Read the full disclaimer](./DISCLAIMER.md)**
691
+
692
+ ---
693
+
694
+ ## Learn More
695
+
696
+ ### Documentation
697
+
698
+ - [Contributing Guide](./CONTRIBUTING.md) - How to contribute to Automaker
699
+ - [Project Documentation](./docs/) - Architecture guides, patterns, and developer docs
700
+ - [Shared Packages Guide](./docs/llm-shared-packages.md) - Using monorepo packages
701
+
702
+ ### Community
703
+
704
+ Join the **Agentic Jumpstart** Discord to connect with other builders exploring **agentic coding**:
705
+
706
+ 👉 [Agentic Jumpstart Discord](https://discord.gg/jjem7aEDKU)
707
+
708
+ ## Project Status
709
+
710
+ **This project is no longer actively maintained.** The codebase is provided as-is for those who wish to use, study, or fork it. No bug fixes, security updates, or new features are being developed. Community contributions may still be accepted, but there is no guarantee of review or merge.
711
+
712
+ ## License
713
+
714
+ This project is licensed under the **MIT License**. See [LICENSE](LICENSE) for the full text.
jules_branch/apps/server/.env.example ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Automaker Server Configuration
2
+ # Copy this file to .env and configure your settings
3
+
4
+ # ============================================
5
+ # REQUIRED
6
+ # ============================================
7
+
8
+ # Your Anthropic API key for Claude models
9
+ ANTHROPIC_API_KEY=sk-ant-...
10
+
11
+ # ============================================
12
+ # OPTIONAL - Additional API Keys
13
+ # ============================================
14
+
15
+ # OpenAI API key for Codex/GPT models
16
+ OPENAI_API_KEY=sk-...
17
+
18
+ # Cursor API key for Cursor models
19
+ CURSOR_API_KEY=...
20
+
21
+ # OAuth credentials for CLI authentication (extracted automatically)
22
+ CLAUDE_OAUTH_CREDENTIALS=
23
+ CURSOR_AUTH_TOKEN=
24
+
25
+ # ============================================
26
+ # OPTIONAL - Security
27
+ # ============================================
28
+
29
+ # API key for authenticating requests (leave empty to disable auth)
30
+ # If set, all API requests must include X-API-Key header
31
+ AUTOMAKER_API_KEY=
32
+
33
+ # Root directory for projects and file operations
34
+ # If set, users can only create/open projects and files within this directory
35
+ # Recommended for sandboxed deployments (Docker, restricted environments)
36
+ # Example: ALLOWED_ROOT_DIRECTORY=/projects
37
+ ALLOWED_ROOT_DIRECTORY=
38
+
39
+ # CORS origin - which domains can access the API
40
+ # Use "*" for development, set specific origin for production
41
+ CORS_ORIGIN=http://localhost:3007
42
+
43
+ # ============================================
44
+ # OPTIONAL - Server
45
+ # ============================================
46
+
47
+ # Host to bind the server to (default: 0.0.0.0)
48
+ # Use 0.0.0.0 to listen on all interfaces (recommended for Docker/remote access)
49
+ # Use 127.0.0.1 or localhost to restrict to local connections only
50
+ HOST=0.0.0.0
51
+
52
+ # Port to run the server on
53
+ PORT=3008
54
+
55
+ # Port to run the server on for testing
56
+ TEST_SERVER_PORT=3108
57
+
58
+ # Port to run the UI on for testing
59
+ TEST_PORT=3107
60
+
61
+ # Data directory for sessions and metadata
62
+ DATA_DIR=./data
63
+
64
+ # ============================================
65
+ # OPTIONAL - Terminal Access
66
+ # ============================================
67
+
68
+ # Enable/disable terminal access (default: true)
69
+ TERMINAL_ENABLED=true
70
+
71
+ # Password to protect terminal access (leave empty for no password)
72
+ # If set, users must enter this password before accessing terminal
73
+ TERMINAL_PASSWORD=
74
+
75
+ ENABLE_REQUEST_LOGGING=false
76
+
77
+ # ============================================
78
+ # OPTIONAL - UI Behavior
79
+ # ============================================
80
+
81
+ # Skip the sandbox warning dialog on startup (default: false)
82
+ # Set to "true" to disable the warning entirely (useful for dev/CI environments)
83
+ AUTOMAKER_SKIP_SANDBOX_WARNING=false
84
+
85
+ # ============================================
86
+ # OPTIONAL - Debugging
87
+ # ============================================
88
+
89
+ # Enable raw output logging for agent streams (default: false)
90
+ # When enabled, saves unprocessed stream events to raw-output.jsonl
91
+ # in each feature's directory (.automaker/features/{id}/raw-output.jsonl)
92
+ # Useful for debugging provider streaming issues, improving log parsing,
93
+ # or analyzing how different providers (Claude, Cursor) stream responses
94
+ # Note: This adds disk I/O overhead, only enable when debugging
95
+ AUTOMAKER_DEBUG_RAW_OUTPUT=false
jules_branch/apps/server/.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ .env
2
+ data
3
+ node_modules
4
+ coverage
jules_branch/apps/server/eslint.config.mjs ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig, globalIgnores } from 'eslint/config';
2
+ import js from '@eslint/js';
3
+ import ts from '@typescript-eslint/eslint-plugin';
4
+ import tsParser from '@typescript-eslint/parser';
5
+
6
+ const eslintConfig = defineConfig([
7
+ js.configs.recommended,
8
+ {
9
+ files: ['**/*.ts'],
10
+ languageOptions: {
11
+ parser: tsParser,
12
+ parserOptions: {
13
+ ecmaVersion: 'latest',
14
+ sourceType: 'module',
15
+ },
16
+ globals: {
17
+ // Node.js globals
18
+ console: 'readonly',
19
+ process: 'readonly',
20
+ Buffer: 'readonly',
21
+ __dirname: 'readonly',
22
+ __filename: 'readonly',
23
+ URL: 'readonly',
24
+ URLSearchParams: 'readonly',
25
+ AbortController: 'readonly',
26
+ AbortSignal: 'readonly',
27
+ fetch: 'readonly',
28
+ Response: 'readonly',
29
+ Request: 'readonly',
30
+ Headers: 'readonly',
31
+ FormData: 'readonly',
32
+ RequestInit: 'readonly',
33
+ // Timers
34
+ setTimeout: 'readonly',
35
+ setInterval: 'readonly',
36
+ clearTimeout: 'readonly',
37
+ clearInterval: 'readonly',
38
+ setImmediate: 'readonly',
39
+ clearImmediate: 'readonly',
40
+ queueMicrotask: 'readonly',
41
+ // Node.js types
42
+ NodeJS: 'readonly',
43
+ },
44
+ },
45
+ plugins: {
46
+ '@typescript-eslint': ts,
47
+ },
48
+ rules: {
49
+ ...ts.configs.recommended.rules,
50
+ '@typescript-eslint/no-unused-vars': [
51
+ 'warn',
52
+ {
53
+ argsIgnorePattern: '^_',
54
+ varsIgnorePattern: '^_',
55
+ caughtErrorsIgnorePattern: '^_',
56
+ ignoreRestSiblings: true,
57
+ },
58
+ ],
59
+ '@typescript-eslint/no-explicit-any': 'warn',
60
+ // Server code frequently works with terminal output containing ANSI escape codes
61
+ 'no-control-regex': 'off',
62
+ '@typescript-eslint/ban-ts-comment': [
63
+ 'error',
64
+ {
65
+ 'ts-nocheck': 'allow-with-description',
66
+ minimumDescriptionLength: 10,
67
+ },
68
+ ],
69
+ },
70
+ },
71
+ globalIgnores(['dist/**', 'node_modules/**']),
72
+ ]);
73
+
74
+ export default eslintConfig;
jules_branch/apps/server/package.json ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "@automaker/server",
3
+ "version": "1.0.0",
4
+ "description": "Backend server for Automaker - provides API for both web and Electron modes",
5
+ "author": "AutoMaker Team",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "private": true,
8
+ "engines": {
9
+ "node": ">=22.0.0 <23.0.0"
10
+ },
11
+ "type": "module",
12
+ "main": "dist/index.js",
13
+ "scripts": {
14
+ "dev": "tsx watch src/index.ts",
15
+ "dev:test": "tsx src/index.ts",
16
+ "build": "tsc",
17
+ "start": "node dist/index.js",
18
+ "lint": "eslint src/",
19
+ "test": "vitest",
20
+ "test:ui": "vitest --ui",
21
+ "test:run": "vitest run",
22
+ "test:cov": "vitest run --coverage",
23
+ "test:watch": "vitest watch",
24
+ "test:unit": "vitest run tests/unit"
25
+ },
26
+ "dependencies": {
27
+ "@anthropic-ai/claude-agent-sdk": "0.2.32",
28
+ "@automaker/dependency-resolver": "1.0.0",
29
+ "@automaker/git-utils": "1.0.0",
30
+ "@automaker/model-resolver": "1.0.0",
31
+ "@automaker/platform": "1.0.0",
32
+ "@automaker/prompts": "1.0.0",
33
+ "@automaker/types": "1.0.0",
34
+ "@automaker/utils": "1.0.0",
35
+ "@github/copilot-sdk": "0.1.16",
36
+ "@modelcontextprotocol/sdk": "1.25.2",
37
+ "@openai/codex-sdk": "^0.98.0",
38
+ "cookie-parser": "1.4.7",
39
+ "cors": "2.8.5",
40
+ "dotenv": "17.2.3",
41
+ "express": "5.2.1",
42
+ "morgan": "1.10.1",
43
+ "node-pty": "1.1.0-beta41",
44
+ "ws": "8.18.3",
45
+ "yaml": "2.7.0"
46
+ },
47
+ "devDependencies": {
48
+ "@playwright/test": "1.57.0",
49
+ "@types/cookie": "0.6.0",
50
+ "@types/cookie-parser": "1.4.10",
51
+ "@types/cors": "2.8.19",
52
+ "@types/express": "5.0.6",
53
+ "@types/morgan": "1.9.10",
54
+ "@types/node": "22.19.3",
55
+ "@types/ws": "8.18.1",
56
+ "@vitest/coverage-v8": "4.0.16",
57
+ "@vitest/ui": "4.0.16",
58
+ "tsx": "4.21.0",
59
+ "typescript": "5.9.3",
60
+ "vitest": "4.0.16"
61
+ }
62
+ }
jules_branch/apps/server/src/index.ts ADDED
@@ -0,0 +1,979 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Automaker Backend Server
3
+ *
4
+ * Provides HTTP/WebSocket API for both web and Electron modes.
5
+ * In Electron mode, this server runs locally.
6
+ * In web mode, this server runs on a remote host.
7
+ */
8
+
9
+ import express from 'express';
10
+ import cors from 'cors';
11
+ import morgan from 'morgan';
12
+ import cookieParser from 'cookie-parser';
13
+ import cookie from 'cookie';
14
+ import { WebSocketServer, WebSocket } from 'ws';
15
+ import { createServer } from 'http';
16
+ import dotenv from 'dotenv';
17
+
18
+ import { createEventEmitter, type EventEmitter } from './lib/events.js';
19
+ import { initAllowedPaths, getClaudeAuthIndicators } from '@automaker/platform';
20
+ import { createLogger, setLogLevel, LogLevel } from '@automaker/utils';
21
+
22
+ const logger = createLogger('Server');
23
+
24
+ /**
25
+ * Map server log level string to LogLevel enum
26
+ */
27
+ const LOG_LEVEL_MAP: Record<string, LogLevel> = {
28
+ error: LogLevel.ERROR,
29
+ warn: LogLevel.WARN,
30
+ info: LogLevel.INFO,
31
+ debug: LogLevel.DEBUG,
32
+ };
33
+ import { authMiddleware, validateWsConnectionToken, checkRawAuthentication } from './lib/auth.js';
34
+ import { requireJsonContentType } from './middleware/require-json-content-type.js';
35
+ import { createAuthRoutes } from './routes/auth/index.js';
36
+ import { createFsRoutes } from './routes/fs/index.js';
37
+ import { createHealthRoutes, createDetailedHandler } from './routes/health/index.js';
38
+ import { createAgentRoutes } from './routes/agent/index.js';
39
+ import { createSessionsRoutes } from './routes/sessions/index.js';
40
+ import { createFeaturesRoutes } from './routes/features/index.js';
41
+ import { createAutoModeRoutes } from './routes/auto-mode/index.js';
42
+ import { createEnhancePromptRoutes } from './routes/enhance-prompt/index.js';
43
+ import { createWorktreeRoutes } from './routes/worktree/index.js';
44
+ import { createGitRoutes } from './routes/git/index.js';
45
+ import { createSetupRoutes } from './routes/setup/index.js';
46
+ import { createModelsRoutes } from './routes/models/index.js';
47
+ import { createRunningAgentsRoutes } from './routes/running-agents/index.js';
48
+ import { createWorkspaceRoutes } from './routes/workspace/index.js';
49
+ import { createTemplatesRoutes } from './routes/templates/index.js';
50
+ import {
51
+ createTerminalRoutes,
52
+ validateTerminalToken,
53
+ isTerminalEnabled,
54
+ isTerminalPasswordRequired,
55
+ } from './routes/terminal/index.js';
56
+ import { createSettingsRoutes } from './routes/settings/index.js';
57
+ import { AgentService } from './services/agent-service.js';
58
+ import { FeatureLoader } from './services/feature-loader.js';
59
+ import { AutoModeServiceCompat } from './services/auto-mode/index.js';
60
+ import { getTerminalService } from './services/terminal-service.js';
61
+ import { SettingsService } from './services/settings-service.js';
62
+ import { createSpecRegenerationRoutes } from './routes/app-spec/index.js';
63
+ import { createClaudeRoutes } from './routes/claude/index.js';
64
+ import { ClaudeUsageService } from './services/claude-usage-service.js';
65
+ import { createCodexRoutes } from './routes/codex/index.js';
66
+ import { CodexUsageService } from './services/codex-usage-service.js';
67
+ import { CodexAppServerService } from './services/codex-app-server-service.js';
68
+ import { CodexModelCacheService } from './services/codex-model-cache-service.js';
69
+ import { createZaiRoutes } from './routes/zai/index.js';
70
+ import { ZaiUsageService } from './services/zai-usage-service.js';
71
+ import { createGeminiRoutes } from './routes/gemini/index.js';
72
+ import { GeminiUsageService } from './services/gemini-usage-service.js';
73
+ import { createGitHubRoutes } from './routes/github/index.js';
74
+ import { createContextRoutes } from './routes/context/index.js';
75
+ import { createBacklogPlanRoutes } from './routes/backlog-plan/index.js';
76
+ import { cleanupStaleValidations } from './routes/github/routes/validation-common.js';
77
+ import { createMCPRoutes } from './routes/mcp/index.js';
78
+ import { MCPTestService } from './services/mcp-test-service.js';
79
+ import { createPipelineRoutes } from './routes/pipeline/index.js';
80
+ import { pipelineService } from './services/pipeline-service.js';
81
+ import { createIdeationRoutes } from './routes/ideation/index.js';
82
+ import { IdeationService } from './services/ideation-service.js';
83
+ import { getDevServerService } from './services/dev-server-service.js';
84
+ import { eventHookService } from './services/event-hook-service.js';
85
+ import { createNotificationsRoutes } from './routes/notifications/index.js';
86
+ import { getNotificationService } from './services/notification-service.js';
87
+ import { createEventHistoryRoutes } from './routes/event-history/index.js';
88
+ import { getEventHistoryService } from './services/event-history-service.js';
89
+ import { getTestRunnerService } from './services/test-runner-service.js';
90
+ import { createProjectsRoutes } from './routes/projects/index.js';
91
+
92
+ // Load environment variables
93
+ dotenv.config();
94
+
95
+ const PORT = parseInt(process.env.PORT || '3008', 10);
96
+ const HOST = process.env.HOST || '0.0.0.0';
97
+ const HOSTNAME = process.env.HOSTNAME || 'localhost';
98
+ const DATA_DIR = process.env.DATA_DIR || './data';
99
+ logger.info('[SERVER_STARTUP] process.env.DATA_DIR:', process.env.DATA_DIR);
100
+ logger.info('[SERVER_STARTUP] Resolved DATA_DIR:', DATA_DIR);
101
+ logger.info('[SERVER_STARTUP] process.cwd():', process.cwd());
102
+ const ENABLE_REQUEST_LOGGING_DEFAULT = process.env.ENABLE_REQUEST_LOGGING !== 'false'; // Default to true
103
+
104
+ // Runtime-configurable request logging flag (can be changed via settings)
105
+ let requestLoggingEnabled = ENABLE_REQUEST_LOGGING_DEFAULT;
106
+
107
+ /**
108
+ * Enable or disable HTTP request logging at runtime
109
+ */
110
+ export function setRequestLoggingEnabled(enabled: boolean): void {
111
+ requestLoggingEnabled = enabled;
112
+ }
113
+
114
+ /**
115
+ * Get current request logging state
116
+ */
117
+ export function isRequestLoggingEnabled(): boolean {
118
+ return requestLoggingEnabled;
119
+ }
120
+
121
+ // Width for log box content (excluding borders)
122
+ const BOX_CONTENT_WIDTH = 67;
123
+
124
+ // Check for Claude authentication (async - runs in background)
125
+ // The Claude Agent SDK can use either ANTHROPIC_API_KEY or Claude Code CLI authentication
126
+ (async () => {
127
+ const hasAnthropicKey = !!process.env.ANTHROPIC_API_KEY;
128
+ const hasEnvOAuthToken = !!process.env.CLAUDE_CODE_OAUTH_TOKEN;
129
+
130
+ logger.debug('[CREDENTIAL_CHECK] Starting credential detection...');
131
+ logger.debug('[CREDENTIAL_CHECK] Environment variables:', {
132
+ hasAnthropicKey,
133
+ hasEnvOAuthToken,
134
+ });
135
+
136
+ if (hasAnthropicKey) {
137
+ logger.info('✓ ANTHROPIC_API_KEY detected');
138
+ return;
139
+ }
140
+
141
+ if (hasEnvOAuthToken) {
142
+ logger.info('✓ CLAUDE_CODE_OAUTH_TOKEN detected');
143
+ return;
144
+ }
145
+
146
+ // Check for Claude Code CLI authentication
147
+ // Store indicators outside the try block so we can use them in the warning message
148
+ let cliAuthIndicators: Awaited<ReturnType<typeof getClaudeAuthIndicators>> | null = null;
149
+
150
+ try {
151
+ cliAuthIndicators = await getClaudeAuthIndicators();
152
+ const indicators = cliAuthIndicators;
153
+
154
+ // Log detailed credential detection results
155
+ const { checks, ...indicatorSummary } = indicators;
156
+ logger.debug('[CREDENTIAL_CHECK] Claude CLI auth indicators:', indicatorSummary);
157
+
158
+ logger.debug('[CREDENTIAL_CHECK] File check details:', checks);
159
+
160
+ const hasCliAuth =
161
+ indicators.hasStatsCacheWithActivity ||
162
+ (indicators.hasSettingsFile && indicators.hasProjectsSessions) ||
163
+ (indicators.hasCredentialsFile &&
164
+ (indicators.credentials?.hasOAuthToken || indicators.credentials?.hasApiKey));
165
+
166
+ logger.debug('[CREDENTIAL_CHECK] Auth determination:', {
167
+ hasCliAuth,
168
+ reason: hasCliAuth
169
+ ? indicators.hasStatsCacheWithActivity
170
+ ? 'stats cache with activity'
171
+ : indicators.hasSettingsFile && indicators.hasProjectsSessions
172
+ ? 'settings file + project sessions'
173
+ : indicators.credentials?.hasOAuthToken
174
+ ? 'credentials file with OAuth token'
175
+ : 'credentials file with API key'
176
+ : 'no valid credentials found',
177
+ });
178
+
179
+ if (hasCliAuth) {
180
+ logger.info('✓ Claude Code CLI authentication detected');
181
+ return;
182
+ }
183
+ } catch (error) {
184
+ // Ignore errors checking CLI auth - will fall through to warning
185
+ logger.warn('Error checking for Claude Code CLI authentication:', error);
186
+ }
187
+
188
+ // No authentication found - show warning with paths that were checked
189
+ const wHeader = '⚠️ WARNING: No Claude authentication configured'.padEnd(BOX_CONTENT_WIDTH);
190
+ const w1 = 'The Claude Agent SDK requires authentication to function.'.padEnd(BOX_CONTENT_WIDTH);
191
+ const w2 = 'Options:'.padEnd(BOX_CONTENT_WIDTH);
192
+ const w3 = '1. Install Claude Code CLI and authenticate with subscription'.padEnd(
193
+ BOX_CONTENT_WIDTH
194
+ );
195
+ const w4 = '2. Set your Anthropic API key:'.padEnd(BOX_CONTENT_WIDTH);
196
+ const w5 = ' export ANTHROPIC_API_KEY="sk-ant-..."'.padEnd(BOX_CONTENT_WIDTH);
197
+ const w6 = '3. Use the setup wizard in Settings to configure authentication.'.padEnd(
198
+ BOX_CONTENT_WIDTH
199
+ );
200
+
201
+ // Build paths checked summary from the indicators (if available)
202
+ let pathsCheckedInfo = '';
203
+ if (cliAuthIndicators) {
204
+ const pathsChecked: string[] = [];
205
+
206
+ // Collect paths that were checked (paths are always populated strings)
207
+ pathsChecked.push(`Settings: ${cliAuthIndicators.checks.settingsFile.path}`);
208
+ pathsChecked.push(`Stats cache: ${cliAuthIndicators.checks.statsCache.path}`);
209
+ pathsChecked.push(`Projects dir: ${cliAuthIndicators.checks.projectsDir.path}`);
210
+ for (const credFile of cliAuthIndicators.checks.credentialFiles) {
211
+ pathsChecked.push(`Credentials: ${credFile.path}`);
212
+ }
213
+
214
+ if (pathsChecked.length > 0) {
215
+ pathsCheckedInfo = `
216
+ ║ ║
217
+ ║ ${'Paths checked:'.padEnd(BOX_CONTENT_WIDTH)}║
218
+ ${pathsChecked
219
+ .map((p) => {
220
+ const maxLen = BOX_CONTENT_WIDTH - 4;
221
+ const display = p.length > maxLen ? '...' + p.slice(-(maxLen - 3)) : p;
222
+ return `║ ${display.padEnd(maxLen)} ║`;
223
+ })
224
+ .join('\n')}`;
225
+ }
226
+ }
227
+
228
+ logger.warn(`
229
+ ╔═════════════════════════════════���═══════════════════════════════════╗
230
+ ║ ${wHeader}║
231
+ ╠═════════════════════════════════════════════════════════════════════╣
232
+ ║ ║
233
+ ║ ${w1}║
234
+ ║ ║
235
+ ║ ${w2}║
236
+ ║ ${w3}║
237
+ ║ ${w4}║
238
+ ║ ${w5}║
239
+ ║ ${w6}║${pathsCheckedInfo}
240
+ ║ ║
241
+ ╚═════════════════════════════════════════════════════════════════════╝
242
+ `);
243
+ })();
244
+
245
+ // Initialize security
246
+ initAllowedPaths();
247
+
248
+ // Create Express app
249
+ const app = express();
250
+
251
+ // Middleware
252
+ // Custom colored logger showing only endpoint and status code (dynamically configurable)
253
+ morgan.token('status-colored', (_req, res) => {
254
+ const status = res.statusCode;
255
+ if (status >= 500) return `\x1b[31m${status}\x1b[0m`; // Red for server errors
256
+ if (status >= 400) return `\x1b[33m${status}\x1b[0m`; // Yellow for client errors
257
+ if (status >= 300) return `\x1b[36m${status}\x1b[0m`; // Cyan for redirects
258
+ return `\x1b[32m${status}\x1b[0m`; // Green for success
259
+ });
260
+
261
+ app.use(
262
+ morgan(':method :url :status-colored', {
263
+ // Skip when request logging is disabled or for health check endpoints
264
+ skip: (req) =>
265
+ !requestLoggingEnabled ||
266
+ req.url === '/api/health' ||
267
+ req.url === '/api/auto-mode/context-exists',
268
+ })
269
+ );
270
+ // CORS configuration
271
+ // When using credentials (cookies), origin cannot be '*'
272
+ // We dynamically allow the requesting origin for local development
273
+
274
+ // Check if origin is a local/private network address
275
+ function isLocalOrigin(origin: string): boolean {
276
+ try {
277
+ const url = new URL(origin);
278
+ const hostname = url.hostname;
279
+ return (
280
+ hostname === 'localhost' ||
281
+ hostname === '127.0.0.1' ||
282
+ hostname === '[::1]' ||
283
+ hostname === '0.0.0.0' ||
284
+ hostname.startsWith('192.168.') ||
285
+ hostname.startsWith('10.') ||
286
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(hostname)
287
+ );
288
+ } catch {
289
+ return false;
290
+ }
291
+ }
292
+
293
+ app.use(
294
+ cors({
295
+ origin: (origin, callback) => {
296
+ // Allow requests with no origin (like mobile apps, curl, Electron)
297
+ if (!origin) {
298
+ callback(null, true);
299
+ return;
300
+ }
301
+
302
+ // If CORS_ORIGIN is set, use it (can be comma-separated list)
303
+ const allowedOrigins = process.env.CORS_ORIGIN?.split(',')
304
+ .map((o) => o.trim())
305
+ .filter(Boolean);
306
+ if (allowedOrigins && allowedOrigins.length > 0) {
307
+ if (allowedOrigins.includes('*')) {
308
+ callback(null, true);
309
+ return;
310
+ }
311
+ if (allowedOrigins.includes(origin)) {
312
+ callback(null, origin);
313
+ return;
314
+ }
315
+ // Fall through to local network check below
316
+ }
317
+
318
+ // Allow all localhost/loopback/private network origins (any port)
319
+ if (isLocalOrigin(origin)) {
320
+ callback(null, origin);
321
+ return;
322
+ }
323
+
324
+ // Reject other origins by default for security
325
+ callback(new Error('Not allowed by CORS'));
326
+ },
327
+ credentials: true,
328
+ })
329
+ );
330
+ app.use(express.json({ limit: '50mb' }));
331
+ app.use(cookieParser());
332
+
333
+ // Create shared event emitter for streaming
334
+ const events: EventEmitter = createEventEmitter();
335
+
336
+ // Create services
337
+ // Note: settingsService is created first so it can be injected into other services
338
+ const settingsService = new SettingsService(DATA_DIR);
339
+ const agentService = new AgentService(DATA_DIR, events, settingsService);
340
+ const featureLoader = new FeatureLoader();
341
+
342
+ // Auto-mode services: compatibility layer provides old interface while using new architecture
343
+ const autoModeService = new AutoModeServiceCompat(events, settingsService, featureLoader);
344
+ const claudeUsageService = new ClaudeUsageService();
345
+ const codexAppServerService = new CodexAppServerService();
346
+ const codexModelCacheService = new CodexModelCacheService(DATA_DIR, codexAppServerService);
347
+ const codexUsageService = new CodexUsageService(codexAppServerService);
348
+ const zaiUsageService = new ZaiUsageService();
349
+ const geminiUsageService = new GeminiUsageService();
350
+ const mcpTestService = new MCPTestService(settingsService);
351
+ const ideationService = new IdeationService(events, settingsService, featureLoader);
352
+
353
+ // Initialize DevServerService with event emitter for real-time log streaming
354
+ const devServerService = getDevServerService();
355
+ devServerService.initialize(DATA_DIR, events).catch((err) => {
356
+ logger.error('Failed to initialize DevServerService:', err);
357
+ });
358
+
359
+ // Initialize Notification Service with event emitter for real-time updates
360
+ const notificationService = getNotificationService();
361
+ notificationService.setEventEmitter(events);
362
+
363
+ // Initialize Event History Service
364
+ const eventHistoryService = getEventHistoryService();
365
+
366
+ // Initialize Test Runner Service with event emitter for real-time test output streaming
367
+ const testRunnerService = getTestRunnerService();
368
+ testRunnerService.setEventEmitter(events);
369
+
370
+ // Initialize Event Hook Service for custom event triggers (with history storage)
371
+ eventHookService.initialize(events, settingsService, eventHistoryService, featureLoader);
372
+
373
+ // Initialize services
374
+ (async () => {
375
+ // Migrate settings from legacy Electron userData location if needed
376
+ // This handles users upgrading from versions that stored settings in ~/.config/Automaker (Linux),
377
+ // ~/Library/Application Support/Automaker (macOS), or %APPDATA%\Automaker (Windows)
378
+ // to the new shared ./data directory
379
+ try {
380
+ const migrationResult = await settingsService.migrateFromLegacyElectronPath();
381
+ if (migrationResult.migrated) {
382
+ logger.info(`Settings migrated from legacy location: ${migrationResult.legacyPath}`);
383
+ logger.info(`Migrated files: ${migrationResult.migratedFiles.join(', ')}`);
384
+ }
385
+ if (migrationResult.errors.length > 0) {
386
+ logger.warn('Migration errors:', migrationResult.errors);
387
+ }
388
+ } catch (err) {
389
+ logger.warn('Failed to check for legacy settings migration:', err);
390
+ }
391
+
392
+ // Fetch global settings once and reuse for logging config and feature reconciliation
393
+ let globalSettings: Awaited<ReturnType<typeof settingsService.getGlobalSettings>> | null = null;
394
+ try {
395
+ globalSettings = await settingsService.getGlobalSettings();
396
+ } catch {
397
+ logger.warn('Failed to load global settings, using defaults');
398
+ }
399
+
400
+ // Apply logging settings from saved settings
401
+ if (globalSettings) {
402
+ try {
403
+ if (
404
+ globalSettings.serverLogLevel &&
405
+ LOG_LEVEL_MAP[globalSettings.serverLogLevel] !== undefined
406
+ ) {
407
+ setLogLevel(LOG_LEVEL_MAP[globalSettings.serverLogLevel]);
408
+ logger.info(`Server log level set to: ${globalSettings.serverLogLevel}`);
409
+ }
410
+ // Apply request logging setting (default true if not set)
411
+ const enableRequestLog = globalSettings.enableRequestLogging ?? true;
412
+ setRequestLoggingEnabled(enableRequestLog);
413
+ logger.info(`HTTP request logging: ${enableRequestLog ? 'enabled' : 'disabled'}`);
414
+ } catch {
415
+ logger.warn('Failed to apply logging settings, using defaults');
416
+ }
417
+ }
418
+
419
+ await agentService.initialize();
420
+ logger.info('Agent service initialized');
421
+
422
+ // Reconcile feature states on startup
423
+ // After any type of restart (clean, forced, crash), features may be stuck in
424
+ // transient states (in_progress, interrupted, pipeline_*) that don't match reality.
425
+ // Reconcile them back to resting states before the UI is served.
426
+ if (globalSettings) {
427
+ try {
428
+ if (globalSettings.projects && globalSettings.projects.length > 0) {
429
+ let totalReconciled = 0;
430
+ for (const project of globalSettings.projects) {
431
+ const count = await autoModeService.reconcileFeatureStates(project.path);
432
+ totalReconciled += count;
433
+ }
434
+ if (totalReconciled > 0) {
435
+ logger.info(
436
+ `[STARTUP] Reconciled ${totalReconciled} feature(s) across ${globalSettings.projects.length} project(s)`
437
+ );
438
+ } else {
439
+ logger.info('[STARTUP] Feature state reconciliation complete - no stale states found');
440
+ }
441
+
442
+ // Resume interrupted features in the background for all projects.
443
+ // This handles features stuck in transient states (in_progress, pipeline_*)
444
+ // or explicitly marked as interrupted. Running in background so it doesn't block startup.
445
+ for (const project of globalSettings.projects) {
446
+ autoModeService.resumeInterruptedFeatures(project.path).catch((err) => {
447
+ logger.warn(
448
+ `[STARTUP] Failed to resume interrupted features for ${project.path}:`,
449
+ err
450
+ );
451
+ });
452
+ }
453
+ logger.info('[STARTUP] Initiated background resume of interrupted features');
454
+ }
455
+ } catch (err) {
456
+ logger.warn('[STARTUP] Failed to reconcile feature states:', err);
457
+ }
458
+ }
459
+
460
+ // Bootstrap Codex model cache in background (don't block server startup)
461
+ void codexModelCacheService.getModels().catch((err) => {
462
+ logger.error('Failed to bootstrap Codex model cache:', err);
463
+ });
464
+ })();
465
+
466
+ // Run stale validation cleanup every hour to prevent memory leaks from crashed validations
467
+ const VALIDATION_CLEANUP_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
468
+ setInterval(() => {
469
+ const cleaned = cleanupStaleValidations();
470
+ if (cleaned > 0) {
471
+ logger.info(`Cleaned up ${cleaned} stale validation entries`);
472
+ }
473
+ }, VALIDATION_CLEANUP_INTERVAL_MS);
474
+
475
+ // Require Content-Type: application/json for all API POST/PUT/PATCH requests
476
+ // This helps prevent CSRF and content-type confusion attacks
477
+ app.use('/api', requireJsonContentType);
478
+
479
+ // Mount API routes - health, auth, and setup are unauthenticated
480
+ app.use('/api/health', createHealthRoutes());
481
+ app.use('/api/auth', createAuthRoutes());
482
+ app.use('/api/setup', createSetupRoutes());
483
+
484
+ // Apply authentication to all other routes
485
+ app.use('/api', authMiddleware);
486
+
487
+ // Protected health endpoint with detailed info
488
+ app.get('/api/health/detailed', createDetailedHandler());
489
+
490
+ app.use('/api/fs', createFsRoutes(events));
491
+ app.use('/api/agent', createAgentRoutes(agentService, events));
492
+ app.use('/api/sessions', createSessionsRoutes(agentService));
493
+ app.use(
494
+ '/api/features',
495
+ createFeaturesRoutes(featureLoader, settingsService, events, autoModeService)
496
+ );
497
+ app.use('/api/auto-mode', createAutoModeRoutes(autoModeService));
498
+ app.use('/api/enhance-prompt', createEnhancePromptRoutes(settingsService));
499
+ app.use('/api/worktree', createWorktreeRoutes(events, settingsService, featureLoader));
500
+ app.use('/api/git', createGitRoutes());
501
+ app.use('/api/models', createModelsRoutes());
502
+ app.use('/api/spec-regeneration', createSpecRegenerationRoutes(events, settingsService));
503
+ app.use('/api/running-agents', createRunningAgentsRoutes(autoModeService));
504
+ app.use('/api/workspace', createWorkspaceRoutes());
505
+ app.use('/api/templates', createTemplatesRoutes());
506
+ app.use('/api/terminal', createTerminalRoutes());
507
+ app.use('/api/settings', createSettingsRoutes(settingsService));
508
+ app.use('/api/claude', createClaudeRoutes(claudeUsageService));
509
+ app.use('/api/codex', createCodexRoutes(codexUsageService, codexModelCacheService));
510
+ app.use('/api/zai', createZaiRoutes(zaiUsageService, settingsService));
511
+ app.use('/api/gemini', createGeminiRoutes(geminiUsageService, events));
512
+ app.use('/api/github', createGitHubRoutes(events, settingsService));
513
+ app.use('/api/context', createContextRoutes(settingsService));
514
+ app.use('/api/backlog-plan', createBacklogPlanRoutes(events, settingsService));
515
+ app.use('/api/mcp', createMCPRoutes(mcpTestService));
516
+ app.use('/api/pipeline', createPipelineRoutes(pipelineService));
517
+ app.use('/api/ideation', createIdeationRoutes(events, ideationService, featureLoader));
518
+ app.use('/api/notifications', createNotificationsRoutes(notificationService));
519
+ app.use('/api/event-history', createEventHistoryRoutes(eventHistoryService, settingsService));
520
+ app.use(
521
+ '/api/projects',
522
+ createProjectsRoutes(featureLoader, autoModeService, settingsService, notificationService)
523
+ );
524
+
525
+ // Create HTTP server
526
+ const server = createServer(app);
527
+
528
+ // WebSocket servers using noServer mode for proper multi-path support
529
+ const wss = new WebSocketServer({ noServer: true });
530
+ const terminalWss = new WebSocketServer({ noServer: true });
531
+ const terminalService = getTerminalService(settingsService);
532
+
533
+ /**
534
+ * Authenticate WebSocket upgrade requests
535
+ * Checks for API key in header/query, session token in header/query, OR valid session cookie
536
+ */
537
+ function authenticateWebSocket(request: import('http').IncomingMessage): boolean {
538
+ const url = new URL(request.url || '', `http://${request.headers.host}`);
539
+
540
+ // Convert URL search params to query object
541
+ const query: Record<string, string | undefined> = {};
542
+ url.searchParams.forEach((value, key) => {
543
+ query[key] = value;
544
+ });
545
+
546
+ // Parse cookies from header
547
+ const cookieHeader = request.headers.cookie;
548
+ const cookies = cookieHeader ? cookie.parse(cookieHeader) : {};
549
+
550
+ // Use shared authentication logic for standard auth methods
551
+ if (
552
+ checkRawAuthentication(
553
+ request.headers as Record<string, string | string[] | undefined>,
554
+ query,
555
+ cookies
556
+ )
557
+ ) {
558
+ return true;
559
+ }
560
+
561
+ // Additionally check for short-lived WebSocket connection token (WebSocket-specific)
562
+ const wsToken = url.searchParams.get('wsToken');
563
+ if (wsToken && validateWsConnectionToken(wsToken)) {
564
+ return true;
565
+ }
566
+
567
+ return false;
568
+ }
569
+
570
+ // Handle HTTP upgrade requests manually to route to correct WebSocket server
571
+ server.on('upgrade', (request, socket, head) => {
572
+ const { pathname } = new URL(request.url || '', `http://${request.headers.host}`);
573
+
574
+ // Authenticate all WebSocket connections
575
+ if (!authenticateWebSocket(request)) {
576
+ logger.info('Authentication failed, rejecting connection');
577
+ socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
578
+ socket.destroy();
579
+ return;
580
+ }
581
+
582
+ if (pathname === '/api/events') {
583
+ wss.handleUpgrade(request, socket, head, (ws) => {
584
+ wss.emit('connection', ws, request);
585
+ });
586
+ } else if (pathname === '/api/terminal/ws') {
587
+ terminalWss.handleUpgrade(request, socket, head, (ws) => {
588
+ terminalWss.emit('connection', ws, request);
589
+ });
590
+ } else {
591
+ socket.destroy();
592
+ }
593
+ });
594
+
595
+ // Events WebSocket connection handler
596
+ wss.on('connection', (ws: WebSocket) => {
597
+ logger.info('Client connected, ready state:', ws.readyState);
598
+
599
+ // Subscribe to all events and forward to this client
600
+ const unsubscribe = events.subscribe((type, payload) => {
601
+ // Use debug level for high-frequency events to avoid log spam
602
+ // that causes progressive memory growth and server slowdown
603
+ const isHighFrequency =
604
+ type === 'dev-server:output' || type === 'test-runner:output' || type === 'feature:progress';
605
+ const log = isHighFrequency ? logger.debug.bind(logger) : logger.info.bind(logger);
606
+
607
+ log('Event received:', {
608
+ type,
609
+ hasPayload: !!payload,
610
+ wsReadyState: ws.readyState,
611
+ });
612
+
613
+ if (ws.readyState === WebSocket.OPEN) {
614
+ const message = JSON.stringify({ type, payload });
615
+ ws.send(message);
616
+ } else {
617
+ logger.warn('Cannot send event, WebSocket not open. ReadyState:', ws.readyState);
618
+ }
619
+ });
620
+
621
+ ws.on('close', () => {
622
+ logger.info('Client disconnected');
623
+ unsubscribe();
624
+ });
625
+
626
+ ws.on('error', (error) => {
627
+ logger.error('ERROR:', error);
628
+ unsubscribe();
629
+ });
630
+ });
631
+
632
+ // Track WebSocket connections per session
633
+ const terminalConnections: Map<string, Set<WebSocket>> = new Map();
634
+ // Track last resize dimensions per session to deduplicate resize messages
635
+ const lastResizeDimensions: Map<string, { cols: number; rows: number }> = new Map();
636
+ // Track last resize timestamp to rate-limit resize operations (prevents resize storm)
637
+ const lastResizeTime: Map<string, number> = new Map();
638
+ const RESIZE_MIN_INTERVAL_MS = 100; // Minimum 100ms between resize operations
639
+
640
+ // Clean up resize tracking when sessions actually exit (not just when connections close)
641
+ terminalService.onExit((sessionId) => {
642
+ lastResizeDimensions.delete(sessionId);
643
+ lastResizeTime.delete(sessionId);
644
+ terminalConnections.delete(sessionId);
645
+ });
646
+
647
+ // Terminal WebSocket connection handler
648
+ terminalWss.on('connection', (ws: WebSocket, req: import('http').IncomingMessage) => {
649
+ // Parse URL to get session ID and token
650
+ const url = new URL(req.url || '', `http://${req.headers.host}`);
651
+ const sessionId = url.searchParams.get('sessionId');
652
+ const token = url.searchParams.get('token');
653
+
654
+ logger.info(`Connection attempt for session: ${sessionId}`);
655
+
656
+ // Check if terminal is enabled
657
+ if (!isTerminalEnabled()) {
658
+ logger.info('Terminal is disabled');
659
+ ws.close(4003, 'Terminal access is disabled');
660
+ return;
661
+ }
662
+
663
+ // Validate token if password is required
664
+ if (isTerminalPasswordRequired() && !validateTerminalToken(token || undefined)) {
665
+ logger.info('Invalid or missing token');
666
+ ws.close(4001, 'Authentication required');
667
+ return;
668
+ }
669
+
670
+ if (!sessionId) {
671
+ logger.info('No session ID provided');
672
+ ws.close(4002, 'Session ID required');
673
+ return;
674
+ }
675
+
676
+ // Check if session exists
677
+ const session = terminalService.getSession(sessionId);
678
+ if (!session) {
679
+ logger.warn(
680
+ `Terminal session ${sessionId} not found. ` +
681
+ `The session may have exited, been deleted, or was never created. ` +
682
+ `Active terminal sessions: ${terminalService.getSessionCount()}`
683
+ );
684
+ ws.close(
685
+ 4004,
686
+ 'Session not found. The terminal session may have expired or been closed. Please create a new terminal.'
687
+ );
688
+ return;
689
+ }
690
+
691
+ logger.info(`Client connected to session ${sessionId}`);
692
+
693
+ // Track this connection
694
+ if (!terminalConnections.has(sessionId)) {
695
+ terminalConnections.set(sessionId, new Set());
696
+ }
697
+ terminalConnections.get(sessionId)!.add(ws);
698
+
699
+ // Send initial connection success FIRST
700
+ ws.send(
701
+ JSON.stringify({
702
+ type: 'connected',
703
+ sessionId,
704
+ shell: session.shell,
705
+ cwd: session.cwd,
706
+ })
707
+ );
708
+
709
+ // Send scrollback buffer BEFORE subscribing to prevent race condition
710
+ // Also clear pending output buffer to prevent duplicates from throttled flush
711
+ const scrollback = terminalService.getScrollbackAndClearPending(sessionId);
712
+ if (scrollback && scrollback.length > 0) {
713
+ ws.send(
714
+ JSON.stringify({
715
+ type: 'scrollback',
716
+ data: scrollback,
717
+ })
718
+ );
719
+ }
720
+
721
+ // NOW subscribe to terminal data (after scrollback is sent)
722
+ const unsubscribeData = terminalService.onData((sid, data) => {
723
+ if (sid === sessionId && ws.readyState === WebSocket.OPEN) {
724
+ ws.send(JSON.stringify({ type: 'data', data }));
725
+ }
726
+ });
727
+
728
+ // Subscribe to terminal exit
729
+ const unsubscribeExit = terminalService.onExit((sid, exitCode) => {
730
+ if (sid === sessionId && ws.readyState === WebSocket.OPEN) {
731
+ ws.send(JSON.stringify({ type: 'exit', exitCode }));
732
+ ws.close(1000, 'Session ended');
733
+ }
734
+ });
735
+
736
+ // Handle incoming messages
737
+ ws.on('message', (message) => {
738
+ try {
739
+ const msg = JSON.parse(message.toString());
740
+
741
+ switch (msg.type) {
742
+ case 'input':
743
+ // Validate input data type and length
744
+ if (typeof msg.data !== 'string') {
745
+ ws.send(JSON.stringify({ type: 'error', message: 'Invalid input type' }));
746
+ break;
747
+ }
748
+ // Limit input size to 1MB to prevent memory issues
749
+ if (msg.data.length > 1024 * 1024) {
750
+ ws.send(JSON.stringify({ type: 'error', message: 'Input too large' }));
751
+ break;
752
+ }
753
+ // Write user input to terminal
754
+ terminalService.write(sessionId, msg.data);
755
+ break;
756
+
757
+ case 'resize':
758
+ // Validate resize dimensions are positive integers within reasonable bounds
759
+ if (
760
+ typeof msg.cols !== 'number' ||
761
+ typeof msg.rows !== 'number' ||
762
+ !Number.isInteger(msg.cols) ||
763
+ !Number.isInteger(msg.rows) ||
764
+ msg.cols < 1 ||
765
+ msg.cols > 1000 ||
766
+ msg.rows < 1 ||
767
+ msg.rows > 500
768
+ ) {
769
+ break; // Silently ignore invalid resize requests
770
+ }
771
+ // Resize terminal with deduplication and rate limiting
772
+ if (msg.cols && msg.rows) {
773
+ const now = Date.now();
774
+ const lastTime = lastResizeTime.get(sessionId) || 0;
775
+ const lastDimensions = lastResizeDimensions.get(sessionId);
776
+
777
+ // Skip if resized too recently (prevents resize storm during splits)
778
+ if (now - lastTime < RESIZE_MIN_INTERVAL_MS) {
779
+ break;
780
+ }
781
+
782
+ // Check if dimensions are different from last resize
783
+ if (
784
+ !lastDimensions ||
785
+ lastDimensions.cols !== msg.cols ||
786
+ lastDimensions.rows !== msg.rows
787
+ ) {
788
+ // Only suppress output on subsequent resizes, not the first one
789
+ // The first resize happens on terminal open and we don't want to drop the initial prompt
790
+ const isFirstResize = !lastDimensions;
791
+ terminalService.resize(sessionId, msg.cols, msg.rows, !isFirstResize);
792
+ lastResizeDimensions.set(sessionId, {
793
+ cols: msg.cols,
794
+ rows: msg.rows,
795
+ });
796
+ lastResizeTime.set(sessionId, now);
797
+ }
798
+ }
799
+ break;
800
+
801
+ case 'ping':
802
+ // Respond to ping
803
+ ws.send(JSON.stringify({ type: 'pong' }));
804
+ break;
805
+
806
+ default:
807
+ logger.warn(`Unknown message type: ${msg.type}`);
808
+ }
809
+ } catch (error) {
810
+ logger.error('Error processing message:', error);
811
+ }
812
+ });
813
+
814
+ ws.on('close', () => {
815
+ logger.info(`Client disconnected from session ${sessionId}`);
816
+ unsubscribeData();
817
+ unsubscribeExit();
818
+
819
+ // Remove from connections tracking
820
+ const connections = terminalConnections.get(sessionId);
821
+ if (connections) {
822
+ connections.delete(ws);
823
+ if (connections.size === 0) {
824
+ terminalConnections.delete(sessionId);
825
+ // DON'T delete lastResizeDimensions/lastResizeTime here!
826
+ // The session still exists, and reconnecting clients need to know
827
+ // this isn't the "first resize" to prevent duplicate prompts.
828
+ // These get cleaned up when the session actually exits.
829
+ }
830
+ }
831
+ });
832
+
833
+ ws.on('error', (error) => {
834
+ logger.error(`Error on session ${sessionId}:`, error);
835
+ unsubscribeData();
836
+ unsubscribeExit();
837
+ });
838
+ });
839
+
840
+ // Start server with error handling for port conflicts
841
+ const startServer = (port: number, host: string) => {
842
+ server.listen(port, host, () => {
843
+ const terminalStatus = isTerminalEnabled()
844
+ ? isTerminalPasswordRequired()
845
+ ? 'enabled (password protected)'
846
+ : 'enabled'
847
+ : 'disabled';
848
+
849
+ // Build URLs for display
850
+ const listenAddr = `${host}:${port}`;
851
+ const httpUrl = `http://${HOSTNAME}:${port}`;
852
+ const wsEventsUrl = `ws://${HOSTNAME}:${port}/api/events`;
853
+ const wsTerminalUrl = `ws://${HOSTNAME}:${port}/api/terminal/ws`;
854
+ const healthUrl = `http://${HOSTNAME}:${port}/api/health`;
855
+
856
+ const sHeader = '🚀 Automaker Backend Server'.padEnd(BOX_CONTENT_WIDTH);
857
+ const s1 = `Listening: ${listenAddr}`.padEnd(BOX_CONTENT_WIDTH);
858
+ const s2 = `HTTP API: ${httpUrl}`.padEnd(BOX_CONTENT_WIDTH);
859
+ const s3 = `WebSocket: ${wsEventsUrl}`.padEnd(BOX_CONTENT_WIDTH);
860
+ const s4 = `Terminal WS: ${wsTerminalUrl}`.padEnd(BOX_CONTENT_WIDTH);
861
+ const s5 = `Health: ${healthUrl}`.padEnd(BOX_CONTENT_WIDTH);
862
+ const s6 = `Terminal: ${terminalStatus}`.padEnd(BOX_CONTENT_WIDTH);
863
+
864
+ logger.info(`
865
+ ╔═════════════════════════════════════════════════════════════════════╗
866
+ ║ ${sHeader}║
867
+ ╠═════════════════════════════════════════════════════════════════════╣
868
+ ║ ║
869
+ ║ ${s1}║
870
+ ║ ${s2}║
871
+ ║ ${s3}║
872
+ ║ ${s4}║
873
+ ║ ${s5}║
874
+ ║ ${s6}║
875
+ ║ ║
876
+ ╚═════════════════════════════════════════════════════════════════════╝
877
+ `);
878
+ });
879
+
880
+ server.on('error', (error: NodeJS.ErrnoException) => {
881
+ if (error.code === 'EADDRINUSE') {
882
+ const portStr = port.toString();
883
+ const nextPortStr = (port + 1).toString();
884
+ const killCmd = `lsof -ti:${portStr} | xargs kill -9`;
885
+ const altCmd = `PORT=${nextPortStr} npm run dev:server`;
886
+
887
+ const eHeader = `❌ ERROR: Port ${portStr} is already in use`.padEnd(BOX_CONTENT_WIDTH);
888
+ const e1 = 'Another process is using this port.'.padEnd(BOX_CONTENT_WIDTH);
889
+ const e2 = 'To fix this, try one of:'.padEnd(BOX_CONTENT_WIDTH);
890
+ const e3 = '1. Kill the process using the port:'.padEnd(BOX_CONTENT_WIDTH);
891
+ const e4 = ` ${killCmd}`.padEnd(BOX_CONTENT_WIDTH);
892
+ const e5 = '2. Use a different port:'.padEnd(BOX_CONTENT_WIDTH);
893
+ const e6 = ` ${altCmd}`.padEnd(BOX_CONTENT_WIDTH);
894
+ const e7 = '3. Use the init.sh script which handles this:'.padEnd(BOX_CONTENT_WIDTH);
895
+ const e8 = ' ./init.sh'.padEnd(BOX_CONTENT_WIDTH);
896
+
897
+ logger.error(`
898
+ ╔═════════════════════════════════════════════════════════════════════╗
899
+ ║ ${eHeader}║
900
+ ╠═════════════════════════════════════════════════════════════════════╣
901
+ ║ ║
902
+ ║ ${e1}║
903
+ ║ ║
904
+ ║ ${e2}║
905
+ ║ ║
906
+ ║ ${e3}║
907
+ ║ ${e4}║
908
+ ║ ║
909
+ ║ ${e5}║
910
+ ║ ${e6}║
911
+ ║ ║
912
+ ║ ${e7}║
913
+ ║ ${e8}║
914
+ ║ ║
915
+ ╚═════════════════════════════════════════════════════════════════════╝
916
+ `);
917
+ process.exit(1);
918
+ } else {
919
+ logger.error('Error starting server:', error);
920
+ process.exit(1);
921
+ }
922
+ });
923
+ };
924
+
925
+ startServer(PORT, HOST);
926
+
927
+ // Global error handlers to prevent crashes from uncaught errors
928
+ process.on('unhandledRejection', (reason: unknown, _promise: Promise<unknown>) => {
929
+ logger.error('Unhandled Promise Rejection:', {
930
+ reason: reason instanceof Error ? reason.message : String(reason),
931
+ stack: reason instanceof Error ? reason.stack : undefined,
932
+ });
933
+ // Don't exit - log the error and continue running
934
+ // This prevents the server from crashing due to unhandled rejections
935
+ });
936
+
937
+ process.on('uncaughtException', (error: Error) => {
938
+ logger.error('Uncaught Exception:', {
939
+ message: error.message,
940
+ stack: error.stack,
941
+ });
942
+ // Exit on uncaught exceptions to prevent undefined behavior
943
+ // The process is in an unknown state after an uncaught exception
944
+ process.exit(1);
945
+ });
946
+
947
+ // Graceful shutdown timeout (30 seconds)
948
+ const SHUTDOWN_TIMEOUT_MS = 30000;
949
+
950
+ // Graceful shutdown helper
951
+ const gracefulShutdown = async (signal: string) => {
952
+ logger.info(`${signal} received, shutting down...`);
953
+
954
+ // Set up a force-exit timeout to prevent hanging
955
+ const forceExitTimeout = setTimeout(() => {
956
+ logger.error(`Shutdown timed out after ${SHUTDOWN_TIMEOUT_MS}ms, forcing exit`);
957
+ process.exit(1);
958
+ }, SHUTDOWN_TIMEOUT_MS);
959
+
960
+ // Mark all running features as interrupted before shutdown
961
+ // This ensures they can be resumed when the server restarts
962
+ // Note: markAllRunningFeaturesInterrupted handles errors internally and never rejects
963
+ await autoModeService.markAllRunningFeaturesInterrupted(`${signal} signal received`);
964
+
965
+ terminalService.cleanup();
966
+ server.close(() => {
967
+ clearTimeout(forceExitTimeout);
968
+ logger.info('Server closed');
969
+ process.exit(0);
970
+ });
971
+ };
972
+
973
+ process.on('SIGTERM', () => {
974
+ gracefulShutdown('SIGTERM');
975
+ });
976
+
977
+ process.on('SIGINT', () => {
978
+ gracefulShutdown('SIGINT');
979
+ });
jules_branch/apps/server/src/lib/agent-discovery.ts ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Agent Discovery - Scans filesystem for AGENT.md files
3
+ *
4
+ * Discovers agents from:
5
+ * - ~/.claude/agents/ (user-level, global)
6
+ * - .claude/agents/ (project-level)
7
+ *
8
+ * Similar to Skills, but for custom subagents defined in AGENT.md files.
9
+ */
10
+
11
+ import path from 'path';
12
+ import os from 'os';
13
+ import { createLogger } from '@automaker/utils';
14
+ import { secureFs, systemPaths } from '@automaker/platform';
15
+ import type { AgentDefinition } from '@automaker/types';
16
+
17
+ const logger = createLogger('AgentDiscovery');
18
+
19
+ export interface FilesystemAgent {
20
+ name: string; // Directory name (e.g., 'code-reviewer')
21
+ definition: AgentDefinition;
22
+ source: 'user' | 'project';
23
+ filePath: string; // Full path to AGENT.md
24
+ }
25
+
26
+ /**
27
+ * Parse agent content string into AgentDefinition
28
+ * Format:
29
+ * ---
30
+ * name: agent-name # Optional
31
+ * description: When to use this agent
32
+ * tools: tool1, tool2, tool3 # Optional (comma or space separated list)
33
+ * model: sonnet # Optional: sonnet, opus, haiku
34
+ * ---
35
+ * System prompt content here...
36
+ */
37
+ function parseAgentContent(content: string, filePath: string): AgentDefinition | null {
38
+ // Extract frontmatter
39
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
40
+ if (!frontmatterMatch) {
41
+ logger.warn(`Invalid agent file format (missing frontmatter): ${filePath}`);
42
+ return null;
43
+ }
44
+
45
+ const [, frontmatter, prompt] = frontmatterMatch;
46
+
47
+ // Parse description (required)
48
+ const description = frontmatter.match(/description:\s*(.+)/)?.[1]?.trim();
49
+ if (!description) {
50
+ logger.warn(`Missing description in agent file: ${filePath}`);
51
+ return null;
52
+ }
53
+
54
+ // Parse tools (optional) - supports both comma-separated and space-separated
55
+ const toolsMatch = frontmatter.match(/tools:\s*(.+)/);
56
+ const tools = toolsMatch
57
+ ? toolsMatch[1]
58
+ .split(/[,\s]+/) // Split by comma or whitespace
59
+ .map((t) => t.trim())
60
+ .filter((t) => t && t !== '')
61
+ : undefined;
62
+
63
+ // Parse model (optional) - validate against allowed values
64
+ const modelMatch = frontmatter.match(/model:\s*(\w+)/);
65
+ const modelValue = modelMatch?.[1]?.trim();
66
+ const validModels = ['sonnet', 'opus', 'haiku', 'inherit'] as const;
67
+ const model =
68
+ modelValue && validModels.includes(modelValue as (typeof validModels)[number])
69
+ ? (modelValue as 'sonnet' | 'opus' | 'haiku' | 'inherit')
70
+ : undefined;
71
+
72
+ if (modelValue && !model) {
73
+ logger.warn(
74
+ `Invalid model "${modelValue}" in agent file: ${filePath}. Expected one of: ${validModels.join(', ')}`
75
+ );
76
+ }
77
+
78
+ return {
79
+ description,
80
+ prompt: prompt.trim(),
81
+ tools,
82
+ model,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Directory entry with type information
88
+ */
89
+ interface DirEntry {
90
+ name: string;
91
+ isFile: boolean;
92
+ isDirectory: boolean;
93
+ }
94
+
95
+ /**
96
+ * Filesystem adapter interface for abstracting systemPaths vs secureFs
97
+ */
98
+ interface FsAdapter {
99
+ exists: (filePath: string) => Promise<boolean>;
100
+ readdir: (dirPath: string) => Promise<DirEntry[]>;
101
+ readFile: (filePath: string) => Promise<string>;
102
+ }
103
+
104
+ /**
105
+ * Create a filesystem adapter for system paths (user directory)
106
+ */
107
+ function createSystemPathAdapter(): FsAdapter {
108
+ return {
109
+ exists: (filePath) => Promise.resolve(systemPaths.systemPathExists(filePath)),
110
+ readdir: async (dirPath) => {
111
+ const entryNames = await systemPaths.systemPathReaddir(dirPath);
112
+ const entries: DirEntry[] = [];
113
+ for (const name of entryNames) {
114
+ const stat = await systemPaths.systemPathStat(path.join(dirPath, name));
115
+ entries.push({
116
+ name,
117
+ isFile: stat.isFile(),
118
+ isDirectory: stat.isDirectory(),
119
+ });
120
+ }
121
+ return entries;
122
+ },
123
+ readFile: (filePath) => systemPaths.systemPathReadFile(filePath, 'utf-8') as Promise<string>,
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Create a filesystem adapter for project paths (secureFs)
129
+ */
130
+ function createSecureFsAdapter(): FsAdapter {
131
+ return {
132
+ exists: (filePath) =>
133
+ secureFs
134
+ .access(filePath)
135
+ .then(() => true)
136
+ .catch(() => false),
137
+ readdir: async (dirPath) => {
138
+ const entries = await secureFs.readdir(dirPath, { withFileTypes: true });
139
+ return entries.map((entry) => ({
140
+ name: entry.name,
141
+ isFile: entry.isFile(),
142
+ isDirectory: entry.isDirectory(),
143
+ }));
144
+ },
145
+ readFile: (filePath) => secureFs.readFile(filePath, 'utf-8') as Promise<string>,
146
+ };
147
+ }
148
+
149
+ /**
150
+ * Parse agent file using the provided filesystem adapter
151
+ */
152
+ async function parseAgentFileWithAdapter(
153
+ filePath: string,
154
+ fsAdapter: FsAdapter
155
+ ): Promise<AgentDefinition | null> {
156
+ try {
157
+ const content = await fsAdapter.readFile(filePath);
158
+ return parseAgentContent(content, filePath);
159
+ } catch (error) {
160
+ logger.error(`Failed to parse agent file: ${filePath}`, error);
161
+ return null;
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Scan a directory for agent .md files
167
+ * Agents can be in two formats:
168
+ * 1. Flat: agent-name.md (file directly in agents/)
169
+ * 2. Subdirectory: agent-name/AGENT.md (folder + file, similar to Skills)
170
+ */
171
+ async function scanAgentsDirectory(
172
+ baseDir: string,
173
+ source: 'user' | 'project'
174
+ ): Promise<FilesystemAgent[]> {
175
+ const agents: FilesystemAgent[] = [];
176
+ const fsAdapter = source === 'user' ? createSystemPathAdapter() : createSecureFsAdapter();
177
+
178
+ try {
179
+ // Check if directory exists
180
+ const exists = await fsAdapter.exists(baseDir);
181
+ if (!exists) {
182
+ logger.debug(`Directory does not exist: ${baseDir}`);
183
+ return agents;
184
+ }
185
+
186
+ // Read all entries in the directory
187
+ const entries = await fsAdapter.readdir(baseDir);
188
+
189
+ for (const entry of entries) {
190
+ // Check for flat .md file format (agent-name.md)
191
+ if (entry.isFile && entry.name.endsWith('.md')) {
192
+ const agentName = entry.name.slice(0, -3); // Remove .md extension
193
+ const agentFilePath = path.join(baseDir, entry.name);
194
+ const definition = await parseAgentFileWithAdapter(agentFilePath, fsAdapter);
195
+ if (definition) {
196
+ agents.push({
197
+ name: agentName,
198
+ definition,
199
+ source,
200
+ filePath: agentFilePath,
201
+ });
202
+ logger.debug(`Discovered ${source} agent (flat): ${agentName}`);
203
+ }
204
+ }
205
+ // Check for subdirectory format (agent-name/AGENT.md)
206
+ else if (entry.isDirectory) {
207
+ const agentFilePath = path.join(baseDir, entry.name, 'AGENT.md');
208
+ const agentFileExists = await fsAdapter.exists(agentFilePath);
209
+
210
+ if (agentFileExists) {
211
+ const definition = await parseAgentFileWithAdapter(agentFilePath, fsAdapter);
212
+ if (definition) {
213
+ agents.push({
214
+ name: entry.name,
215
+ definition,
216
+ source,
217
+ filePath: agentFilePath,
218
+ });
219
+ logger.debug(`Discovered ${source} agent (subdirectory): ${entry.name}`);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ } catch (error) {
225
+ logger.error(`Failed to scan agents directory: ${baseDir}`, error);
226
+ }
227
+
228
+ return agents;
229
+ }
230
+
231
+ /**
232
+ * Discover all filesystem-based agents from user and project sources
233
+ */
234
+ export async function discoverFilesystemAgents(
235
+ projectPath?: string,
236
+ sources: Array<'user' | 'project'> = ['user', 'project']
237
+ ): Promise<FilesystemAgent[]> {
238
+ const agents: FilesystemAgent[] = [];
239
+
240
+ // Discover user-level agents from ~/.claude/agents/
241
+ if (sources.includes('user')) {
242
+ const userAgentsDir = path.join(os.homedir(), '.claude', 'agents');
243
+ const userAgents = await scanAgentsDirectory(userAgentsDir, 'user');
244
+ agents.push(...userAgents);
245
+ logger.info(`Discovered ${userAgents.length} user-level agents from ${userAgentsDir}`);
246
+ }
247
+
248
+ // Discover project-level agents from .claude/agents/
249
+ if (sources.includes('project') && projectPath) {
250
+ const projectAgentsDir = path.join(projectPath, '.claude', 'agents');
251
+ const projectAgents = await scanAgentsDirectory(projectAgentsDir, 'project');
252
+ agents.push(...projectAgents);
253
+ logger.info(`Discovered ${projectAgents.length} project-level agents from ${projectAgentsDir}`);
254
+ }
255
+
256
+ return agents;
257
+ }
jules_branch/apps/server/src/lib/app-spec-format.ts ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * XML Template Format Specification for app_spec.txt
3
+ *
4
+ * This format must be included in all prompts that generate, modify, or regenerate
5
+ * app specifications to ensure consistency across the application.
6
+ */
7
+
8
+ // Import and re-export spec types from shared package
9
+ export type { SpecOutput } from '@automaker/types';
10
+ export { specOutputSchema } from '@automaker/types';
11
+
12
+ /**
13
+ * Escape special XML characters
14
+ * Handles undefined/null values by converting them to empty strings
15
+ */
16
+ export function escapeXml(str: string | undefined | null): string {
17
+ if (str == null) {
18
+ return '';
19
+ }
20
+ return str
21
+ .replace(/&/g, '&amp;')
22
+ .replace(/</g, '&lt;')
23
+ .replace(/>/g, '&gt;')
24
+ .replace(/"/g, '&quot;')
25
+ .replace(/'/g, '&apos;');
26
+ }
27
+
28
+ /**
29
+ * Convert structured spec output to XML format
30
+ */
31
+ export function specToXml(spec: import('@automaker/types').SpecOutput): string {
32
+ const indent = ' ';
33
+
34
+ let xml = `<?xml version="1.0" encoding="UTF-8"?>
35
+ <project_specification>
36
+ ${indent}<project_name>${escapeXml(spec.project_name)}</project_name>
37
+
38
+ ${indent}<overview>
39
+ ${indent}${indent}${escapeXml(spec.overview)}
40
+ ${indent}</overview>
41
+
42
+ ${indent}<technology_stack>
43
+ ${spec.technology_stack.map((t) => `${indent}${indent}<technology>${escapeXml(t)}</technology>`).join('\n')}
44
+ ${indent}</technology_stack>
45
+
46
+ ${indent}<core_capabilities>
47
+ ${spec.core_capabilities.map((c) => `${indent}${indent}<capability>${escapeXml(c)}</capability>`).join('\n')}
48
+ ${indent}</core_capabilities>
49
+
50
+ ${indent}<implemented_features>
51
+ ${spec.implemented_features
52
+ .map(
53
+ (f) => `${indent}${indent}<feature>
54
+ ${indent}${indent}${indent}<name>${escapeXml(f.name)}</name>
55
+ ${indent}${indent}${indent}<description>${escapeXml(f.description)}</description>${
56
+ f.file_locations && f.file_locations.length > 0
57
+ ? `\n${indent}${indent}${indent}<file_locations>
58
+ ${f.file_locations.map((loc) => `${indent}${indent}${indent}${indent}<location>${escapeXml(loc)}</location>`).join('\n')}
59
+ ${indent}${indent}${indent}</file_locations>`
60
+ : ''
61
+ }
62
+ ${indent}${indent}</feature>`
63
+ )
64
+ .join('\n')}
65
+ ${indent}</implemented_features>`;
66
+
67
+ // Optional sections
68
+ if (spec.additional_requirements && spec.additional_requirements.length > 0) {
69
+ xml += `
70
+
71
+ ${indent}<additional_requirements>
72
+ ${spec.additional_requirements.map((r) => `${indent}${indent}<requirement>${escapeXml(r)}</requirement>`).join('\n')}
73
+ ${indent}</additional_requirements>`;
74
+ }
75
+
76
+ if (spec.development_guidelines && spec.development_guidelines.length > 0) {
77
+ xml += `
78
+
79
+ ${indent}<development_guidelines>
80
+ ${spec.development_guidelines.map((g) => `${indent}${indent}<guideline>${escapeXml(g)}</guideline>`).join('\n')}
81
+ ${indent}</development_guidelines>`;
82
+ }
83
+
84
+ if (spec.implementation_roadmap && spec.implementation_roadmap.length > 0) {
85
+ xml += `
86
+
87
+ ${indent}<implementation_roadmap>
88
+ ${spec.implementation_roadmap
89
+ .map(
90
+ (r) => `${indent}${indent}<phase>
91
+ ${indent}${indent}${indent}<name>${escapeXml(r.phase)}</name>
92
+ ${indent}${indent}${indent}<status>${escapeXml(r.status)}</status>
93
+ ${indent}${indent}${indent}<description>${escapeXml(r.description)}</description>
94
+ ${indent}${indent}</phase>`
95
+ )
96
+ .join('\n')}
97
+ ${indent}</implementation_roadmap>`;
98
+ }
99
+
100
+ xml += `
101
+ </project_specification>`;
102
+
103
+ return xml;
104
+ }
105
+
106
+ /**
107
+ * Get prompt instruction for structured output (simpler than XML instructions)
108
+ */
109
+ export function getStructuredSpecPromptInstruction(): string {
110
+ return `
111
+ Analyze the project and provide a comprehensive specification with:
112
+
113
+ 1. **project_name**: The name of the project
114
+ 2. **overview**: A comprehensive description of what the project does, its purpose, and key goals
115
+ 3. **technology_stack**: List all technologies, frameworks, libraries, and tools used
116
+ 4. **core_capabilities**: List the main features and capabilities the project provides
117
+ 5. **implemented_features**: For each implemented feature, provide:
118
+ - name: Feature name
119
+ - description: What it does
120
+ - file_locations: Key files where it's implemented (optional)
121
+ 6. **additional_requirements**: Any system requirements, dependencies, or constraints (optional)
122
+ 7. **development_guidelines**: Development standards and best practices (optional)
123
+ 8. **implementation_roadmap**: Project phases with status (completed/in_progress/pending) (optional)
124
+
125
+ Be thorough in your analysis. The output will be automatically formatted as structured JSON.
126
+ `;
127
+ }
128
+ export const APP_SPEC_XML_FORMAT = `
129
+ The app_spec.txt file MUST follow this exact XML format:
130
+
131
+ <project_specification>
132
+ <project_name>Project Name</project_name>
133
+
134
+ <overview>
135
+ A comprehensive description of what the project does, its purpose, and key goals.
136
+ </overview>
137
+
138
+ <technology_stack>
139
+ <technology>Technology 1</technology>
140
+ <technology>Technology 2</technology>
141
+ <!-- List all technologies, frameworks, libraries, and tools used -->
142
+ </technology_stack>
143
+
144
+ <core_capabilities>
145
+ <capability>Core capability 1</capability>
146
+ <capability>Core capability 2</capability>
147
+ <!-- List main features and capabilities the project provides -->
148
+ </core_capabilities>
149
+
150
+ <implemented_features>
151
+ <!-- Features that have been implemented (populated by AI agent based on code analysis) -->
152
+ </implemented_features>
153
+
154
+ <!-- Optional sections that may be included: -->
155
+ <additional_requirements>
156
+ <!-- Any additional requirements or constraints -->
157
+ </additional_requirements>
158
+
159
+ <development_guidelines>
160
+ <guideline>Guideline 1</guideline>
161
+ <guideline>Guideline 2</guideline>
162
+ <!-- Development standards and practices -->
163
+ </development_guidelines>
164
+
165
+ <implementation_roadmap>
166
+ <!-- Phases or roadmap items for implementation -->
167
+ </implementation_roadmap>
168
+ </project_specification>
169
+
170
+ IMPORTANT:
171
+ - All content must be wrapped in valid XML tags
172
+ - Use proper XML escaping for special characters (&lt;, &gt;, &amp;)
173
+ - Maintain proper indentation (2 spaces)
174
+ - All sections should be populated based on project analysis
175
+ - The format must be strictly followed - do not use markdown, JSON, or any other format
176
+ `;
177
+
178
+ /**
179
+ * Returns a prompt suffix that instructs the AI to format the response as XML
180
+ * following the app_spec.txt template format.
181
+ */
182
+ export function getAppSpecFormatInstruction(): string {
183
+ return `
184
+ ${APP_SPEC_XML_FORMAT}
185
+
186
+ CRITICAL FORMATTING REQUIREMENTS:
187
+ - Do NOT use the Write, Edit, or Bash tools to create files - just OUTPUT the XML in your response
188
+ - Your ENTIRE response MUST be valid XML following the exact template structure above
189
+ - Do NOT use markdown formatting (no # headers, no **bold**, no - lists, etc.)
190
+ - Do NOT include any explanatory text, prefix, or suffix outside the XML tags
191
+ - Do NOT include phrases like "Based on my analysis...", "I'll create...", "Let me analyze..." before the XML
192
+ - Do NOT include any text before <project_specification> or after </project_specification>
193
+ - Your response must start IMMEDIATELY with <project_specification> with no preceding text
194
+ - Your response must end IMMEDIATELY with </project_specification> with no following text
195
+ - Use ONLY XML tags as shown in the template
196
+ - Properly escape XML special characters (&lt; for <, &gt; for >, &amp; for &)
197
+ - Maintain 2-space indentation for readability
198
+ - The output will be saved directly to app_spec.txt and must be parseable as valid XML
199
+ - The response must contain exactly ONE root XML element: <project_specification>
200
+ - Do not include code blocks, markdown fences, or any other formatting
201
+
202
+ VERIFICATION: Before responding, verify that:
203
+ 1. Your response starts with <project_specification> (no spaces, no text before it)
204
+ 2. Your response ends with </project_specification> (no spaces, no text after it)
205
+ 3. There is exactly one root XML element
206
+ 4. There is no explanatory text, analysis, or commentary outside the XML tags
207
+
208
+ Your response should be ONLY the XML content, nothing else.
209
+ `;
210
+ }