prd-to-flutter 0.1.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.
Files changed (85) hide show
  1. package/README.md +149 -0
  2. package/bin/p2f.mjs +18 -0
  3. package/dist/cli.js +203 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/clean.js +35 -0
  6. package/dist/commands/clean.js.map +1 -0
  7. package/dist/commands/doctor.js +148 -0
  8. package/dist/commands/doctor.js.map +1 -0
  9. package/dist/commands/generate.js +120 -0
  10. package/dist/commands/generate.js.map +1 -0
  11. package/dist/commands/init.js +46 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/paths.js +58 -0
  14. package/dist/commands/paths.js.map +1 -0
  15. package/dist/commands/remove.js +23 -0
  16. package/dist/commands/remove.js.map +1 -0
  17. package/dist/commands/screenshots-audit.js +39 -0
  18. package/dist/commands/screenshots-audit.js.map +1 -0
  19. package/dist/commands/skills-install.js +21 -0
  20. package/dist/commands/skills-install.js.map +1 -0
  21. package/dist/commands/sync.js +84 -0
  22. package/dist/commands/sync.js.map +1 -0
  23. package/dist/commands/update.js +93 -0
  24. package/dist/commands/update.js.map +1 -0
  25. package/dist/core/existing-page-detector.js +463 -0
  26. package/dist/core/existing-page-detector.js.map +1 -0
  27. package/dist/core/fail-fast.js +50 -0
  28. package/dist/core/fail-fast.js.map +1 -0
  29. package/dist/core/feature-coverage-builder.js +667 -0
  30. package/dist/core/feature-coverage-builder.js.map +1 -0
  31. package/dist/core/flutter-project-scanner.js +393 -0
  32. package/dist/core/flutter-project-scanner.js.map +1 -0
  33. package/dist/core/implementation-plan-writer.js +190 -0
  34. package/dist/core/implementation-plan-writer.js.map +1 -0
  35. package/dist/core/logger.js +39 -0
  36. package/dist/core/logger.js.map +1 -0
  37. package/dist/core/package-info.js +33 -0
  38. package/dist/core/package-info.js.map +1 -0
  39. package/dist/core/paths.js +37 -0
  40. package/dist/core/paths.js.map +1 -0
  41. package/dist/core/playwright-capture.js +539 -0
  42. package/dist/core/playwright-capture.js.map +1 -0
  43. package/dist/core/playwright-cli.js +26 -0
  44. package/dist/core/playwright-cli.js.map +1 -0
  45. package/dist/core/playwright-install.js +40 -0
  46. package/dist/core/playwright-install.js.map +1 -0
  47. package/dist/core/prd-clone.js +131 -0
  48. package/dist/core/prd-clone.js.map +1 -0
  49. package/dist/core/prd-install.js +108 -0
  50. package/dist/core/prd-install.js.map +1 -0
  51. package/dist/core/profile.js +149 -0
  52. package/dist/core/profile.js.map +1 -0
  53. package/dist/core/project-doc-reader.js +252 -0
  54. package/dist/core/project-doc-reader.js.map +1 -0
  55. package/dist/core/report-writer.js +90 -0
  56. package/dist/core/report-writer.js.map +1 -0
  57. package/dist/core/route-name.js +60 -0
  58. package/dist/core/route-name.js.map +1 -0
  59. package/dist/core/run-context.js +160 -0
  60. package/dist/core/run-context.js.map +1 -0
  61. package/dist/core/screenshot-auditor.js +405 -0
  62. package/dist/core/screenshot-auditor.js.map +1 -0
  63. package/dist/core/screenshot-exploration-plan-writer.js +200 -0
  64. package/dist/core/screenshot-exploration-plan-writer.js.map +1 -0
  65. package/dist/core/semantic-model-builder.js +922 -0
  66. package/dist/core/semantic-model-builder.js.map +1 -0
  67. package/dist/core/skill-install.js +78 -0
  68. package/dist/core/skill-install.js.map +1 -0
  69. package/dist/core/stage-stub.js +24 -0
  70. package/dist/core/stage-stub.js.map +1 -0
  71. package/dist/core/task-index-writer.js +149 -0
  72. package/dist/core/task-index-writer.js.map +1 -0
  73. package/dist/core/update-checker.js +155 -0
  74. package/dist/core/update-checker.js.map +1 -0
  75. package/dist/core/vue-page-locator.js +748 -0
  76. package/dist/core/vue-page-locator.js.map +1 -0
  77. package/dist/core/vue-project-reader.js +116 -0
  78. package/dist/core/vue-project-reader.js.map +1 -0
  79. package/docs/artifacts-and-agent.md +203 -0
  80. package/docs/development.md +118 -0
  81. package/docs/usage.md +246 -0
  82. package/package.json +50 -0
  83. package/skills/p2f/SKILL.md +303 -0
  84. package/skills/p2f/references/page-layout-patterns.md +120 -0
  85. package/skills/p2f/references/youfi-flutter-guidelines.md +71 -0
@@ -0,0 +1,463 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+ import { logger } from './logger.js';
4
+ import { markComplete } from './run-context.js';
5
+ const EXISTS_THRESHOLD = 0.75;
6
+ const UNCERTAIN_THRESHOLD = 0.45;
7
+ export function detectExistingFlutterPage(ctx, snapshot, model) {
8
+ const outline = model.outline;
9
+ // Normalize route path from the prototype to a comparable form.
10
+ const protoPath = outline.route.path.replace(/^\/prototype\/|^\/design\//, '/');
11
+ const protoSlug = protoPath.replace(/^\//, '').replace(/\//g, '-');
12
+ const routeName = outline.route.name ?? '';
13
+ // --- Route match -----------------------------------------------------------
14
+ const routeHits = snapshot.routeTable.filter((r) => normalizePath(r.path) === normalizePath(protoPath) ||
15
+ similarityPath(r.path, protoPath) > 0.7 ||
16
+ (routeName && r.key.toLowerCase().replace(/_/g, '-') === routeName.toLowerCase()));
17
+ // --- Class-name match ------------------------------------------------------
18
+ const candidateClassNames = guessExpectedClassNames(routeName, outline.route.label ?? '');
19
+ const classHits = [];
20
+ for (const m of snapshot.modules) {
21
+ for (const vc of m.viewClasses) {
22
+ if (candidateClassNames.some((want) => vc === want)) {
23
+ // Find the file that declares this class.
24
+ const file = m.pages.find((p) => p.toLowerCase().includes(dashOf(vc).toLowerCase()));
25
+ classHits.push({ cls: vc, file: file ?? join(m.path, 'views') });
26
+ }
27
+ }
28
+ }
29
+ // --- Module match (by keyword overlap with route segments) -----------------
30
+ const moduleHits = rankModules(snapshot.modules, [routeName, outline.route.label ?? '', protoSlug]);
31
+ const bestModule = moduleHits[0]?.module ?? snapshot.modules[0];
32
+ if (!bestModule) {
33
+ // Impossible in a real YouFi workspace (modules list non-empty), but keep
34
+ // the compiler happy.
35
+ return makeEmptyVerdict(ctx, snapshot, model);
36
+ }
37
+ // --- Tally confidence ------------------------------------------------------
38
+ const evidenceDetails = [];
39
+ let score = 0;
40
+ if (routeHits.length) {
41
+ score += 0.45;
42
+ evidenceDetails.push({
43
+ kind: 'route',
44
+ contribution: 0.45,
45
+ confidence: 'high',
46
+ summary: `路由匹配:${routeHits.map((r) => r.path).join(', ')}`,
47
+ details: routeHits.map((r) => `AppRoutes.${r.key} = '${r.path}'` +
48
+ `${r.viewClass ? ` · view=${r.viewClass}` : ''}` +
49
+ `${r.viewFile ? ` · file=${r.viewFile}` : ''}`),
50
+ });
51
+ }
52
+ if (classHits.length) {
53
+ score += 0.35;
54
+ evidenceDetails.push({
55
+ kind: 'class',
56
+ contribution: 0.35,
57
+ confidence: 'high',
58
+ summary: `Widget class 同名:${classHits.map((h) => h.cls).join(', ')}`,
59
+ details: classHits.map((h) => `${h.cls} · ${h.file}`),
60
+ });
61
+ }
62
+ if (moduleHits.length && moduleHits[0].score > 0.3) {
63
+ score += 0.15;
64
+ evidenceDetails.push({
65
+ kind: 'module',
66
+ contribution: 0.15,
67
+ confidence: 'medium',
68
+ summary: `模块命名相似:${moduleHits[0].module.path}`,
69
+ details: moduleHits.slice(0, 5).map((h) => `${h.module.path} · score=${h.score.toFixed(2)}`),
70
+ });
71
+ }
72
+ const labelHits = outline.route.label ? findLabelHits(snapshot, outline.route.label) : [];
73
+ if (outline.route.label) {
74
+ // Look for the label as a literal in any existing view file.
75
+ if (labelHits.length) {
76
+ score += 0.1;
77
+ evidenceDetails.push({
78
+ kind: 'title',
79
+ contribution: 0.1,
80
+ confidence: 'low',
81
+ summary: `AppBar / 标题文案匹配:${outline.route.label}`,
82
+ details: labelHits.slice(0, 5),
83
+ });
84
+ }
85
+ }
86
+ if (!routeHits.length) {
87
+ evidenceDetails.push({
88
+ kind: 'negative',
89
+ contribution: 0,
90
+ confidence: 'medium',
91
+ summary: '未命中现有 Flutter 路由',
92
+ details: [`prototype route: ${protoPath}`, routeName ? `route name: ${routeName}` : 'route name: (无)'],
93
+ });
94
+ }
95
+ if (!classHits.length && candidateClassNames.length) {
96
+ evidenceDetails.push({
97
+ kind: 'negative',
98
+ contribution: 0,
99
+ confidence: 'medium',
100
+ summary: '未命中预期 Widget class',
101
+ details: candidateClassNames,
102
+ });
103
+ }
104
+ score = Math.min(1, score);
105
+ const status = decideStatus(score, routeHits.length, classHits.length);
106
+ const pageExists = status === 'exists';
107
+ // --- Proposal for new page (used when pageExists is false) ----------------
108
+ const preferredSuffix = toClassSuffix(snapshot.pageSuffix);
109
+ const proposedClass = candidateClassNames.find((name) => name.endsWith(preferredSuffix)) ??
110
+ candidateClassNames[0] ??
111
+ `Unnamed${preferredSuffix || 'Page'}`;
112
+ const proposedFile = join(bestModule.path, snapshot.structure.moduleViewDirs[0] ?? 'views', `${dashOf(proposedClass).replace(/-/g, '_')}.dart`);
113
+ const proposedRouteKey = routeName ? toCamelCaseKey(routeName) : 'unnamedRoute';
114
+ const proposedRoutePath = protoPath;
115
+ // --- Reuse candidates ------------------------------------------------------
116
+ const reuseCandidates = {
117
+ widgets: snapshot.commonWidgets.slice(0, 20).map((w) => w.name),
118
+ themeTokens: snapshot.themeTokens.filter((t) => /primary|bg|background|text|border|secondary|label/i.test(t)).slice(0, 20),
119
+ };
120
+ const bestExistingCandidate = {
121
+ pageFile: routeHits[0]?.viewFile ?? classHits[0]?.file ?? null,
122
+ widgetClass: routeHits[0]?.viewClass ?? classHits[0]?.cls ?? null,
123
+ routeKey: routeHits[0]?.key ?? null,
124
+ routePath: routeHits[0]?.path ?? null,
125
+ };
126
+ const agentReview = buildAgentReviewPlan({
127
+ status,
128
+ confidence: Number(score.toFixed(2)),
129
+ protoPath,
130
+ routeName,
131
+ routeLabel: outline.route.label ?? '',
132
+ candidateClassNames,
133
+ bestModule,
134
+ routeHits,
135
+ classHits,
136
+ moduleHits,
137
+ labelHits,
138
+ proposal: {
139
+ pageFile: proposedFile,
140
+ widgetClass: proposedClass,
141
+ routeKey: proposedRouteKey,
142
+ routePath: proposedRoutePath,
143
+ },
144
+ });
145
+ const verdict = {
146
+ pageExists,
147
+ status,
148
+ confidence: Number(score.toFixed(2)),
149
+ evidence: evidenceDetails
150
+ .filter((e) => e.kind !== 'negative')
151
+ .map((e) => `${e.summary}(+${e.contribution.toFixed(2)})`),
152
+ evidenceDetails,
153
+ agentReview,
154
+ targetModule: bestModule.path,
155
+ targetModuleName: bestModule.name,
156
+ targetPageFile: pageExists ? (classHits[0]?.file ?? null) : null,
157
+ targetWidgetClass: pageExists ? (classHits[0]?.cls ?? null) : null,
158
+ targetRouteKey: pageExists ? (routeHits[0]?.key ?? null) : null,
159
+ targetRoutePath: pageExists ? (routeHits[0]?.path ?? null) : null,
160
+ proposal: {
161
+ pageFile: proposedFile,
162
+ widgetClass: proposedClass,
163
+ routeKey: proposedRouteKey,
164
+ routePath: proposedRoutePath,
165
+ },
166
+ reuseCandidates,
167
+ writtenTo: '',
168
+ };
169
+ const analysisDir = join(ctx.pageDir, 'analysis');
170
+ mkdirSync(analysisDir, { recursive: true });
171
+ const writtenTo = join(analysisDir, 'flutter-mapping.md');
172
+ writeFileSync(writtenTo, renderVerdict(ctx, verdict, snapshot), 'utf8');
173
+ verdict.writtenTo = writtenTo;
174
+ logger.success(`Existing-page detection · status=${status} confidence=${score.toFixed(2)} module=${bestModule.name}`);
175
+ markComplete(ctx, 'detect-existing-page');
176
+ return verdict;
177
+ }
178
+ // ---------------------------------------------------------------------------
179
+ // Helpers
180
+ // ---------------------------------------------------------------------------
181
+ function normalizePath(p) {
182
+ return p.replace(/^\/+|\/+$/g, '').replace(/[-_]/g, '').toLowerCase();
183
+ }
184
+ function similarityPath(a, b) {
185
+ const ap = a.split('/').filter(Boolean);
186
+ const bp = b.split('/').filter(Boolean);
187
+ let hit = 0;
188
+ for (let i = 0; i < Math.min(ap.length, bp.length); i += 1) {
189
+ if (ap[i]?.toLowerCase() === bp[i]?.toLowerCase())
190
+ hit += 1;
191
+ }
192
+ return hit / Math.max(ap.length, bp.length, 1);
193
+ }
194
+ /**
195
+ * Generate plausible Flutter class names for a given route name / label.
196
+ *
197
+ * Examples:
198
+ * routeName "stock-trade" → StockTradePage / StockTradeScreen / StockTradeView
199
+ * routeName "design-stock-detail" → StockDetailPage / StockDetailView / ...
200
+ * label "个股详情页" → StockDetailPage (no good mapping, skip)
201
+ */
202
+ function guessExpectedClassNames(routeName, _label) {
203
+ const out = [];
204
+ if (!routeName)
205
+ return out;
206
+ // Strip common registry prefixes.
207
+ const trimmed = routeName.replace(/^(prototype-|design-|spec-)/, '');
208
+ const parts = trimmed.split(/[-_]/).filter(Boolean);
209
+ const base = parts
210
+ .map((p) => p.charAt(0).toUpperCase() + p.slice(1))
211
+ .join('');
212
+ if (!base)
213
+ return out;
214
+ for (const suffix of ['Page', 'Screen', 'View']) {
215
+ out.push(`${base}${suffix}`);
216
+ }
217
+ return out;
218
+ }
219
+ function rankModules(modules, hints) {
220
+ const tokens = new Set();
221
+ for (const h of hints) {
222
+ for (const t of (h ?? '').toLowerCase().split(/[\s\-_/]/))
223
+ if (t)
224
+ tokens.add(t);
225
+ }
226
+ return modules
227
+ .map((module) => {
228
+ let score = 0;
229
+ for (const t of tokens) {
230
+ if (!t)
231
+ continue;
232
+ if (module.name.toLowerCase().includes(t))
233
+ score += 0.3;
234
+ if (module.viewClasses.some((vc) => vc.toLowerCase().includes(t)))
235
+ score += 0.1;
236
+ if (module.pages.some((p) => p.toLowerCase().includes(t)))
237
+ score += 0.05;
238
+ }
239
+ return { module, score };
240
+ })
241
+ .filter((x) => x.score > 0)
242
+ .sort((a, b) => b.score - a.score);
243
+ }
244
+ function decideStatus(score, routeHitCount, classHitCount) {
245
+ if (score >= EXISTS_THRESHOLD)
246
+ return 'exists';
247
+ if (score >= UNCERTAIN_THRESHOLD || routeHitCount > 0 || classHitCount > 0)
248
+ return 'uncertain';
249
+ return 'missing';
250
+ }
251
+ function findLabelHits(snapshot, _label) {
252
+ // Cheap label scan: check each view file. For long labels we skip to avoid
253
+ // noisy literal matches against random Dart strings.
254
+ const label = (_label ?? '').trim();
255
+ if (!label || label.length > 10)
256
+ return [];
257
+ const out = [];
258
+ for (const m of snapshot.modules) {
259
+ for (const p of m.pages) {
260
+ // We intentionally do not re-read files here; the scanner already captures
261
+ // class names and paths. A deeper text search is intentionally deferred
262
+ // to avoid rescanning for every generate run.
263
+ if (p.toLowerCase().includes(label.toLowerCase()))
264
+ out.push(p);
265
+ }
266
+ }
267
+ return out;
268
+ }
269
+ function dashOf(cls) {
270
+ // "StockTradePage" → "stock-trade-page"
271
+ return cls
272
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
273
+ .toLowerCase();
274
+ }
275
+ function toCamelCaseKey(routeName) {
276
+ // "stock-trade" → "stockTrade"
277
+ const parts = routeName.split(/[-_]/).filter(Boolean);
278
+ if (!parts.length)
279
+ return routeName;
280
+ return parts[0] + parts.slice(1).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join('');
281
+ }
282
+ function renderVerdict(ctx, v, snapshot) {
283
+ const lines = [];
284
+ lines.push(`# Flutter 映射 — ${ctx.options.pageName}`);
285
+ lines.push('');
286
+ lines.push(`- status: **${v.status}**`);
287
+ lines.push(`- pageExists: **${v.pageExists}**(仅 status=exists 时为 true)`);
288
+ lines.push(`- confidence: **${v.confidence}**`);
289
+ lines.push(`- agentReviewRequired: **${v.agentReview.required}**`);
290
+ lines.push(`- targetModule: \`${v.targetModule}\``);
291
+ if (v.targetPageFile)
292
+ lines.push(`- targetPageFile: \`${v.targetPageFile}\``);
293
+ if (v.targetWidgetClass)
294
+ lines.push(`- targetWidgetClass: \`${v.targetWidgetClass}\``);
295
+ if (v.targetRouteKey)
296
+ lines.push(`- targetRoute: \`AppRoutes.${v.targetRouteKey} = '${v.targetRoutePath}'\``);
297
+ lines.push('');
298
+ lines.push('## 状态说明');
299
+ lines.push('');
300
+ if (v.status === 'exists') {
301
+ lines.push('- CLI 高置信判断页面已存在,agent 可以在复核后优先扩展目标页面。');
302
+ }
303
+ else if (v.status === 'uncertain') {
304
+ lines.push('- CLI 找到部分匹配证据,但不足以安全判断页面已存在或不存在。agent 必须先完成下方复核任务,再决定修改已有页面或新增页面。');
305
+ }
306
+ else {
307
+ lines.push('- CLI 未找到足够证据证明页面已存在,默认按新增页面处理;agent 仍需快速确认没有漏扫。');
308
+ }
309
+ lines.push('');
310
+ lines.push('## 判定依据');
311
+ lines.push('');
312
+ if (v.evidence.length === 0)
313
+ lines.push('- (无显著匹配数据;默认按未初始化处理)');
314
+ for (const e of v.evidence)
315
+ lines.push(`- ${e}`);
316
+ lines.push('');
317
+ lines.push('## 证据明细');
318
+ lines.push('');
319
+ lines.push('| 类型 | 贡献 | 置信 | 摘要 | 明细 |');
320
+ lines.push('| --- | ---: | --- | --- | --- |');
321
+ for (const e of v.evidenceDetails) {
322
+ lines.push(`| ${e.kind} | ${e.contribution.toFixed(2)} | ${e.confidence} | ${escapeTable(e.summary)} | ${escapeTable(e.details.join('<br>'))} |`);
323
+ }
324
+ lines.push('');
325
+ if (v.agentReview.required) {
326
+ lines.push('## Agent 复核任务');
327
+ lines.push('');
328
+ lines.push(`- 原因:${v.agentReview.reason}`);
329
+ lines.push(`- 候选文件:${v.agentReview.candidateFiles.map((f) => `\`${f}\``).join(', ') || '(无)'}`);
330
+ lines.push('');
331
+ lines.push('### 建议搜索命令');
332
+ lines.push('');
333
+ for (const cmd of v.agentReview.commands)
334
+ lines.push(`- \`${cmd}\``);
335
+ lines.push('');
336
+ lines.push('### 复核清单');
337
+ lines.push('');
338
+ for (const item of v.agentReview.checklist)
339
+ lines.push(`- ${item}`);
340
+ lines.push('');
341
+ }
342
+ lines.push('## 提案(未初始化时使用)');
343
+ lines.push('');
344
+ lines.push(`- 新建文件:\`${v.proposal.pageFile}\``);
345
+ lines.push(`- 新建类:\`${v.proposal.widgetClass}\``);
346
+ lines.push(`- 新增路由:\`AppRoutes.${v.proposal.routeKey} = '${v.proposal.routePath}'\``);
347
+ lines.push(`- 路由文件:\`${snapshot.structure.routeConstantsFile ?? '(未检测到)'}\``);
348
+ lines.push(`- 页面注册文件:\`${snapshot.structure.routePagesFile ?? '(未检测到)'}\``);
349
+ lines.push('- 若用户指定页面入口文件或模块,agent 实现时以用户指定为准。');
350
+ lines.push('');
351
+ lines.push('## 可复用资源');
352
+ lines.push('');
353
+ lines.push(`- 公共组件候选:${v.reuseCandidates.widgets.join(', ') || '(无)'}`);
354
+ lines.push(`- 主题 token 候选:${v.reuseCandidates.themeTokens.join(', ') || '(无)'}`);
355
+ lines.push('');
356
+ lines.push(`> 项目扫描详情见:\`${relative(ctx.paths.workspaceDir, snapshot.writtenTo)}\`(共享快照,每次 generate 更新)`);
357
+ return lines.join('\n') + '\n';
358
+ }
359
+ function buildAgentReviewPlan(input) {
360
+ const candidateFiles = dedupeStrings([
361
+ ...input.routeHits.map((h) => h.viewFile).filter(isString),
362
+ ...input.classHits.map((h) => h.file),
363
+ ...input.labelHits,
364
+ ...input.moduleHits.slice(0, 2).flatMap((h) => h.module.pages.slice(0, 3)),
365
+ ]);
366
+ const required = input.status === 'uncertain';
367
+ const reason = required
368
+ ? `existing-page 置信度 ${input.confidence} 处于复核区间,不能直接判定修改已有页面或新增页面。`
369
+ : input.status === 'exists'
370
+ ? `existing-page 置信度 ${input.confidence} 达到高置信阈值。`
371
+ : `existing-page 置信度 ${input.confidence} 未达到复核区间。`;
372
+ const searchTerms = dedupeStrings([
373
+ input.protoPath,
374
+ input.routeName,
375
+ input.routeLabel,
376
+ ...input.candidateClassNames,
377
+ input.proposal.widgetClass,
378
+ ].filter(Boolean));
379
+ const rgTerms = searchTerms.slice(0, 8).map((term) => escapeForRg(term)).join('|');
380
+ const commands = [
381
+ ...(rgTerms ? [`rg -n "${rgTerms}" lib/app`] : []),
382
+ `rg --files lib/app | rg "${escapeForRg(input.routeName || input.bestModule.name || input.proposal.widgetClass)}"`,
383
+ ...(candidateFiles.length ? candidateFiles.slice(0, 5).map((file) => `sed -n '1,220p' ${file}`) : []),
384
+ ];
385
+ return {
386
+ required,
387
+ reason,
388
+ candidateFiles,
389
+ commands: dedupeStrings(commands),
390
+ checklist: [
391
+ '确认候选文件是否承载同一个产品页面,而不是同名模块、旧页面或相似页面。',
392
+ '确认 Flutter 路由 path / AppRoutes key 是否与原型路由语义一致。',
393
+ '确认 Widget class、AppBar 标题、主要文案和页面结构是否与原型页面一致。',
394
+ '如果确认已有页面,优先在候选文件上扩展,并在实现说明记录复核依据。',
395
+ `如果确认不存在,使用新增提案:${input.proposal.pageFile} / ${input.proposal.widgetClass} / AppRoutes.${input.proposal.routeKey}。`,
396
+ ],
397
+ };
398
+ }
399
+ function escapeTable(value) {
400
+ return value.replace(/\|/g, '\\|').replace(/\n/g, '<br>');
401
+ }
402
+ function escapeForRg(value) {
403
+ return value.replace(/[.*+?^${}()|[\]\\"]/g, '\\$&');
404
+ }
405
+ function isString(value) {
406
+ return typeof value === 'string' && value.length > 0;
407
+ }
408
+ function dedupeStrings(values) {
409
+ return [...new Set(values.filter(Boolean))];
410
+ }
411
+ function toClassSuffix(pageSuffix) {
412
+ if (!pageSuffix)
413
+ return 'Page';
414
+ return pageSuffix.charAt(0).toUpperCase() + pageSuffix.slice(1);
415
+ }
416
+ function makeEmptyVerdict(ctx, snapshot, model) {
417
+ const analysisDir = join(ctx.pageDir, 'analysis');
418
+ mkdirSync(analysisDir, { recursive: true });
419
+ const writtenTo = join(analysisDir, 'flutter-mapping.md');
420
+ const verdict = {
421
+ pageExists: false,
422
+ status: 'missing',
423
+ confidence: 0,
424
+ evidence: ['Flutter 项目未发现任何模块,跳过对齐。'],
425
+ evidenceDetails: [
426
+ {
427
+ kind: 'negative',
428
+ contribution: 0,
429
+ confidence: 'high',
430
+ summary: 'Flutter 项目未发现任何模块',
431
+ details: ['snapshot.modules is empty'],
432
+ },
433
+ ],
434
+ agentReview: {
435
+ required: true,
436
+ reason: 'Flutter 项目模块扫描为空,无法判断页面是否已存在。',
437
+ candidateFiles: [],
438
+ commands: ['rg --files lib/app | head', 'rg -n "GetPage\\(|AppRoutes\\." lib/app'],
439
+ checklist: [
440
+ '确认 p2f profile 中的 flutter.moduleRoots 是否匹配当前项目结构。',
441
+ '确认 Flutter 项目是否已经初始化并包含业务模块。',
442
+ ],
443
+ },
444
+ targetModule: '',
445
+ targetModuleName: '',
446
+ targetPageFile: null,
447
+ targetWidgetClass: null,
448
+ targetRouteKey: null,
449
+ targetRoutePath: null,
450
+ proposal: {
451
+ pageFile: '',
452
+ widgetClass: '',
453
+ routeKey: '',
454
+ routePath: model.outline.route.path,
455
+ },
456
+ reuseCandidates: { widgets: [], themeTokens: [] },
457
+ writtenTo,
458
+ };
459
+ writeFileSync(writtenTo, renderVerdict(ctx, verdict, snapshot), 'utf8');
460
+ markComplete(ctx, 'detect-existing-page');
461
+ return verdict;
462
+ }
463
+ //# sourceMappingURL=existing-page-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"existing-page-detector.js","sourceRoot":"","sources":["../../src/core/existing-page-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { logger } from './logger.js';
2
+ /**
3
+ * Raised by any stage that cannot proceed. The CLI top-level handler formats it
4
+ * into the structured failure output mandated by SKILL.md §4.
5
+ */
6
+ export class FailFastError extends Error {
7
+ detail;
8
+ constructor(detail) {
9
+ super(`[${detail.stage}] ${detail.reason}`);
10
+ this.name = 'FailFastError';
11
+ this.detail = detail;
12
+ }
13
+ }
14
+ export function failFast(detail) {
15
+ throw new FailFastError(detail);
16
+ }
17
+ export function reportFailure(err) {
18
+ const d = err.detail;
19
+ const divider = '─'.repeat(60);
20
+ logger.error(`还原已停止:${d.reason}`);
21
+ const lines = [
22
+ '',
23
+ divider,
24
+ `失败阶段 : ${d.stage}`,
25
+ `失败动作 : ${d.action}`,
26
+ `失败原因 : ${d.reason}`,
27
+ ];
28
+ if (d.completedSteps?.length) {
29
+ lines.push('', '已完成:');
30
+ for (const s of d.completedSteps)
31
+ lines.push(` - ${s}`);
32
+ }
33
+ if (d.pendingSteps?.length) {
34
+ lines.push('', '未完成:');
35
+ for (const s of d.pendingSteps)
36
+ lines.push(` - ${s}`);
37
+ }
38
+ if (d.suggestions?.length) {
39
+ lines.push('', '建议方案:');
40
+ d.suggestions.forEach((s, i) => lines.push(` ${i + 1}. ${s}`));
41
+ }
42
+ if (d.needsUserDecision?.length) {
43
+ lines.push('', '需要用户决策:');
44
+ for (const s of d.needsUserDecision)
45
+ lines.push(` - ${s}`);
46
+ }
47
+ lines.push(divider, '');
48
+ console.error(lines.join('\n'));
49
+ }
50
+ //# sourceMappingURL=fail-fast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fail-fast.js","sourceRoot":"","sources":["../../src/core/fail-fast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAoCrC;;;GAGG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC7B,MAAM,CAAiB;IAEhC,YAAY,MAAsB;QAChC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,UAAU,QAAQ,CAAC,MAAsB;IAC7C,MAAM,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAkB;IAC9C,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;IACrB,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,MAAM,KAAK,GAAa;QACtB,EAAE;QACF,OAAO;QACP,UAAU,CAAC,CAAC,KAAK,EAAE;QACnB,UAAU,CAAC,CAAC,MAAM,EAAE;QACpB,UAAU,CAAC,CAAC,MAAM,EAAE;KACrB,CAAC;IACF,IAAI,CAAC,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,iBAAiB;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACxB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,CAAC"}