mta-mcp 3.15.3 → 3.15.5

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/dist/index.js CHANGED
@@ -6234,6 +6234,7 @@ var OUTPUT_GUIDE = {
6234
6234
  "- **restorationContract.topPrimaryEntry**: \u82E5\u5B58\u5728\u9876\u90E8\u4E3B\u5165\u53E3\u5757\uFF0C**\u7981\u6B62**\u8FC1\u79FB\u4E3A\u5E95\u90E8\u56FA\u5B9A CTA",
6235
6235
  "- **restorationContract.bottomNavigation.present**: \u82E5\u4E3A true \u4E14 contract \u672A\u58F0\u660E\u989D\u5916 CTA\uFF0C\u7981\u6B62\u518D\u989D\u5916\u589E\u52A0\u5E95\u90E8\u64CD\u4F5C\u6761",
6236
6236
  "- **restorationContract.hardRules**: \u751F\u6210\u4EE3\u7801\u524D\u5FC5\u987B\u9010\u6761\u68C0\u67E5\uFF1B\u4E00\u65E6\u8FDD\u53CD\uFF0C\u8BF4\u660E\u9875\u9762\u5DF2\u53D1\u751F\u7ED3\u6784\u6F02\u79FB",
6237
+ "- **restorationContract.systemStatusBar.detected**: true \u8868\u793A Sketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u5C5E\u4E8E\u8BBE\u5907\u7CFB\u7EDF chrome\uFF0CFlutter \u9875\u9762\u5FC5\u987B\u4F9D\u8D56 SafeArea/AppBar\uFF0C\u7981\u6B62\u628A\u8FD9\u4E9B\u5143\u7D20\u753B\u8FDB\u4E1A\u52A1 UI",
6237
6238
  "",
6238
6239
  "### \u989C\u8272\u5B57\u6BB5\uFF08\u6700\u5E38\u51FA\u9519\uFF09",
6239
6240
  '- **colorSource**: "native" \u8868\u793A\u901A\u8FC7 Cocoa API \u83B7\u53D6\u7684\u7CBE\u786E\u989C\u8272\uFF08\u4F18\u5148\u4FE1\u4EFB\uFF09\uFF0C"jsApi" \u662F Sketch JS API \u9884\u5904\u7406\u503C\uFF08\u53EF\u80FD\u4E0D\u51C6\uFF09',
@@ -6412,7 +6413,7 @@ var OUTPUT_GUIDE = {
6412
6413
  "- **tag**: {bg,ph,pv,r,text} Tag\u5BB9\u5668\u4FE1\u606F",
6413
6414
  "- **layout**: {dir,gap,main,cross,pad} \u5E03\u5C40\u610F\u56FE",
6414
6415
  "- **ch**: \u5B50\u5143\u7D20\u6570\u7EC4\uFF08\u9012\u5F52\uFF09",
6415
- "- **designSurface**: {width,height,maxWidth,wideScreenRule} \u8BBE\u8BA1\u753B\u677F\u7EA6\u675F\uFF1B\u79FB\u52A8\u7AEF\u7A84\u753B\u677F\u5728\u5BBD\u5C4F\u5FC5\u987B\u505A\u5C45\u4E2D\u5939\u6301",
6416
+ "- **designSurface**: {width,height,maxWidth,wideScreenRule} \u8BBE\u8BA1\u753B\u677F\u5C3A\u5BF8\u53C2\u8003\uFF1B\u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B Scaffold/SafeArea \u548C\u9875\u9762 padding\uFF0C\u7981\u6B62\u628A\u6574\u9875\u9501\u6210 artboard \u58F3\u5B50",
6416
6417
  "- **selectionContext**: compact \u82E5\u53D1\u73B0\u9009\u4E2D\u7684\u662F\u5B50\u56FE\u5C42\uFF0C\u4F1A\u81EA\u52A8\u63D0\u5347\u5230\u6240\u5C5E\u753B\u677F/\u9876\u5C42\u5BB9\u5668\u5E76\u8BB0\u5F55 warning",
6417
6418
  "",
6418
6419
  "### \u4F7F\u7528\u65B9\u5F0F",
@@ -6423,7 +6424,8 @@ var OUTPUT_GUIDE = {
6423
6424
  "- SVG \u662F\u5426\u8BEF\u52A0 ColorFilter\uFF1A\u4FDD\u7559\u539F\u8272\u7684 SVG \u4E0D\u5F97\u4E8C\u6B21\u67D3\u8272",
6424
6425
  "- \u56FE\u6807\u662F\u5426\u7528\u9519\u5C3A\u5BF8\uFF1A16x16 \u69FD\u4F4D\u4E0D\u7B49\u4E8E 16x16 \u56FE\u5F62\uFF0C\u6309 xs/cs \u5206\u79BB\u5360\u4F4D\u4E0E\u6E32\u67D3",
6425
6426
  "- Bitmap \u662F\u5426\u8BEF\u5F53 SVG\uFF1ASketch Image \u56FE\u5C42\u5FC5\u987B\u5BFC\u51FA PNG + Image.asset\uFF0C\u4E14\u8865\u9F50 2.0x/3.0x \u53D8\u4F53",
6426
- "- \u79FB\u52A8\u7AEF\u7A84\u753B\u677F\uFF08\u5982 390 \u5BBD\uFF09\u5728\u5BBD\u5C4F\u5FC5\u987B\u7528 Center + ConstrainedBox(maxWidth: designSurface.maxWidth) \u5939\u6301\uFF0C\u7981\u6B62\u8BA9 Positioned(left/right) \u76F4\u63A5\u62C9\u4F38\u5230\u5168\u5C4F",
6427
+ "- \u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B Scaffold/SafeArea/AppBar \u548C\u9875\u9762 padding\uFF0C\u7981\u6B62\u628A\u6574\u9875\u9501\u6210 390 \u753B\u677F\u58F3\u5B50",
6428
+ "- Sketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u5C5E\u4E8E\u8BBE\u5907\u7CFB\u7EDF chrome\uFF0C\u4E0D\u5C5E\u4E8E\u9875\u9762\u4E1A\u52A1 UI\uFF0C\u7981\u6B62\u76F4\u63A5\u8FD8\u539F\u5230 Flutter \u9875\u9762",
6427
6429
  "- \u82E5\u8282\u70B9\u540C\u65F6\u7ED9\u51FA f \u4E0E vf\uFF0C\u8BF4\u660E\u80CC\u666F\u5C42/\u9634\u5F71\u8D85\u51FA\u903B\u8F91 frame\uFF1B\u5BB9\u5668\u5C3A\u5BF8\u548C\u5E95\u90E8\u89C6\u89C9\u95F4\u8DDD\u4F18\u5148\u4F7F\u7528 vf",
6428
6430
  "- \u82E5 selectionContext.autoPromoted=true\uFF0C\u8BF4\u660E\u4E4B\u524D\u9009\u4E2D\u4E86\u5185\u5C42 glyph\uFF1B\u540E\u7EED\u5C40\u90E8\u5BFC\u51FA\u56FE\u6807\u65F6\u5E94\u6539\u7528 cmd=svg \u9009\u4E2D\u5177\u4F53\u56FE\u5C42",
6429
6431
  "- \u9875\u9762\u9AA8\u67B6\u662F\u5426\u88AB\u4E1A\u52A1\u7EC4\u4EF6\u6539\u5199\uFF1A\u6807\u9898\u3001\u9876\u90E8\u5165\u53E3\u3001\u641C\u7D22\u5757\u548C\u5E95\u5BFC\u987A\u5E8F\u5FC5\u987B\u56DE\u770B restorationContract"
@@ -6516,14 +6518,15 @@ async function sketchMeasure(args) {
6516
6518
  scriptPath: tempScriptPath,
6517
6519
  scriptLength: fullScript.length,
6518
6520
  pluginInstall: installStatus,
6519
- instruction: "\u5C06 loaderScript \u4F20\u5165 mcp_sketch_run_code({ code: loaderScript }) \u6267\u884C\u3002\u8BBE\u8BA1\u7A3F\u8FD8\u539F\u9996\u8F6E\u4F18\u5148\u4F7F\u7528 cmd=compact\uFF1B\u53EA\u6709\u5F53 compact contract \u4E0D\u8DB3\u4EE5\u89E3\u91CA\u5C40\u90E8\u5E03\u5C40\u6216\u6837\u5F0F\u65F6\uFF0C\u518D\u8865\u7528 measure/style\u3002\u82E5\u504F\u5DEE\u96C6\u4E2D\u5728\u5355\u4E2A icon/svg/bitmap\uFF0C\u8BF7\u91CD\u65B0\u9009\u4E2D\u8BE5\u56FE\u5C42\u6267\u884C svg \u6216\u5C40\u90E8\u5BFC\u51FA\uFF0C\u5E76\u590D\u67E5 colorStrategy\u3001viewBox\u3001containerSize/contentSize\u3001vf \u4E0E bitmapScales\uFF0C\u907F\u514D\u590D\u7528\u65E7\u9875\u9762\u8D44\u4EA7\u3002\u79FB\u52A8\u7AEF\u7A84\u753B\u677F\u8981\u6309 designSurface.maxWidth \u505A\u5BBD\u5C4F\u5939\u6301\u3002compact \u82E5\u68C0\u6D4B\u5230\u4F60\u9009\u4E2D\u7684\u662F\u5185\u5C42 glyph\uFF0C\u4F1A\u81EA\u52A8\u63D0\u5347\u5230\u6240\u5C5E\u753B\u677F\u5E76\u901A\u8FC7 selectionContext \u56DE\u62A5\u3002\u8BF7\u5148\u5728 Sketch \u4E2D\u9009\u4E2D\u76EE\u6807\u753B\u677F/\u56FE\u5C42\u3002",
6521
+ instruction: "\u5C06 loaderScript \u4F20\u5165 mcp_sketch_run_code({ code: loaderScript }) \u6267\u884C\u3002\u8BBE\u8BA1\u7A3F\u8FD8\u539F\u9996\u8F6E\u4F18\u5148\u4F7F\u7528 cmd=compact\uFF1B\u53EA\u6709\u5F53 compact contract \u4E0D\u8DB3\u4EE5\u89E3\u91CA\u5C40\u90E8\u5E03\u5C40\u6216\u6837\u5F0F\u65F6\uFF0C\u518D\u8865\u7528 measure/style\u3002\u82E5\u504F\u5DEE\u96C6\u4E2D\u5728\u5355\u4E2A icon/svg/bitmap\uFF0C\u8BF7\u91CD\u65B0\u9009\u4E2D\u8BE5\u56FE\u5C42\u6267\u884C svg \u6216\u5C40\u90E8\u5BFC\u51FA\uFF0C\u5E76\u590D\u67E5 colorStrategy\u3001viewBox\u3001containerSize/contentSize\u3001vf \u4E0E bitmapScales\uFF0C\u907F\u514D\u590D\u7528\u65E7\u9875\u9762\u8D44\u4EA7\u3002\u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B Scaffold/SafeArea/AppBar \u548C\u9875\u9762 padding \u9002\u914D\uFF1BSketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u5C5E\u4E8E\u8BBE\u5907\u7CFB\u7EDF chrome\uFF0C\u7981\u6B62\u76F4\u63A5\u8FD8\u539F\u5230 Flutter \u9875\u9762\u3002compact \u82E5\u68C0\u6D4B\u5230\u4F60\u9009\u4E2D\u7684\u662F\u5185\u5C42 glyph\uFF0C\u4F1A\u81EA\u52A8\u63D0\u5347\u5230\u6240\u5C5E\u753B\u677F\u5E76\u901A\u8FC7 selectionContext \u56DE\u62A5\u3002\u8BF7\u5148\u5728 Sketch \u4E2D\u9009\u4E2D\u76EE\u6807\u753B\u677F/\u56FE\u5C42\u3002",
6520
6522
  restoreChecklist: [
6521
6523
  "\u5148\u6309 restorationContract \u9501\u5B9A\u9875\u9762\u9AA8\u67B6\uFF0C\u518D\u5904\u7406\u5C40\u90E8\u6837\u5F0F",
6522
6524
  "\u5355\u4E2A\u56FE\u6807\u504F\u5DEE\u4F18\u5148\u5C40\u90E8\u91CD\u5BFC\u51FA\uFF0C\u4E0D\u590D\u7528\u5176\u5B83\u9875\u9762\u65E7\u8D44\u4EA7",
6523
6525
  "preserve \u6A21\u5F0F SVG \u7981\u6B62\u8FFD\u52A0 ColorFilter",
6524
6526
  "16x16 \u69FD\u4F4D\u4E0E 6x8/12x12 \u56FE\u5F62\u8981\u5206\u5F00\u5904\u7406",
6525
6527
  "Sketch Image \u56FE\u5C42\u5BFC\u51FA PNG\uFF0C\u4E0D\u8981\u4F2A\u88C5\u6210 SVG \u4F7F\u7528\uFF0C\u5E76\u8865\u9F50 2.0x/3.0x \u53D8\u4F53",
6526
- "\u79FB\u52A8\u7AEF\u7A84\u753B\u677F\u5728\u5BBD\u5C4F\u5FC5\u987B\u7528 Center + ConstrainedBox(maxWidth: designSurface.maxWidth) \u5939\u6301\uFF0C\u7981\u6B62\u5168\u5C4F\u62C9\u4F38",
6528
+ "\u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B Scaffold/SafeArea/AppBar \u548C\u9875\u9762 padding\uFF0C\u53EA\u6709\u660E\u786E\u6D4B\u5F97\u7684\u5C40\u90E8\u6D6E\u5C42/\u5361\u7247\u5BB9\u5668\u624D\u505A clamp",
6529
+ "Sketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u5C5E\u4E8E\u8BBE\u5907\u7CFB\u7EDF chrome\uFF0C\u4E0D\u5C5E\u4E8E\u9875\u9762\u4E1A\u52A1 UI\uFF0C\u7981\u6B62\u76F4\u63A5\u8FD8\u539F\u5230 Flutter \u9875\u9762",
6527
6530
  "\u82E5\u8282\u70B9\u540C\u65F6\u51FA\u73B0 f \u4E0E vf\uFF0C\u5BB9\u5668\u5C3A\u5BF8\u548C\u5E95\u90E8\u89C6\u89C9\u95F4\u8DDD\u4F18\u5148\u4F7F\u7528 vf\uFF0C\u4E0D\u8981\u53EA\u6284\u903B\u8F91 frame",
6528
6531
  "\u82E5 compact \u8FD4\u56DE selectionContext.autoPromoted=true\uFF0C\u8BF4\u660E\u4E4B\u524D\u8BEF\u9009\u4E2D\u4E86\u5B50\u56FE\u5C42\uFF0C\u4E0D\u8981\u628A\u5185\u5C42 glyph \u5F53\u6574\u9875\u5408\u540C",
6529
6532
  "\u4EE3\u7801\u751F\u6210\u540E\u5FC5\u987B\u8C03\u7528 validate_restoration \u6821\u9A8C\u9875\u9762\u9AA8\u67B6\u3001\u8D44\u4EA7\u6765\u6E90\u548C\u771F\u5B9E\u8DEF\u7531"
@@ -6628,31 +6631,51 @@ function hasCodePropertyLiteral(codeContent, property, value) {
6628
6631
  const escapedValue = String(value).replace(".", "\\.");
6629
6632
  return new RegExp(`${property}\\s*:\\s*${escapedValue}(?:\\.0+)?\\b`).test(codeContent);
6630
6633
  }
6631
- function hasResponsiveSurfaceConstraint(codeContent, designWidth) {
6634
+ function collectPatternEvidence(codeContent, patterns) {
6635
+ return patterns.filter(({ pattern }) => pattern.test(codeContent)).map(({ label }) => label);
6636
+ }
6637
+ function detectSystemStatusBarRenderEvidence(codeContent) {
6638
+ return collectPatternEvidence(codeContent, [
6639
+ { pattern: /['\"]9:41['\"]/, label: "9:41" },
6640
+ { pattern: /signal\.svg/i, label: "signal.svg" },
6641
+ { pattern: /wifi\.svg/i, label: "wifi.svg" },
6642
+ { pattern: /battery\.svg/i, label: "battery.svg" },
6643
+ { pattern: /\b_StatusBar[A-Za-z0-9_]*\b/, label: "_StatusBar*" },
6644
+ { pattern: /\bStatusBar[A-Za-z0-9_]*\b/, label: "StatusBar*" },
6645
+ { pattern: /\bstatusBar[A-Za-z0-9_]*\b/, label: "statusBar*" }
6646
+ ]);
6647
+ }
6648
+ function detectFullPageArtboardClampEvidence(codeContent, designWidth) {
6632
6649
  const escapedWidth = String(designWidth).replace(".", "\\.");
6633
- const directPatterns = [
6634
- new RegExp(`maxWidth\\s*:\\s*${escapedWidth}(?:\\.0+)?\\b`),
6635
- new RegExp(`width\\s*:\\s*${escapedWidth}(?:\\.0+)?\\b`),
6636
- /ConstrainedBox\s*\(/,
6637
- /BoxConstraints\s*\([^)]*maxWidth\s*:/,
6638
- /LayoutBuilder\s*\(/,
6639
- /MediaQuery\.(sizeOf|of)\(/,
6640
- /math\.(min|max)\(/,
6641
- /clamp\(/
6642
- ];
6643
- return directPatterns.some((pattern) => pattern.test(codeContent));
6644
- }
6645
- function hasWideStretchRisk(codeContent) {
6646
- const edgePinnedPositioned = /Positioned\([\s\S]{0,220}left\s*:\s*[-\d.]+[\s\S]{0,220}right\s*:\s*[-\d.]+/.test(codeContent) || /Positioned\([\s\S]{0,220}right\s*:\s*[-\d.]+[\s\S]{0,220}left\s*:\s*[-\d.]+/.test(codeContent);
6647
- return edgePinnedPositioned || /SizedBox\.expand\s*\(/.test(codeContent) || /double\.infinity/.test(codeContent);
6650
+ const evidence = collectPatternEvidence(codeContent, [
6651
+ { pattern: new RegExp(`_designSurfaceWidth\\s*=\\s*${escapedWidth}(?:\\.0+)?\\b`), label: `_designSurfaceWidth = ${designWidth}` },
6652
+ { pattern: new RegExp(`maxWidth\\s*:\\s*${escapedWidth}(?:\\.0+)?\\b`), label: `maxWidth: ${designWidth}` },
6653
+ { pattern: new RegExp(`width\\s*:\\s*${escapedWidth}(?:\\.0+)?\\b`), label: `width: ${designWidth}` },
6654
+ { pattern: /ConstrainedBox\s*\(/, label: "ConstrainedBox" },
6655
+ { pattern: /BoxConstraints\s*\([^)]*maxWidth\s*:/, label: "BoxConstraints(maxWidth: ...)" },
6656
+ { pattern: /LayoutBuilder\s*\(/, label: "LayoutBuilder" },
6657
+ { pattern: /math\.(min|max)\(/, label: "math.min/math.max" },
6658
+ { pattern: /constraints\.maxWidth/, label: "constraints.maxWidth" },
6659
+ { pattern: /Align\s*\(/, label: "Align" },
6660
+ { pattern: /Center\s*\(/, label: "Center" },
6661
+ { pattern: /SizedBox\s*\([^)]*width\s*:/, label: "SizedBox(width: ...)" }
6662
+ ]);
6663
+ const hasExplicitClampWidth = evidence.some((item) => item.startsWith("_designSurfaceWidth") || item.startsWith("maxWidth:") || item.startsWith("width:"));
6664
+ const hasResponsiveClamp = evidence.includes("LayoutBuilder") && evidence.includes("math.min/math.max") && evidence.includes("constraints.maxWidth");
6665
+ const hasCenteredShell = hasExplicitClampWidth && evidence.some((item) => item === "ConstrainedBox" || item === "BoxConstraints(maxWidth: ...)" || item === "Align" || item === "Center" || item === "SizedBox(width: ...)");
6666
+ return hasResponsiveClamp || hasCenteredShell ? evidence : [];
6648
6667
  }
6649
6668
  function collectVisualFrameContracts(node, bucket = []) {
6669
+ var _a;
6650
6670
  if (!node) {
6651
6671
  return bucket;
6652
6672
  }
6653
6673
  if (node.f && node.vf) {
6654
6674
  const hasVisualDelta = node.f.some((value, index) => value !== node.vf[index]);
6655
- if (hasVisualDelta) {
6675
+ const hasVisualDecoration = Boolean(
6676
+ node.bg || node.gd || node.bd || node.token || ((_a = node.sh) == null ? void 0 : _a.length) || node.r !== void 0
6677
+ );
6678
+ if (hasVisualDelta && hasVisualDecoration) {
6656
6679
  bucket.push({
6657
6680
  nodeName: node.n || node.t || "unknown",
6658
6681
  frame: node.f,
@@ -6665,6 +6688,15 @@ function collectVisualFrameContracts(node, bucket = []) {
6665
6688
  }
6666
6689
  return bucket;
6667
6690
  }
6691
+ function extractRouteChunk(routeContent, routeIndex) {
6692
+ const blockStart = routeContent.lastIndexOf("GetPage(", routeIndex);
6693
+ const start = blockStart === -1 ? routeIndex : blockStart;
6694
+ const nextBlockStart = routeContent.indexOf("GetPage(", routeIndex + 1);
6695
+ if (nextBlockStart === -1) {
6696
+ return routeContent.slice(start);
6697
+ }
6698
+ return routeContent.slice(start, nextBlockStart);
6699
+ }
6668
6700
  function resolveProjectAssetPath(projectPath, assetPath) {
6669
6701
  return path20.join(projectPath, assetPath);
6670
6702
  }
@@ -6744,29 +6776,26 @@ function buildContractValidator(payload, codeContent) {
6744
6776
  });
6745
6777
  }
6746
6778
  }
6747
- const needsStatusBar = navCopyLedger.includes("9:41") || hasAnyPattern(JSON.stringify(payload.tree || {}), [/"Signal"/, /"WiFi"/, /"Battery"/]);
6748
- if (needsStatusBar) {
6749
- requiredBlocks += 1;
6750
- if (hasAnyPattern(codeContent, [/9:41/, /Signal/, /WiFi/, /Battery/, /statusBar/i])) {
6751
- matchedBlocks += 1;
6752
- } else {
6753
- findings.push({
6754
- id: "missing_status_bar_block",
6755
- severity: "warning",
6756
- message: "\u8BBE\u8BA1\u7A3F\u9876\u90E8\u72B6\u6001\u680F\u5757\u672A\u843D\u5730\uFF0C\u5F53\u524D\u9875\u9762\u9AA8\u67B6\u4ECD\u7136\u4E0D\u5B8C\u6574\u3002",
6757
- suggestion: "\u5982\u679C\u76EE\u6807\u662F 1:1 \u8FD8\u539F\uFF0C\u9700\u628A 9:41 / Signal / WiFi / Battery \u8FD9\u7EC4\u9876\u90E8\u5757\u8865\u56DE\u3002"
6758
- });
6759
- }
6779
+ const systemStatusBarEvidence = detectSystemStatusBarRenderEvidence(codeContent);
6780
+ if (systemStatusBarEvidence.length > 0) {
6781
+ findings.push({
6782
+ id: "system_status_bar_rendered",
6783
+ severity: "error",
6784
+ message: "\u4EE3\u7801\u4E2D\u76F4\u63A5\u6E32\u67D3\u4E86 Sketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u7B49\u8BBE\u5907\u7CFB\u7EDF chrome\uFF1B\u8FD9\u4E9B\u5143\u7D20\u4E0D\u5E94\u88AB\u753B\u8FDB Flutter \u9875\u9762\u3002",
6785
+ evidence: systemStatusBarEvidence,
6786
+ suggestion: "\u6539\u7528 Scaffold + SafeArea/AppBar \u5904\u7406\u9876\u90E8\u5B89\u5168\u533A\u57DF\uFF0C\u4E0D\u8981\u628A 9:41 / signal / wifi / battery \u8FD8\u539F\u4E3A\u4E1A\u52A1 UI\u3002"
6787
+ });
6760
6788
  }
6761
6789
  const designWidth = ((_d = payload.designSurface) == null ? void 0 : _d.maxWidth) || ((_e = payload.artboard) == null ? void 0 : _e.w);
6762
6790
  if (designWidth && designWidth <= 430) {
6763
- const isClamped = hasResponsiveSurfaceConstraint(codeContent, designWidth);
6764
- if (hasWideStretchRisk(codeContent) && !isClamped) {
6791
+ const clampEvidence = detectFullPageArtboardClampEvidence(codeContent, designWidth);
6792
+ if (clampEvidence.length > 0) {
6765
6793
  findings.push({
6766
- id: "design_surface_constraint_missing",
6794
+ id: "full_page_artboard_clamp_detected",
6767
6795
  severity: "error",
6768
- message: `\u5F53\u524D\u8BBE\u8BA1\u7A3F\u4E3A ${designWidth} \u5BBD\u79FB\u52A8\u7AEF\u753B\u677F\uFF0C\u4F46\u4EE3\u7801\u672A\u68C0\u6D4B\u5230\u5BBD\u5C4F\u5939\u6301\u7EA6\u675F\uFF0C\u5BBD\u7A97\u53E3\u4E0B\u4F1A\u88AB\u76F4\u63A5\u62C9\u4F38\u3002`,
6769
- suggestion: "\u5916\u5C42\u5148\u7528 Center + ConstrainedBox(maxWidth: designSurface.maxWidth) \u6216\u7B49\u6548\u7EA6\u675F\uFF0C\u518D\u5728\u7EA6\u675F\u5185\u4F7F\u7528 Positioned/Stack\u3002"
6796
+ message: `\u5F53\u524D\u9875\u9762\u770B\u8D77\u6765\u628A\u6574\u9875\u9501\u6210\u4E86 ${designWidth} \u5BBD design surface/artboard \u58F3\u5B50\uFF1B\u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B\u5E03\u5C40\u4E0E\u9875\u9762 padding \u9002\u914D\uFF0C\u4E0D\u5E94\u6574\u9875 clamp\u3002`,
6797
+ evidence: clampEvidence,
6798
+ suggestion: "\u6539\u7528 Scaffold + SafeArea + ListView/AppBar + \u9875\u9762 padding \u7684\u771F\u5B9E\u9875\u9762\u9AA8\u67B6\uFF1B\u53EA\u6709\u660E\u786E\u6D4B\u5F97\u7684\u5C40\u90E8\u6A21\u6001\u6216\u6D6E\u5C42\u5BB9\u5668\u624D\u505A clamp\u3002"
6770
6799
  });
6771
6800
  }
6772
6801
  }
@@ -6912,7 +6941,7 @@ function buildRouteReviewValidator(args, codeContent) {
6912
6941
  suggestion: "\u751F\u6210\u9875\u9762\u540E\u5FC5\u987B\u786E\u8BA4\u771F\u5B9E\u8DEF\u7531\u5DF2\u7ECF\u63A5\u901A\uFF0C\u4E0D\u80FD\u505C\u7559\u5728\u5B64\u7ACB\u9875\u9762\u6587\u4EF6\u3002"
6913
6942
  });
6914
6943
  } else {
6915
- const routeChunk = routeContent.slice(routeIndex, routeIndex + 240);
6944
+ const routeChunk = extractRouteChunk(routeContent, routeIndex);
6916
6945
  routeConnected = true;
6917
6946
  if (/_ComingSoonPage/.test(routeChunk)) {
6918
6947
  routeConnected = false;