edsger 0.38.3 → 0.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/api/web-deploy.d.ts +60 -0
  2. package/dist/api/web-deploy.js +198 -0
  3. package/dist/phases/analyze-logs/index.js +1 -1
  4. package/dist/phases/analyze-logs/prompts.d.ts +1 -1
  5. package/dist/phases/analyze-logs/prompts.js +7 -39
  6. package/dist/phases/app-store-generation/__tests__/prompts.test.js +1 -44
  7. package/dist/phases/app-store-generation/index.js +1 -1
  8. package/dist/phases/app-store-generation/prompts.d.ts +1 -1
  9. package/dist/phases/app-store-generation/prompts.js +14 -79
  10. package/dist/phases/autonomous/index.js +1 -1
  11. package/dist/phases/autonomous/prompts.d.ts +1 -2
  12. package/dist/phases/autonomous/prompts.js +15 -58
  13. package/dist/phases/branch-planning/index.js +1 -1
  14. package/dist/phases/branch-planning/prompts.d.ts +1 -1
  15. package/dist/phases/branch-planning/prompts.js +15 -77
  16. package/dist/phases/bug-fixing/analyzer.js +2 -54
  17. package/dist/phases/bug-fixing/prompts.d.ts +1 -1
  18. package/dist/phases/bug-fixing/prompts.js +8 -62
  19. package/dist/phases/code-implementation/prompts.d.ts +1 -1
  20. package/dist/phases/code-implementation/prompts.js +12 -78
  21. package/dist/phases/code-implementation-verification/agent.d.ts +1 -1
  22. package/dist/phases/code-implementation-verification/agent.js +2 -2
  23. package/dist/phases/code-implementation-verification/prompts.d.ts +1 -2
  24. package/dist/phases/code-implementation-verification/prompts.js +12 -99
  25. package/dist/phases/code-refine/prompts.d.ts +1 -1
  26. package/dist/phases/code-refine/prompts.js +16 -89
  27. package/dist/phases/code-refine/refine-iteration.js +1 -1
  28. package/dist/phases/code-testing/analyzer.js +1 -1
  29. package/dist/phases/code-testing/prompts.d.ts +1 -1
  30. package/dist/phases/code-testing/prompts.js +10 -91
  31. package/dist/phases/feature-analysis/index.js +1 -1
  32. package/dist/phases/feature-analysis/prompts.d.ts +1 -1
  33. package/dist/phases/feature-analysis/prompts.js +8 -188
  34. package/dist/phases/feature-analysis-verification/agent.js +1 -1
  35. package/dist/phases/feature-analysis-verification/prompts.d.ts +1 -1
  36. package/dist/phases/feature-analysis-verification/prompts.js +10 -69
  37. package/dist/phases/functional-testing/prompts.d.ts +1 -2
  38. package/dist/phases/functional-testing/prompts.js +10 -78
  39. package/dist/phases/growth-analysis/index.js +1 -1
  40. package/dist/phases/growth-analysis/prompts.d.ts +1 -1
  41. package/dist/phases/growth-analysis/prompts.js +14 -143
  42. package/dist/phases/intelligence-analysis/__tests__/prompts.test.js +1 -73
  43. package/dist/phases/intelligence-analysis/agent.js +250 -18
  44. package/dist/phases/intelligence-analysis/index.js +11 -4
  45. package/dist/phases/intelligence-analysis/prompts.d.ts +1 -1
  46. package/dist/phases/intelligence-analysis/prompts.js +30 -116
  47. package/dist/phases/output-contracts.d.ts +7 -0
  48. package/dist/phases/output-contracts.js +824 -0
  49. package/dist/phases/pr-execution/index.js +2 -2
  50. package/dist/phases/pr-execution/prompts.d.ts +2 -2
  51. package/dist/phases/pr-execution/prompts.js +28 -122
  52. package/dist/phases/pr-splitting/index.js +1 -1
  53. package/dist/phases/pr-splitting/prompts.d.ts +1 -1
  54. package/dist/phases/pr-splitting/prompts.js +15 -91
  55. package/dist/phases/task/index.js +1 -1
  56. package/dist/phases/task/prompts.d.ts +1 -1
  57. package/dist/phases/task/prompts.js +8 -15
  58. package/dist/phases/technical-design/index.js +1 -1
  59. package/dist/phases/technical-design/prompts.d.ts +1 -1
  60. package/dist/phases/technical-design/prompts.js +17 -89
  61. package/dist/phases/technical-design-verification/agent.d.ts +1 -1
  62. package/dist/phases/technical-design-verification/agent.js +2 -2
  63. package/dist/phases/technical-design-verification/prompts.d.ts +1 -2
  64. package/dist/phases/technical-design-verification/prompts.js +12 -88
  65. package/dist/phases/test-cases-analysis/index.js +1 -1
  66. package/dist/phases/test-cases-analysis/prompts.d.ts +1 -1
  67. package/dist/phases/test-cases-analysis/prompts.js +8 -125
  68. package/dist/phases/user-stories-analysis/index.js +1 -1
  69. package/dist/phases/user-stories-analysis/prompts.d.ts +1 -1
  70. package/dist/phases/user-stories-analysis/prompts.js +10 -155
  71. package/dist/services/skill-resolver.d.ts +46 -0
  72. package/dist/services/skill-resolver.js +121 -0
  73. package/dist/skills/phase/analyze-logs/SKILL.md +24 -0
  74. package/dist/skills/phase/app-store-generation/SKILL.md +60 -0
  75. package/dist/skills/phase/autonomous/SKILL.md +52 -0
  76. package/dist/skills/phase/branch-planning/SKILL.md +55 -0
  77. package/dist/skills/phase/bug-fixing/SKILL.md +47 -0
  78. package/dist/skills/phase/code-implementation/SKILL.md +68 -0
  79. package/dist/skills/phase/code-implementation-verification/SKILL.md +76 -0
  80. package/dist/skills/phase/code-refine/SKILL.md +62 -0
  81. package/dist/skills/phase/code-testing/SKILL.md +78 -0
  82. package/dist/skills/phase/feature-analysis/SKILL.md +117 -0
  83. package/dist/skills/phase/feature-analysis-verification/SKILL.md +46 -0
  84. package/dist/skills/phase/functional-testing/SKILL.md +62 -0
  85. package/dist/skills/phase/growth-analysis/SKILL.md +97 -0
  86. package/dist/skills/phase/incremental-sync/SKILL.md +48 -0
  87. package/dist/skills/phase/intelligence-analysis/SKILL.md +52 -0
  88. package/dist/skills/phase/pr-execution/SKILL.md +53 -0
  89. package/dist/skills/phase/pr-splitting/SKILL.md +70 -0
  90. package/dist/skills/phase/task/SKILL.md +19 -0
  91. package/dist/skills/phase/technical-design/SKILL.md +75 -0
  92. package/dist/skills/phase/technical-design-verification/SKILL.md +43 -0
  93. package/dist/skills/phase/test-cases-analysis/SKILL.md +88 -0
  94. package/dist/skills/phase/user-stories-analysis/SKILL.md +118 -0
  95. package/package.json +2 -2
@@ -0,0 +1,60 @@
1
+ export interface WebDeployConfig {
2
+ id: string;
3
+ product_id: string;
4
+ platform: 'vercel' | 'netlify';
5
+ project_id: string | null;
6
+ project_name: string | null;
7
+ project_url: string | null;
8
+ framework: string | null;
9
+ repo_full_name: string | null;
10
+ has_credentials: boolean;
11
+ is_connected: boolean;
12
+ created_by: string;
13
+ created_at: string;
14
+ updated_at: string;
15
+ }
16
+ export interface VercelProject {
17
+ id: string;
18
+ name: string;
19
+ framework: string | null;
20
+ repo: string | null;
21
+ url: string | null;
22
+ }
23
+ export interface VercelDeployment {
24
+ id: string;
25
+ url: string | null;
26
+ state: 'READY' | 'BUILDING' | 'ERROR' | 'QUEUED' | 'CANCELED';
27
+ target: 'production' | null;
28
+ branch: string | null;
29
+ commit: string | null;
30
+ pr: string | null;
31
+ created_at: string;
32
+ ready_at: string | null;
33
+ }
34
+ export interface VercelEnvVar {
35
+ id: string;
36
+ key: string;
37
+ value: string;
38
+ target: string[];
39
+ type: string;
40
+ }
41
+ export declare function getWebDeployConfigs(productId: string, verbose?: boolean): Promise<WebDeployConfig[]>;
42
+ export declare function upsertWebDeployConfig(params: {
43
+ product_id: string;
44
+ platform: string;
45
+ credentials?: {
46
+ api_token: string;
47
+ };
48
+ }, verbose?: boolean): Promise<WebDeployConfig | null>;
49
+ export declare function deleteWebDeployConfig(configId: string, verbose?: boolean): Promise<void>;
50
+ export declare function connectWebDeploy(configId: string, verbose?: boolean): Promise<{
51
+ user: unknown;
52
+ connected: boolean;
53
+ } | null>;
54
+ export declare function listVercelProjects(configId: string, verbose?: boolean): Promise<VercelProject[]>;
55
+ export declare function createVercelProject(configId: string, name: string, repo: string, framework?: string, rootDirectory?: string, verbose?: boolean): Promise<VercelProject | null>;
56
+ export declare function linkVercelProject(configId: string, project: VercelProject, verbose?: boolean): Promise<WebDeployConfig | null>;
57
+ export declare function listDeployments(configId: string, limit?: number, verbose?: boolean): Promise<VercelDeployment[]>;
58
+ export declare function listEnvVars(configId: string, verbose?: boolean): Promise<VercelEnvVar[]>;
59
+ export declare function upsertEnvVar(configId: string, key: string, value: string, target: string[], verbose?: boolean): Promise<VercelEnvVar | null>;
60
+ export declare function deleteEnvVar(configId: string, envId: string, verbose?: boolean): Promise<void>;
@@ -0,0 +1,198 @@
1
+ import { logError, logInfo } from '../utils/logger.js';
2
+ import { callMcpEndpoint } from './mcp-client.js';
3
+ // =============================================================================
4
+ // Helpers
5
+ // =============================================================================
6
+ function parseMcpResult(result, fallback) {
7
+ const r = result;
8
+ const text = r.content?.[0]?.text;
9
+ if (!text) {
10
+ return fallback;
11
+ }
12
+ try {
13
+ return JSON.parse(text);
14
+ }
15
+ catch {
16
+ return fallback;
17
+ }
18
+ }
19
+ // =============================================================================
20
+ // Config CRUD
21
+ // =============================================================================
22
+ export async function getWebDeployConfigs(productId, verbose) {
23
+ if (verbose) {
24
+ logInfo(`Fetching web deploy configs for product: ${productId}`);
25
+ }
26
+ try {
27
+ const result = await callMcpEndpoint('web_deploy/configs/list', {
28
+ product_id: productId,
29
+ });
30
+ return parseMcpResult(result, []);
31
+ }
32
+ catch (error) {
33
+ if (verbose) {
34
+ logError(`Failed to fetch web deploy configs: ${error instanceof Error ? error.message : String(error)}`);
35
+ }
36
+ return [];
37
+ }
38
+ }
39
+ export async function upsertWebDeployConfig(params, verbose) {
40
+ if (verbose) {
41
+ logInfo(`Upserting web deploy config: ${params.platform}`);
42
+ }
43
+ try {
44
+ const result = await callMcpEndpoint('web_deploy/configs/upsert', params);
45
+ return parseMcpResult(result, null);
46
+ }
47
+ catch (error) {
48
+ logError(`Failed to upsert config: ${error instanceof Error ? error.message : String(error)}`);
49
+ return null;
50
+ }
51
+ }
52
+ export async function deleteWebDeployConfig(configId, verbose) {
53
+ if (verbose) {
54
+ logInfo(`Deleting web deploy config: ${configId}`);
55
+ }
56
+ await callMcpEndpoint('web_deploy/configs/delete', {
57
+ config_id: configId,
58
+ });
59
+ }
60
+ // =============================================================================
61
+ // Connect
62
+ // =============================================================================
63
+ export async function connectWebDeploy(configId, verbose) {
64
+ if (verbose) {
65
+ logInfo(`Validating web deploy connection: ${configId}`);
66
+ }
67
+ try {
68
+ const result = await callMcpEndpoint('web_deploy/connect', {
69
+ config_id: configId,
70
+ });
71
+ return parseMcpResult(result, null);
72
+ }
73
+ catch (error) {
74
+ logError(`Failed to connect: ${error instanceof Error ? error.message : String(error)}`);
75
+ return null;
76
+ }
77
+ }
78
+ // =============================================================================
79
+ // Projects
80
+ // =============================================================================
81
+ export async function listVercelProjects(configId, verbose) {
82
+ if (verbose) {
83
+ logInfo(`Listing Vercel projects for config: ${configId}`);
84
+ }
85
+ try {
86
+ const result = await callMcpEndpoint('web_deploy/projects/list', {
87
+ config_id: configId,
88
+ });
89
+ return parseMcpResult(result, []);
90
+ }
91
+ catch (error) {
92
+ logError(`Failed to list projects: ${error instanceof Error ? error.message : String(error)}`);
93
+ return [];
94
+ }
95
+ }
96
+ export async function createVercelProject(configId, name, repo, framework, rootDirectory, verbose) {
97
+ if (verbose) {
98
+ logInfo(`Creating Vercel project: ${name} → ${repo}`);
99
+ }
100
+ try {
101
+ const result = await callMcpEndpoint('web_deploy/projects/create', {
102
+ config_id: configId,
103
+ name,
104
+ repo,
105
+ framework,
106
+ root_directory: rootDirectory,
107
+ });
108
+ return parseMcpResult(result, null);
109
+ }
110
+ catch (error) {
111
+ logError(`Failed to create project: ${error instanceof Error ? error.message : String(error)}`);
112
+ return null;
113
+ }
114
+ }
115
+ export async function linkVercelProject(configId, project, verbose) {
116
+ if (verbose) {
117
+ logInfo(`Linking Vercel project: ${project.name}`);
118
+ }
119
+ try {
120
+ const result = await callMcpEndpoint('web_deploy/projects/link', {
121
+ config_id: configId,
122
+ project_id: project.id,
123
+ project_name: project.name,
124
+ project_url: project.url,
125
+ framework: project.framework,
126
+ repo_full_name: project.repo,
127
+ });
128
+ return parseMcpResult(result, null);
129
+ }
130
+ catch (error) {
131
+ logError(`Failed to link project: ${error instanceof Error ? error.message : String(error)}`);
132
+ return null;
133
+ }
134
+ }
135
+ // =============================================================================
136
+ // Deployments
137
+ // =============================================================================
138
+ export async function listDeployments(configId, limit, verbose) {
139
+ if (verbose) {
140
+ logInfo(`Listing deployments for config: ${configId}`);
141
+ }
142
+ try {
143
+ const result = await callMcpEndpoint('web_deploy/deployments/list', {
144
+ config_id: configId,
145
+ limit,
146
+ });
147
+ return parseMcpResult(result, []);
148
+ }
149
+ catch (error) {
150
+ logError(`Failed to list deployments: ${error instanceof Error ? error.message : String(error)}`);
151
+ return [];
152
+ }
153
+ }
154
+ // =============================================================================
155
+ // Environment Variables
156
+ // =============================================================================
157
+ export async function listEnvVars(configId, verbose) {
158
+ if (verbose) {
159
+ logInfo(`Listing env vars for config: ${configId}`);
160
+ }
161
+ try {
162
+ const result = await callMcpEndpoint('web_deploy/env/list', {
163
+ config_id: configId,
164
+ });
165
+ return parseMcpResult(result, []);
166
+ }
167
+ catch (error) {
168
+ logError(`Failed to list env vars: ${error instanceof Error ? error.message : String(error)}`);
169
+ return [];
170
+ }
171
+ }
172
+ export async function upsertEnvVar(configId, key, value, target, verbose) {
173
+ if (verbose) {
174
+ logInfo(`Upserting env var: ${key}`);
175
+ }
176
+ try {
177
+ const result = await callMcpEndpoint('web_deploy/env/upsert', {
178
+ config_id: configId,
179
+ key,
180
+ value,
181
+ target,
182
+ });
183
+ return parseMcpResult(result, null);
184
+ }
185
+ catch (error) {
186
+ logError(`Failed to upsert env var: ${error instanceof Error ? error.message : String(error)}`);
187
+ return null;
188
+ }
189
+ }
190
+ export async function deleteEnvVar(configId, envId, verbose) {
191
+ if (verbose) {
192
+ logInfo(`Deleting env var: ${envId}`);
193
+ }
194
+ await callMcpEndpoint('web_deploy/env/delete', {
195
+ config_id: configId,
196
+ env_id: envId,
197
+ });
198
+ }
@@ -57,7 +57,7 @@ export async function analyzeLogs(options) {
57
57
  };
58
58
  }
59
59
  logInfo(`${readyGroups.length} group(s) ready for analysis (inactive >1 hour)`);
60
- const systemPrompt = createAnalyzeLogsSystemPrompt();
60
+ const systemPrompt = await createAnalyzeLogsSystemPrompt();
61
61
  let totalFeedbacks = 0;
62
62
  let totalLogs = 0;
63
63
  // 4. Process each user group
@@ -1,3 +1,3 @@
1
1
  import { type ProductLog } from '../../services/product-logs.js';
2
- export declare function createAnalyzeLogsSystemPrompt(): string;
2
+ export declare function createAnalyzeLogsSystemPrompt(projectDir?: string): Promise<string>;
3
3
  export declare function createAnalyzeLogsUserPrompt(productName: string, userId: string | null, logs: ProductLog[]): string;
@@ -1,43 +1,11 @@
1
- export function createAnalyzeLogsSystemPrompt() {
2
- return `You are a product analyst AI. You analyze user behavior logs from a product to identify issues, pain points, and improvement opportunities.
3
-
4
- Your job is to:
5
- 1. Read through the user's interaction logs carefully
6
- 2. Identify patterns that suggest problems (errors, repeated actions, abandoned flows, confusion)
7
- 3. Identify opportunities for product improvement
8
- 4. Generate actionable feedback items that the product team can act on
9
-
10
- For each issue or improvement you find, output a structured feedback item.
11
-
12
- IMPORTANT RULES:
13
- - Only report genuine issues or meaningful improvements, not noise
14
- - Be specific about what happened and what should change
15
- - Prioritize by impact: bugs > usability issues > minor improvements
16
- - If the logs show normal, successful usage with no issues, say so and return an empty array
17
- - Do NOT fabricate issues that aren't supported by the log data
18
-
19
- Return your analysis as JSON in this exact format:
20
- \`\`\`json
21
- {
22
- "summary": "Brief summary of what the user did and any issues found",
23
- "feedbacks": [
24
- {
25
- "category": "bug|feature_request|improvement|question|other",
26
- "title": "Short descriptive title (max 200 chars)",
27
- "description": "Detailed description of the issue or suggestion (max 5000 chars)",
28
- "priority": "low|medium|high|critical"
1
+ import { resolveSkill } from '../../services/skill-resolver.js';
2
+ import { OUTPUT_CONTRACTS } from '../output-contracts.js';
3
+ export async function createAnalyzeLogsSystemPrompt(projectDir) {
4
+ const skill = await resolveSkill('phase/analyze-logs', { projectDir });
5
+ if (!skill) {
6
+ throw new Error('Failed to load skill: phase/analyze-logs');
29
7
  }
30
- ]
31
- }
32
- \`\`\`
33
-
34
- If no issues are found, return:
35
- \`\`\`json
36
- {
37
- "summary": "User session appears normal with no issues detected",
38
- "feedbacks": []
39
- }
40
- \`\`\``;
8
+ return `${skill.prompt}\n\n${OUTPUT_CONTRACTS['analyze-logs']}`;
41
9
  }
42
10
  export function createAnalyzeLogsUserPrompt(productName, userId, logs) {
43
11
  const logsText = logs
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import assert from 'node:assert';
5
5
  import { describe, it } from 'node:test';
6
- import { createAppStorePromptWithContext, createAppStoreSystemPrompt, STORE_SCREENSHOT_SIZES, } from '../prompts.js';
6
+ import { createAppStorePromptWithContext, STORE_SCREENSHOT_SIZES, } from '../prompts.js';
7
7
  // ============================================================
8
8
  // STORE_SCREENSHOT_SIZES
9
9
  // ============================================================
@@ -67,49 +67,6 @@ void describe('STORE_SCREENSHOT_SIZES', () => {
67
67
  });
68
68
  });
69
69
  // ============================================================
70
- // createAppStoreSystemPrompt
71
- // ============================================================
72
- void describe('createAppStoreSystemPrompt', () => {
73
- void it('should return a string containing ASO reference', () => {
74
- const result = createAppStoreSystemPrompt();
75
- const lower = result.toLowerCase();
76
- assert.ok(lower.includes('aso') || lower.includes('app store optimization'), 'System prompt should mention ASO or app store optimization');
77
- });
78
- void it('should contain NO PLACEHOLDERS rule', () => {
79
- const result = createAppStoreSystemPrompt();
80
- assert.ok(result.includes('NO PLACEHOLDERS'), 'System prompt should contain "NO PLACEHOLDERS" rule');
81
- });
82
- void it('should contain JSON format specification with app_store key', () => {
83
- const result = createAppStoreSystemPrompt();
84
- assert.ok(result.includes('"app_store"'), 'System prompt should contain "app_store" in JSON format spec');
85
- });
86
- void it('should include codebase exploration when hasCodebase=true', () => {
87
- const result = createAppStoreSystemPrompt(true);
88
- assert.ok(result.includes('Explore the Codebase'), 'System prompt with hasCodebase=true should include "Explore the Codebase"');
89
- });
90
- void it('should NOT include codebase exploration when hasCodebase=false (default)', () => {
91
- const result = createAppStoreSystemPrompt();
92
- assert.ok(!result.includes('Explore the Codebase'), 'System prompt with hasCodebase=false should NOT include "Explore the Codebase"');
93
- });
94
- void it('should also NOT include codebase exploration when explicitly passed false', () => {
95
- const result = createAppStoreSystemPrompt(false);
96
- assert.ok(!result.includes('Explore the Codebase'), 'System prompt with hasCodebase=false should NOT include "Explore the Codebase"');
97
- });
98
- void it('should contain character limit requirements', () => {
99
- const result = createAppStoreSystemPrompt();
100
- assert.ok(result.includes('30 characters'), 'Should mention 30 character limit for app name');
101
- assert.ok(result.includes('80 characters'), 'Should mention 80 character limit for short description');
102
- assert.ok(result.includes('4000 characters'), 'Should mention 4000 character limit for description');
103
- assert.ok(result.includes('100 characters'), 'Should mention 100 character limit for keywords');
104
- });
105
- void it('should contain screenshot design standards', () => {
106
- const result = createAppStoreSystemPrompt();
107
- assert.ok(result.includes('Screenshot Design Standards'), 'Should contain screenshot design standards section');
108
- assert.ok(result.includes('gradient'), 'Should mention gradient backgrounds');
109
- assert.ok(result.includes('headline'), 'Should mention headline text');
110
- });
111
- });
112
- // ============================================================
113
70
  // createAppStorePromptWithContext
114
71
  // ============================================================
115
72
  void describe('createAppStorePromptWithContext', () => {
@@ -53,7 +53,7 @@ export const generateAppStoreAssets = async (options, config
53
53
  logInfo(`Repository cloned to: ${repoCwd}`);
54
54
  // Prepare context and prompt
55
55
  const { context, prompt: analysisPrompt } = await prepareAppStoreContext(productId, targetStore, locale, verbose, true);
56
- const systemPrompt = createAppStoreSystemPrompt(true);
56
+ const systemPrompt = await createAppStoreSystemPrompt(true);
57
57
  logInfo('Starting AI generation for app store assets...');
58
58
  const aiResult = await executeAppStoreQuery(analysisPrompt, systemPrompt, config, verbose, repoCwd);
59
59
  if (!aiResult) {
@@ -39,5 +39,5 @@ export declare const STORE_SCREENSHOT_SIZES: {
39
39
  };
40
40
  export type StoreType = 'apple' | 'google';
41
41
  export type DeviceSize = string;
42
- export declare function createAppStoreSystemPrompt(hasCodebase?: boolean): string;
42
+ export declare const createAppStoreSystemPrompt: (hasCodebase?: boolean, projectDir?: string) => Promise<string>;
43
43
  export declare function createAppStorePromptWithContext(productId: string, contextInfo: string, targetStore: 'apple' | 'google' | 'all', locale: string, hasCodebase?: boolean): string;
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * AI prompts for app store screenshot and listing content generation.
3
3
  */
4
+ import { processConditionals, resolveSkill, } from '../../services/skill-resolver.js';
5
+ import { OUTPUT_CONTRACTS } from '../output-contracts.js';
4
6
  export const STORE_SCREENSHOT_SIZES = {
5
7
  apple: {
6
8
  iphone_6_7: { width: 1290, height: 2796, label: 'iPhone 6.7"' },
@@ -13,86 +15,19 @@ export const STORE_SCREENSHOT_SIZES = {
13
15
  tablet_10: { width: 1920, height: 1200, label: '10" Tablet' },
14
16
  },
15
17
  };
16
- export function createAppStoreSystemPrompt(hasCodebase = false) {
17
- return `You are an expert app store optimization (ASO) specialist and UI/UX designer. Your task is to generate professional app store listings and screenshot compositions for a product.
18
+ export const createAppStoreSystemPrompt = async (hasCodebase = false, projectDir) => {
19
+ const skill = await resolveSkill('phase/app-store-generation', { projectDir });
20
+ if (!skill) {
21
+ throw new Error('Failed to load skill: phase/app-store-generation');
22
+ }
23
+ let { prompt } = skill;
24
+ prompt = processConditionals(prompt, {
25
+ hasCodebase,
26
+ });
27
+ return `${prompt}
18
28
 
19
- **Your Role**: Create compelling store listings and visually stunning screenshot HTML templates that showcase the product's key features with realistic mock data, professional text overlays, and gradient backgrounds.
20
-
21
- **Analysis Process**:${hasCodebase
22
- ? `
23
- 1. **Explore the Codebase**: Use your tools to read README, CLAUDE.md, package.json, landing pages, and key source files to deeply understand the product.
24
- 2. **Understand the Product**: Build a complete picture of features, UX flows, and value proposition.`
25
- : `
26
- 1. **Understand the Product**: Analyze the product from the provided context.`}
27
- ${hasCodebase ? '3' : '2'}. **Identify Key Features**: Pick 5-8 standout features to highlight in screenshots.
28
- ${hasCodebase ? '4' : '3'}. **Create Screenshot Compositions**: Design each as a complete HTML page with gradient background, headline text overlay, and a device-framed mock app UI.
29
- ${hasCodebase ? '5' : '4'}. **Write Store Listings**: Generate optimized app name, subtitle, description, and keywords.
30
-
31
- **Screenshot Design Standards**:
32
- - Each screenshot must tell a story about a specific feature
33
- - Professional gradient backgrounds (not flat colors)
34
- - Bold headline text (2-5 words) at top or bottom, large and readable
35
- - Optional subheadline with supporting detail
36
- - The "app mock" area should show realistic UI with mock data (real-looking names, numbers, dates)
37
- - Modern CSS: flexbox, grid, gradients, shadows, rounded corners
38
- - Text must be legible at all display sizes
39
- - Each HTML template is a complete self-contained page with inline CSS
40
- - The template renders at exact store-required dimensions
41
-
42
- **Store Listing Standards**:
43
- - App name: max 30 characters, compelling and searchable
44
- - Subtitle: max 30 characters (Apple), punchy value proposition
45
- - Promotional text: max 170 characters (Apple), highlights current promotions or features — can be updated without a new app version
46
- - Short description: max 80 characters (Google Play)
47
- - Description: max 4000 characters, benefit-focused with feature bullets
48
- - Keywords: max 100 characters (Apple), comma-separated, no spaces after commas
49
- - What's New: concise release notes highlighting latest improvements
50
-
51
- **CRITICAL - NO PLACEHOLDERS**: All content must be fully written using real product details. Never use brackets like [Feature] or [App Name].
52
-
53
- **CRITICAL - Result Format**:
54
- Return ONLY a JSON object. No text before or after.
55
-
56
- \`\`\`json
57
- {
58
- "app_store": {
59
- "listings": {
60
- "en-US": {
61
- "app_name": "Product Name",
62
- "subtitle": "Short value proposition",
63
- "promotional_text": "Highlight a current promotion, new feature, or seasonal message (170 chars max)",
64
- "short_description": "One-liner for Google Play (80 chars max)",
65
- "description": "Full store description with features and benefits",
66
- "keywords": "keyword1,keyword2,keyword3",
67
- "whats_new": "Latest improvements and fixes",
68
- "primary_category": "Category",
69
- "secondary_category": "Category"
70
- }
71
- },
72
- "screenshots": [
73
- {
74
- "feature_highlight": "Feature being showcased",
75
- "headline": "Bold 2-5 Word Headline",
76
- "subheadline": "Supporting detail line (optional)",
77
- "background_gradient": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
78
- "text_color": "#ffffff",
79
- "device_frame": "iphone|ipad|browser|macbook",
80
- "html_template": "<html>...(complete self-contained HTML page showing the app mock with realistic data)...</html>"
81
- }
82
- ]
83
- }
84
- }
85
- \`\`\`
86
-
87
- **Screenshot HTML Template Guidelines**:
88
- - Each template should render the mock app UI (NOT the store composition — composition is handled separately)
89
- - Include realistic mock data that demonstrates the feature
90
- - Use modern, clean design matching current app design trends
91
- - Mobile screenshots: design for portrait orientation
92
- - Tablet/desktop screenshots: design for the appropriate orientation
93
- - Set appropriate viewport meta tags for the target device size
94
- - The HTML renders the "screen content" — it will be wrapped in device frame + background + text overlay automatically`;
95
- }
29
+ ${OUTPUT_CONTRACTS['app-store-generation']}`;
30
+ };
96
31
  export function createAppStorePromptWithContext(productId, contextInfo, targetStore, locale, hasCodebase = false) {
97
32
  const googleOrBothRequirements = targetStore === 'google'
98
33
  ? 'Google Play Store only'
@@ -56,7 +56,7 @@ async function* prompt(userPrompt) {
56
56
  * Run a single autonomous iteration using Claude Code SDK
57
57
  */
58
58
  async function runIteration(featureId, featureDescription, config, verbose) {
59
- const systemPrompt = createAutonomousSystemPrompt(config, featureId);
59
+ const systemPrompt = await createAutonomousSystemPrompt(featureId);
60
60
  const userPromptText = createAutonomousUserPrompt(featureDescription);
61
61
  let lastAssistantResponse = '';
62
62
  for await (const message of query({
@@ -1,6 +1,5 @@
1
1
  /**
2
2
  * Prompts for the autonomous development phase
3
3
  */
4
- import { type EdsgerConfig } from '../../types/index.js';
5
- export declare function createAutonomousSystemPrompt(_config: EdsgerConfig, featureId: string): string;
4
+ export declare const createAutonomousSystemPrompt: (featureId: string, projectDir?: string) => Promise<string>;
6
5
  export declare function createAutonomousUserPrompt(featureDescription: string): string;
@@ -1,64 +1,21 @@
1
1
  /**
2
2
  * Prompts for the autonomous development phase
3
3
  */
4
- export function createAutonomousSystemPrompt(_config, featureId) {
5
- return `You are an autonomous developer working toward a specific objective. Your role is to analyze the current state of the codebase, decide the next most valuable step toward the objective, implement it, and commit your changes.
6
-
7
- **Your Role**: Analyze the codebase, identify the next actionable improvement, implement it, and commit.
8
-
9
- **Available Tools**:
10
- - Bash: Git operations, running commands, tests, and builds
11
- - Glob: Find files and understand project structure
12
- - Read: Examine existing code, configuration, and documentation files
13
- - Edit: Modify existing files
14
- - Write: Create new files
15
- - TodoWrite: Track implementation tasks
16
-
17
- **WORKFLOW - Follow these steps**:
18
-
19
- 1. **ANALYZE**: Use Glob and Read to understand the current state of the code
20
- 2. **DECIDE**: Based on the objective, determine the single most impactful next step
21
- 3. **IMPLEMENT**: Make the changes using Edit/Write tools
22
- 4. **TEST**: Run relevant tests or builds to verify your changes work
23
- 5. **COMMIT**: Commit your changes with a conventional commit message (feat:, fix:, refactor:, docs:, test:, chore:)
24
-
25
- **Types of work you may do**:
26
- - Implement new feature code toward the objective
27
- - Fix bugs discovered during analysis
28
- - Refactor code to improve quality or maintainability
29
- - Add or improve tests
30
- - Update documentation
31
- - Improve error handling or validation
32
-
33
- **Important Rules**:
34
- 1. You are already on the correct branch - do NOT create or switch branches
35
- 2. Focus on ONE coherent change per iteration
36
- 3. Use conventional commit messages that describe what and why
37
- 4. Follow existing code patterns and conventions in the repository
38
- 5. Ensure proper TypeScript types and interfaces
39
- 6. Add appropriate error handling and validation
40
- 7. Handle pre-commit hooks properly:
41
- - If lint-staged fails: Fix formatting and linting issues, then retry commit
42
- - If AI code review fails: Use SKIP_REVIEW=1 git commit -m "message"
43
- - Last resort: git commit --no-verify -m "message"
44
-
45
- **CRITICAL - Result Format**:
46
- You MUST end your response with a JSON object in this EXACT format:
47
-
48
- \`\`\`json
49
- {
50
- "autonomous_result": {
51
- "feature_id": "${featureId}",
52
- "task_type": "feature|bugfix|refactor|test|docs|chore",
53
- "summary": "Brief description of what was done",
54
- "files_modified": ["file1.ts", "file2.tsx"],
55
- "commit_hash": "abc123..."
56
- }
57
- }
58
- \`\`\`
59
-
60
- Remember: Focus on making real, meaningful progress toward the objective. Quality over quantity.`;
61
- }
4
+ import { resolveSkill, substituteVariables, } from '../../services/skill-resolver.js';
5
+ import { OUTPUT_CONTRACTS } from '../output-contracts.js';
6
+ export const createAutonomousSystemPrompt = async (featureId, projectDir) => {
7
+ const skill = await resolveSkill('phase/autonomous', {
8
+ projectDir,
9
+ });
10
+ if (!skill) {
11
+ throw new Error('Failed to load skill: phase/autonomous');
12
+ }
13
+ let { prompt } = skill;
14
+ prompt = substituteVariables(prompt, { FEATURE_ID: featureId });
15
+ return `${prompt}
16
+
17
+ ${OUTPUT_CONTRACTS['autonomous']}`;
18
+ };
62
19
  export function createAutonomousUserPrompt(featureDescription) {
63
20
  return `## Objective
64
21
 
@@ -170,7 +170,7 @@ export const planFeatureBranches = async (options, config
170
170
  // Build the user prompt based on mode
171
171
  const contextInfo = formatContextForPrompt(context.feature, context.product, context.user_stories, context.test_cases);
172
172
  const existingBranchesInfo = formatExistingBranchesForPrompt(context.existing_branches);
173
- const systemPrompt = createBranchPlanningSystemPrompt(config, featureId);
173
+ const systemPrompt = await createBranchPlanningSystemPrompt(config, featureId);
174
174
  const userPrompt = await buildUserPrompt({
175
175
  isIncrementalUpdate,
176
176
  feedbacksContext,
@@ -2,7 +2,7 @@ import { type EdsgerConfig } from '../../types/index.js';
2
2
  /**
3
3
  * Create the system prompt for branch planning
4
4
  */
5
- export declare function createBranchPlanningSystemPrompt(config: EdsgerConfig, featureId: string): string;
5
+ export declare function createBranchPlanningSystemPrompt(config: EdsgerConfig, featureId: string, projectDir?: string): Promise<string>;
6
6
  /**
7
7
  * Create the user prompt with context for branch planning
8
8
  */