popeye-cli 1.4.7 → 1.6.0
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.
- package/CHANGELOG.md +54 -0
- package/README.md +264 -63
- package/dist/adapters/gemini.d.ts +1 -0
- package/dist/adapters/gemini.d.ts.map +1 -1
- package/dist/adapters/gemini.js +9 -4
- package/dist/adapters/gemini.js.map +1 -1
- package/dist/adapters/grok.d.ts +1 -0
- package/dist/adapters/grok.d.ts.map +1 -1
- package/dist/adapters/grok.js +9 -4
- package/dist/adapters/grok.js.map +1 -1
- package/dist/adapters/openai.d.ts +1 -1
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +35 -9
- package/dist/adapters/openai.js.map +1 -1
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +54 -4
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/interactive.d.ts +29 -0
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +132 -7
- package/dist/cli/interactive.js.map +1 -1
- package/dist/generators/all.d.ts +8 -2
- package/dist/generators/all.d.ts.map +1 -1
- package/dist/generators/all.js +37 -316
- package/dist/generators/all.js.map +1 -1
- package/dist/generators/doc-parser.d.ts +64 -0
- package/dist/generators/doc-parser.d.ts.map +1 -0
- package/dist/generators/doc-parser.js +407 -0
- package/dist/generators/doc-parser.js.map +1 -0
- package/dist/generators/frontend-design-analyzer.d.ts +30 -0
- package/dist/generators/frontend-design-analyzer.d.ts.map +1 -0
- package/dist/generators/frontend-design-analyzer.js +208 -0
- package/dist/generators/frontend-design-analyzer.js.map +1 -0
- package/dist/generators/shared-packages.d.ts +45 -0
- package/dist/generators/shared-packages.d.ts.map +1 -0
- package/dist/generators/shared-packages.js +456 -0
- package/dist/generators/shared-packages.js.map +1 -0
- package/dist/generators/templates/index.d.ts +8 -0
- package/dist/generators/templates/index.d.ts.map +1 -1
- package/dist/generators/templates/index.js +8 -0
- package/dist/generators/templates/index.js.map +1 -1
- package/dist/generators/templates/website-components.d.ts +33 -0
- package/dist/generators/templates/website-components.d.ts.map +1 -0
- package/dist/generators/templates/website-components.js +303 -0
- package/dist/generators/templates/website-components.js.map +1 -0
- package/dist/generators/templates/website-config.d.ts +55 -0
- package/dist/generators/templates/website-config.d.ts.map +1 -0
- package/dist/generators/templates/website-config.js +425 -0
- package/dist/generators/templates/website-config.js.map +1 -0
- package/dist/generators/templates/website-conversion.d.ts +27 -0
- package/dist/generators/templates/website-conversion.d.ts.map +1 -0
- package/dist/generators/templates/website-conversion.js +326 -0
- package/dist/generators/templates/website-conversion.js.map +1 -0
- package/dist/generators/templates/website-landing.d.ts +24 -0
- package/dist/generators/templates/website-landing.d.ts.map +1 -0
- package/dist/generators/templates/website-landing.js +276 -0
- package/dist/generators/templates/website-landing.js.map +1 -0
- package/dist/generators/templates/website-layout.d.ts +42 -0
- package/dist/generators/templates/website-layout.d.ts.map +1 -0
- package/dist/generators/templates/website-layout.js +408 -0
- package/dist/generators/templates/website-layout.js.map +1 -0
- package/dist/generators/templates/website-pricing.d.ts +11 -0
- package/dist/generators/templates/website-pricing.d.ts.map +1 -0
- package/dist/generators/templates/website-pricing.js +313 -0
- package/dist/generators/templates/website-pricing.js.map +1 -0
- package/dist/generators/templates/website-sections.d.ts +102 -0
- package/dist/generators/templates/website-sections.d.ts.map +1 -0
- package/dist/generators/templates/website-sections.js +444 -0
- package/dist/generators/templates/website-sections.js.map +1 -0
- package/dist/generators/templates/website-seo.d.ts +76 -0
- package/dist/generators/templates/website-seo.d.ts.map +1 -0
- package/dist/generators/templates/website-seo.js +326 -0
- package/dist/generators/templates/website-seo.js.map +1 -0
- package/dist/generators/templates/website.d.ts +10 -83
- package/dist/generators/templates/website.d.ts.map +1 -1
- package/dist/generators/templates/website.js +12 -875
- package/dist/generators/templates/website.js.map +1 -1
- package/dist/generators/website-content-scanner.d.ts +37 -0
- package/dist/generators/website-content-scanner.d.ts.map +1 -0
- package/dist/generators/website-content-scanner.js +165 -0
- package/dist/generators/website-content-scanner.js.map +1 -0
- package/dist/generators/website-context.d.ts +119 -0
- package/dist/generators/website-context.d.ts.map +1 -0
- package/dist/generators/website-context.js +350 -0
- package/dist/generators/website-context.js.map +1 -0
- package/dist/generators/website-debug.d.ts +68 -0
- package/dist/generators/website-debug.d.ts.map +1 -0
- package/dist/generators/website-debug.js +93 -0
- package/dist/generators/website-debug.js.map +1 -0
- package/dist/generators/website.d.ts +5 -0
- package/dist/generators/website.d.ts.map +1 -1
- package/dist/generators/website.js +136 -11
- package/dist/generators/website.js.map +1 -1
- package/dist/generators/workspace-root.d.ts +27 -0
- package/dist/generators/workspace-root.d.ts.map +1 -0
- package/dist/generators/workspace-root.js +100 -0
- package/dist/generators/workspace-root.js.map +1 -0
- package/dist/state/index.d.ts +35 -0
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +40 -0
- package/dist/state/index.js.map +1 -1
- package/dist/types/consensus.d.ts +3 -0
- package/dist/types/consensus.d.ts.map +1 -1
- package/dist/types/consensus.js +1 -0
- package/dist/types/consensus.js.map +1 -1
- package/dist/types/website-strategy.d.ts +263 -0
- package/dist/types/website-strategy.d.ts.map +1 -0
- package/dist/types/website-strategy.js +105 -0
- package/dist/types/website-strategy.js.map +1 -0
- package/dist/types/workflow.d.ts +21 -0
- package/dist/types/workflow.d.ts.map +1 -1
- package/dist/types/workflow.js +8 -0
- package/dist/types/workflow.js.map +1 -1
- package/dist/upgrade/handlers.d.ts +15 -0
- package/dist/upgrade/handlers.d.ts.map +1 -1
- package/dist/upgrade/handlers.js +52 -0
- package/dist/upgrade/handlers.js.map +1 -1
- package/dist/workflow/auto-fix-bundler.d.ts +37 -0
- package/dist/workflow/auto-fix-bundler.d.ts.map +1 -0
- package/dist/workflow/auto-fix-bundler.js +320 -0
- package/dist/workflow/auto-fix-bundler.js.map +1 -0
- package/dist/workflow/auto-fix.d.ts.map +1 -1
- package/dist/workflow/auto-fix.js +10 -3
- package/dist/workflow/auto-fix.js.map +1 -1
- package/dist/workflow/consensus.d.ts.map +1 -1
- package/dist/workflow/consensus.js +2 -0
- package/dist/workflow/consensus.js.map +1 -1
- package/dist/workflow/execution-mode.d.ts.map +1 -1
- package/dist/workflow/execution-mode.js +18 -0
- package/dist/workflow/execution-mode.js.map +1 -1
- package/dist/workflow/index.d.ts +4 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +37 -0
- package/dist/workflow/index.js.map +1 -1
- package/dist/workflow/overview.d.ts +89 -0
- package/dist/workflow/overview.d.ts.map +1 -0
- package/dist/workflow/overview.js +358 -0
- package/dist/workflow/overview.js.map +1 -0
- package/dist/workflow/plan-mode.d.ts +6 -4
- package/dist/workflow/plan-mode.d.ts.map +1 -1
- package/dist/workflow/plan-mode.js +148 -6
- package/dist/workflow/plan-mode.js.map +1 -1
- package/dist/workflow/website-strategy.d.ts +79 -0
- package/dist/workflow/website-strategy.d.ts.map +1 -0
- package/dist/workflow/website-strategy.js +310 -0
- package/dist/workflow/website-strategy.js.map +1 -0
- package/dist/workflow/website-updater.d.ts +17 -0
- package/dist/workflow/website-updater.d.ts.map +1 -0
- package/dist/workflow/website-updater.js +116 -0
- package/dist/workflow/website-updater.js.map +1 -0
- package/dist/workflow/workflow-logger.d.ts +1 -1
- package/dist/workflow/workflow-logger.d.ts.map +1 -1
- package/dist/workflow/workflow-logger.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/gemini.ts +10 -4
- package/src/adapters/grok.ts +10 -4
- package/src/adapters/openai.ts +38 -6
- package/src/cli/commands/create.ts +58 -4
- package/src/cli/interactive.ts +143 -7
- package/src/generators/all.ts +49 -332
- package/src/generators/doc-parser.ts +449 -0
- package/src/generators/frontend-design-analyzer.ts +261 -0
- package/src/generators/shared-packages.ts +500 -0
- package/src/generators/templates/index.ts +8 -0
- package/src/generators/templates/website-components.ts +330 -0
- package/src/generators/templates/website-config.ts +444 -0
- package/src/generators/templates/website-conversion.ts +341 -0
- package/src/generators/templates/website-landing.ts +331 -0
- package/src/generators/templates/website-layout.ts +443 -0
- package/src/generators/templates/website-pricing.ts +330 -0
- package/src/generators/templates/website-sections.ts +541 -0
- package/src/generators/templates/website-seo.ts +370 -0
- package/src/generators/templates/website.ts +38 -905
- package/src/generators/website-content-scanner.ts +208 -0
- package/src/generators/website-context.ts +493 -0
- package/src/generators/website-debug.ts +130 -0
- package/src/generators/website.ts +178 -20
- package/src/generators/workspace-root.ts +113 -0
- package/src/state/index.ts +56 -0
- package/src/types/consensus.ts +3 -0
- package/src/types/website-strategy.ts +243 -0
- package/src/types/workflow.ts +21 -0
- package/src/upgrade/handlers.ts +65 -0
- package/src/workflow/auto-fix-bundler.ts +392 -0
- package/src/workflow/auto-fix.ts +11 -3
- package/src/workflow/consensus.ts +2 -0
- package/src/workflow/execution-mode.ts +21 -0
- package/src/workflow/index.ts +37 -0
- package/src/workflow/overview.ts +475 -0
- package/src/workflow/plan-mode.ts +193 -8
- package/src/workflow/website-strategy.ts +379 -0
- package/src/workflow/website-updater.ts +142 -0
- package/src/workflow/workflow-logger.ts +1 -0
- package/tests/adapters/persona-switching.test.ts +63 -0
- package/tests/cli/project-naming.test.ts +136 -0
- package/tests/generators/doc-parser.test.ts +121 -0
- package/tests/generators/frontend-design-analyzer.test.ts +90 -0
- package/tests/generators/quality-gate.test.ts +183 -0
- package/tests/generators/shared-packages.test.ts +83 -0
- package/tests/generators/website-components.test.ts +159 -0
- package/tests/generators/website-config.test.ts +84 -0
- package/tests/generators/website-content-scanner.test.ts +181 -0
- package/tests/generators/website-context.test.ts +331 -0
- package/tests/generators/website-debug.test.ts +77 -0
- package/tests/generators/website-landing.test.ts +188 -0
- package/tests/generators/website-pricing.test.ts +98 -0
- package/tests/generators/website-sections.test.ts +245 -0
- package/tests/generators/website-seo-quality.test.ts +246 -0
- package/tests/generators/workspace-root.test.ts +105 -0
- package/tests/upgrade/handlers.test.ts +162 -0
- package/tests/workflow/auto-fix-bundler.test.ts +242 -0
- package/tests/workflow/overview.test.ts +392 -0
- package/tests/workflow/plan-mode.test.ts +111 -1
- package/tests/workflow/website-strategy.test.ts +246 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Website strategy type definitions
|
|
3
|
+
* Defines the strategic marketing document, site architecture,
|
|
4
|
+
* design tokens, and brand assets contract for website generation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Navigation item for site header/footer
|
|
11
|
+
*/
|
|
12
|
+
export interface NavItem {
|
|
13
|
+
label: string;
|
|
14
|
+
href: string;
|
|
15
|
+
children?: NavItem[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Footer section with links
|
|
20
|
+
*/
|
|
21
|
+
export interface FooterSection {
|
|
22
|
+
title: string;
|
|
23
|
+
links: Array<{ label: string; href: string }>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Page definition in site architecture
|
|
28
|
+
*/
|
|
29
|
+
export interface SiteArchitecturePage {
|
|
30
|
+
path: string;
|
|
31
|
+
title: string;
|
|
32
|
+
purpose: string;
|
|
33
|
+
pageType:
|
|
34
|
+
| 'landing'
|
|
35
|
+
| 'pricing'
|
|
36
|
+
| 'solution'
|
|
37
|
+
| 'use-cases'
|
|
38
|
+
| 'about'
|
|
39
|
+
| 'contact'
|
|
40
|
+
| 'blog'
|
|
41
|
+
| 'docs'
|
|
42
|
+
| 'legal';
|
|
43
|
+
sections: string[];
|
|
44
|
+
seoKeywords: string[];
|
|
45
|
+
conversionGoal: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Complete website strategy document
|
|
50
|
+
* Generated by AI from product context, user docs, and market inputs
|
|
51
|
+
*/
|
|
52
|
+
export interface WebsiteStrategyDocument {
|
|
53
|
+
icp: {
|
|
54
|
+
primaryPersona: string;
|
|
55
|
+
painPoints: string[];
|
|
56
|
+
goals: string[];
|
|
57
|
+
objections: string[];
|
|
58
|
+
};
|
|
59
|
+
positioning: {
|
|
60
|
+
category: string;
|
|
61
|
+
differentiators: string[];
|
|
62
|
+
valueProposition: string;
|
|
63
|
+
proofPoints: string[];
|
|
64
|
+
};
|
|
65
|
+
messaging: {
|
|
66
|
+
headline: string;
|
|
67
|
+
subheadline: string;
|
|
68
|
+
elevatorPitch: string;
|
|
69
|
+
longDescription: string;
|
|
70
|
+
};
|
|
71
|
+
seoStrategy: {
|
|
72
|
+
primaryKeywords: string[];
|
|
73
|
+
secondaryKeywords: string[];
|
|
74
|
+
longTailKeywords: string[];
|
|
75
|
+
titleTemplates: Record<string, string>;
|
|
76
|
+
metaDescriptions: Record<string, string>;
|
|
77
|
+
};
|
|
78
|
+
siteArchitecture: {
|
|
79
|
+
pages: SiteArchitecturePage[];
|
|
80
|
+
navigation: NavItem[];
|
|
81
|
+
footerSections: FooterSection[];
|
|
82
|
+
};
|
|
83
|
+
conversionStrategy: {
|
|
84
|
+
primaryCta: { text: string; href: string };
|
|
85
|
+
secondaryCta: { text: string; href: string };
|
|
86
|
+
trustSignals: string[];
|
|
87
|
+
socialProof: string[];
|
|
88
|
+
leadCapture: 'none' | 'webhook' | 'resend' | 'postmark';
|
|
89
|
+
};
|
|
90
|
+
competitiveContext: {
|
|
91
|
+
category: string;
|
|
92
|
+
competitors: string[];
|
|
93
|
+
differentiators: string[];
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Strategy metadata for caching and staleness detection
|
|
99
|
+
*/
|
|
100
|
+
export interface StrategyMetadata {
|
|
101
|
+
/** SHA-256 of (docs + spec + tokens) for staleness detection */
|
|
102
|
+
inputHash: string;
|
|
103
|
+
/** ISO timestamp of generation */
|
|
104
|
+
generatedAt: string;
|
|
105
|
+
/** Schema version */
|
|
106
|
+
version: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Design tokens extracted from project config or brand docs
|
|
111
|
+
*/
|
|
112
|
+
export interface DesignTokens {
|
|
113
|
+
colors: Record<string, string>;
|
|
114
|
+
fonts: { heading: string; body: string; mono?: string };
|
|
115
|
+
borderRadius: string;
|
|
116
|
+
source: 'tailwind-config' | 'css-variables' | 'brand-docs' | 'defaults';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Brand assets contract for deterministic logo/favicon placement
|
|
121
|
+
*/
|
|
122
|
+
export interface BrandAssetsContract {
|
|
123
|
+
/** Discovered source path for logo */
|
|
124
|
+
logoPath?: string;
|
|
125
|
+
/** Canonical output path: public/brand/logo.{ext} */
|
|
126
|
+
logoOutputPath: string;
|
|
127
|
+
/** Discovered source path for favicon */
|
|
128
|
+
faviconPath?: string;
|
|
129
|
+
/** Primary brand color */
|
|
130
|
+
primaryColor?: string;
|
|
131
|
+
/** Full color scheme */
|
|
132
|
+
colorScheme?: Record<string, string>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// --- Zod Schemas ---
|
|
136
|
+
|
|
137
|
+
export const NavItemSchema: z.ZodType<NavItem> = z.lazy(() =>
|
|
138
|
+
z.object({
|
|
139
|
+
label: z.string().min(1),
|
|
140
|
+
href: z.string().min(1),
|
|
141
|
+
children: z.array(NavItemSchema).optional(),
|
|
142
|
+
})
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
export const FooterSectionSchema = z.object({
|
|
146
|
+
title: z.string().min(1),
|
|
147
|
+
links: z.array(
|
|
148
|
+
z.object({
|
|
149
|
+
label: z.string().min(1),
|
|
150
|
+
href: z.string().min(1),
|
|
151
|
+
})
|
|
152
|
+
),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
export const SiteArchitecturePageSchema = z.object({
|
|
156
|
+
path: z.string().min(1),
|
|
157
|
+
title: z.string().min(1),
|
|
158
|
+
purpose: z.string(),
|
|
159
|
+
pageType: z.enum([
|
|
160
|
+
'landing',
|
|
161
|
+
'pricing',
|
|
162
|
+
'solution',
|
|
163
|
+
'use-cases',
|
|
164
|
+
'about',
|
|
165
|
+
'contact',
|
|
166
|
+
'blog',
|
|
167
|
+
'docs',
|
|
168
|
+
'legal',
|
|
169
|
+
]),
|
|
170
|
+
sections: z.array(z.string()),
|
|
171
|
+
seoKeywords: z.array(z.string()),
|
|
172
|
+
conversionGoal: z.string(),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
export const WebsiteStrategySchema = z.object({
|
|
176
|
+
icp: z.object({
|
|
177
|
+
primaryPersona: z.string().min(1),
|
|
178
|
+
painPoints: z.array(z.string()),
|
|
179
|
+
goals: z.array(z.string()),
|
|
180
|
+
objections: z.array(z.string()),
|
|
181
|
+
}),
|
|
182
|
+
positioning: z.object({
|
|
183
|
+
category: z.string().min(1),
|
|
184
|
+
differentiators: z.array(z.string()),
|
|
185
|
+
valueProposition: z.string().min(1),
|
|
186
|
+
proofPoints: z.array(z.string()),
|
|
187
|
+
}),
|
|
188
|
+
messaging: z.object({
|
|
189
|
+
headline: z.string().min(1),
|
|
190
|
+
subheadline: z.string().min(1),
|
|
191
|
+
elevatorPitch: z.string().min(1),
|
|
192
|
+
longDescription: z.string().min(1),
|
|
193
|
+
}),
|
|
194
|
+
seoStrategy: z.object({
|
|
195
|
+
primaryKeywords: z.array(z.string()),
|
|
196
|
+
secondaryKeywords: z.array(z.string()),
|
|
197
|
+
longTailKeywords: z.array(z.string()),
|
|
198
|
+
titleTemplates: z.record(z.string(), z.string()),
|
|
199
|
+
metaDescriptions: z.record(z.string(), z.string()),
|
|
200
|
+
}),
|
|
201
|
+
siteArchitecture: z.object({
|
|
202
|
+
pages: z.array(SiteArchitecturePageSchema),
|
|
203
|
+
navigation: z.array(NavItemSchema),
|
|
204
|
+
footerSections: z.array(FooterSectionSchema),
|
|
205
|
+
}),
|
|
206
|
+
conversionStrategy: z.object({
|
|
207
|
+
primaryCta: z.object({ text: z.string().min(1), href: z.string().min(1) }),
|
|
208
|
+
secondaryCta: z.object({ text: z.string().min(1), href: z.string().min(1) }),
|
|
209
|
+
trustSignals: z.array(z.string()),
|
|
210
|
+
socialProof: z.array(z.string()),
|
|
211
|
+
leadCapture: z.enum(['none', 'webhook', 'resend', 'postmark']),
|
|
212
|
+
}),
|
|
213
|
+
competitiveContext: z.object({
|
|
214
|
+
category: z.string(),
|
|
215
|
+
competitors: z.array(z.string()),
|
|
216
|
+
differentiators: z.array(z.string()),
|
|
217
|
+
}),
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export const StrategyMetadataSchema = z.object({
|
|
221
|
+
inputHash: z.string().min(1),
|
|
222
|
+
generatedAt: z.string().min(1),
|
|
223
|
+
version: z.number(),
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
export const DesignTokensSchema = z.object({
|
|
227
|
+
colors: z.record(z.string(), z.string()),
|
|
228
|
+
fonts: z.object({
|
|
229
|
+
heading: z.string(),
|
|
230
|
+
body: z.string(),
|
|
231
|
+
mono: z.string().optional(),
|
|
232
|
+
}),
|
|
233
|
+
borderRadius: z.string(),
|
|
234
|
+
source: z.enum(['tailwind-config', 'css-variables', 'brand-docs', 'defaults']),
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
export const BrandAssetsContractSchema = z.object({
|
|
238
|
+
logoPath: z.string().optional(),
|
|
239
|
+
logoOutputPath: z.string().min(1),
|
|
240
|
+
faviconPath: z.string().optional(),
|
|
241
|
+
primaryColor: z.string().optional(),
|
|
242
|
+
colorScheme: z.record(z.string(), z.string()).optional(),
|
|
243
|
+
});
|
package/src/types/workflow.ts
CHANGED
|
@@ -192,6 +192,19 @@ export interface ProjectState {
|
|
|
192
192
|
error?: string;
|
|
193
193
|
createdAt: string;
|
|
194
194
|
updatedAt: string;
|
|
195
|
+
/** Raw user documentation discovered from CWD */
|
|
196
|
+
userDocs?: string;
|
|
197
|
+
/** Brand context discovered from CWD */
|
|
198
|
+
brandContext?: {
|
|
199
|
+
logoPath?: string;
|
|
200
|
+
primaryColor?: string;
|
|
201
|
+
};
|
|
202
|
+
/** Path to website strategy JSON file (relative to .popeye/) */
|
|
203
|
+
websiteStrategy?: string;
|
|
204
|
+
/** Error message from website strategy generation (for visibility) */
|
|
205
|
+
strategyError?: string;
|
|
206
|
+
/** Absolute paths to discovered source documentation files */
|
|
207
|
+
sourceDocPaths?: string[];
|
|
195
208
|
}
|
|
196
209
|
|
|
197
210
|
/**
|
|
@@ -229,6 +242,14 @@ export const ProjectStateSchema = z.object({
|
|
|
229
242
|
error: z.string().optional(),
|
|
230
243
|
createdAt: z.string(),
|
|
231
244
|
updatedAt: z.string(),
|
|
245
|
+
userDocs: z.string().optional(),
|
|
246
|
+
brandContext: z.object({
|
|
247
|
+
logoPath: z.string().optional(),
|
|
248
|
+
primaryColor: z.string().optional(),
|
|
249
|
+
}).optional(),
|
|
250
|
+
websiteStrategy: z.string().optional(),
|
|
251
|
+
strategyError: z.string().optional(),
|
|
252
|
+
sourceDocPaths: z.array(z.string()).optional(),
|
|
232
253
|
});
|
|
233
254
|
|
|
234
255
|
/**
|
package/src/upgrade/handlers.ts
CHANGED
|
@@ -21,6 +21,10 @@ import {
|
|
|
21
21
|
generateRootDockerCompose,
|
|
22
22
|
} from '../generators/templates/fullstack.js';
|
|
23
23
|
import { loadState, saveState } from '../state/persistence.js';
|
|
24
|
+
import { buildWebsiteContext, resolveBrandAssets, validateWebsiteContext } from '../generators/website-context.js';
|
|
25
|
+
import type { WebsiteContentContext } from '../generators/website-context.js';
|
|
26
|
+
import { resolveWorkspaceRoot } from '../generators/workspace-root.js';
|
|
27
|
+
import { loadWebsiteStrategy } from '../workflow/website-strategy.js';
|
|
24
28
|
import type { UpgradeResult } from './index.js';
|
|
25
29
|
|
|
26
30
|
/**
|
|
@@ -42,6 +46,57 @@ async function pathExists(filePath: string): Promise<boolean> {
|
|
|
42
46
|
}
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Build website content context from user docs, brand assets, and strategy
|
|
51
|
+
*
|
|
52
|
+
* Replicates the context-building pattern from website-updater.ts so that
|
|
53
|
+
* upgrade-generated websites get real content instead of TODO placeholders.
|
|
54
|
+
*
|
|
55
|
+
* @param projectDir - Project directory (workspace root)
|
|
56
|
+
* @param projectName - Project name
|
|
57
|
+
* @returns Content context and optional warning
|
|
58
|
+
*/
|
|
59
|
+
export async function buildUpgradeContentContext(
|
|
60
|
+
projectDir: string,
|
|
61
|
+
projectName: string,
|
|
62
|
+
): Promise<{ context?: WebsiteContentContext; warning?: string }> {
|
|
63
|
+
try {
|
|
64
|
+
// Build context from user docs (scans projectDir + parent via getScanDirectories)
|
|
65
|
+
const context = await buildWebsiteContext(projectDir, projectName);
|
|
66
|
+
|
|
67
|
+
// Apply brand context from state if available
|
|
68
|
+
const state = await loadState(projectDir);
|
|
69
|
+
if (state?.brandContext?.primaryColor) {
|
|
70
|
+
context.brand = { ...context.brand, primaryColor: state.brandContext.primaryColor };
|
|
71
|
+
}
|
|
72
|
+
if (state?.brandContext?.logoPath) {
|
|
73
|
+
context.brand = { ...context.brand, logoPath: state.brandContext.logoPath };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Resolve brand assets using workspace root
|
|
77
|
+
const workspaceRoot = await resolveWorkspaceRoot(projectDir);
|
|
78
|
+
context.brandAssets = await resolveBrandAssets(workspaceRoot, context.brand);
|
|
79
|
+
|
|
80
|
+
// Load website strategy if available
|
|
81
|
+
const strategyData = await loadWebsiteStrategy(projectDir);
|
|
82
|
+
if (strategyData) {
|
|
83
|
+
context.strategy = strategyData.strategy;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Soft validation: include quality warnings in the return value
|
|
87
|
+
const validation = validateWebsiteContext(context, projectName);
|
|
88
|
+
const validationWarnings = [...validation.issues, ...validation.warnings]
|
|
89
|
+
.map((w) => `[quality-gate] ${w}`);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
context,
|
|
93
|
+
warning: validationWarnings.length > 0 ? validationWarnings.join('; ') : undefined,
|
|
94
|
+
};
|
|
95
|
+
} catch (e) {
|
|
96
|
+
return { warning: e instanceof Error ? e.message : 'Unknown error building website context' };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
45
100
|
/**
|
|
46
101
|
* Update state.json language field
|
|
47
102
|
*
|
|
@@ -297,11 +352,21 @@ export async function upgradeFullstackToAll(
|
|
|
297
352
|
openaiModel: 'gpt-4o',
|
|
298
353
|
};
|
|
299
354
|
|
|
355
|
+
// Build content context from user docs, brand assets, and strategy
|
|
356
|
+
const { context: contentContext, warning } = await buildUpgradeContentContext(
|
|
357
|
+
projectDir,
|
|
358
|
+
projectName,
|
|
359
|
+
);
|
|
360
|
+
if (warning) {
|
|
361
|
+
console.warn(`[upgrade] Website context warning: ${warning}`);
|
|
362
|
+
}
|
|
363
|
+
|
|
300
364
|
const result = await generateWebsiteProject(spec, projectDir, {
|
|
301
365
|
baseDir: websiteDir,
|
|
302
366
|
workspaceMode: true,
|
|
303
367
|
skipDocker: true,
|
|
304
368
|
skipReadme: true,
|
|
369
|
+
contentContext,
|
|
305
370
|
});
|
|
306
371
|
|
|
307
372
|
if (!result.success) {
|