openyida 2026.9.21 → 2026.9.22-beta.2

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 (334) hide show
  1. package/README.md +14 -20
  2. package/bin/yida.js +6 -11
  3. package/lib/app/app-list.js +3 -7
  4. package/lib/app/canvas-compile.js +12 -22
  5. package/lib/app/check-prd-completeness.js +0 -7
  6. package/lib/app/create-app.js +1 -4
  7. package/lib/app/create-form/args.js +12 -37
  8. package/lib/app/create-form/batch.js +11 -86
  9. package/lib/app/create-form.js +86 -193
  10. package/lib/app/create-page.js +17 -84
  11. package/lib/app/custom-theme.js +0 -11
  12. package/lib/app/form-field-validator.js +41 -26
  13. package/lib/app/form-open-guard.js +10 -97
  14. package/lib/app/get-form-config.js +0 -1
  15. package/lib/app/inline-css-guard.js +31 -1
  16. package/lib/app/services/form-compiler.js +4 -2
  17. package/lib/app/theme-from-design.js +41 -144
  18. package/lib/app/theme-presets.js +1 -1
  19. package/lib/app/update-app.js +13 -63
  20. package/lib/asset/ai-image.js +9 -59
  21. package/lib/asset/asset-cmd.js +7 -18
  22. package/lib/asset/asset-plan.js +9 -102
  23. package/lib/asset/asset-resolve.js +10 -55
  24. package/lib/asset/asset-status.js +4 -5
  25. package/lib/asset/host-capabilities.js +2 -11
  26. package/lib/asset/url-verify.js +4 -19
  27. package/lib/auth/dws-sync.js +148 -0
  28. package/lib/auth/token-auth.js +73 -9
  29. package/lib/auth/token-store.js +50 -0
  30. package/lib/connector/connector-test.js +5 -19
  31. package/lib/connector/contract.js +1 -3
  32. package/lib/core/agent-capabilities.js +16 -19
  33. package/lib/core/command-manifest.js +40 -329
  34. package/lib/core/locales/en.js +17 -74
  35. package/lib/core/locales/zh.js +16 -73
  36. package/lib/core/redact.js +10 -15
  37. package/lib/core/sample.js +30 -72
  38. package/lib/core/utils.js +4 -0
  39. package/lib/design-plan/design-plan.js +4 -51
  40. package/lib/design-plan/init.js +26 -121
  41. package/lib/design-plan/materialize.js +348 -451
  42. package/lib/design-plan/normalize.js +29 -74
  43. package/lib/design-plan/parallel.js +16 -71
  44. package/lib/design-plan/patch.js +16 -63
  45. package/lib/design-plan/preview.js +8 -6
  46. package/lib/design-plan/validate.js +11 -71
  47. package/lib/process/create-process.js +50 -84
  48. package/lib/samples/openyida-scaffold/canvas-form-drawer.canvas.jsx +90 -20
  49. package/lib/samples/openyida-scaffold/canvas-nav/content.jsx +13 -93
  50. package/lib/samples/openyida-scaffold/canvas-nav/data.jsx +18 -100
  51. package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +4 -6
  52. package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +5 -5
  53. package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +2 -1
  54. package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +1 -1
  55. package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +9 -15
  56. package/lib/samples/yida-canvas-table-form/table-form-batch-submit.canvas.jsx +83 -9
  57. package/lib/samples/yida-rechart/trend-combo.canvas.jsx +87 -14
  58. package/package.json +1 -3
  59. package/scripts/postinstall.js +3 -3
  60. package/yida-skills/SKILL.md +16 -19
  61. package/yida-skills/references/official-example-schema-patterns.md +1 -1
  62. package/yida-skills/references/yida-api.md +0 -4
  63. package/yida-skills/skills/yida-app/SKILL.md +23 -46
  64. package/yida-skills/skills/yida-app/workflow/parallel-work.md +6 -15
  65. package/yida-skills/skills/yida-app/workflow/plan/step-1-understand.md +1 -1
  66. package/yida-skills/skills/yida-app/workflow/plan/step-2-confirm.md +1 -1
  67. package/yida-skills/skills/yida-app/workflow/plan/step-4-deliver.md +15 -29
  68. package/yida-skills/skills/yida-app/workflow/plan/workflow.md +11 -29
  69. package/yida-skills/skills/yida-app/workflow/step-1-resource-context.md +2 -4
  70. package/yida-skills/skills/yida-app/workflow/step-2-design.md +9 -23
  71. package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +4 -6
  72. package/yida-skills/skills/yida-app/workflow/step-4-forms-processes.md +4 -15
  73. package/yida-skills/skills/yida-app/workflow/step-6-main-page.md +4 -6
  74. package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +9 -15
  75. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +11 -25
  76. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +28 -68
  77. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +43 -42
  78. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +44 -60
  79. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-theme-provider.md +50 -72
  80. package/yida-skills/skills/yida-canvas-custom-page/references/component-library-guide.md +1 -13
  81. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +1 -140
  82. package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +72 -101
  83. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +32 -35
  84. package/yida-skills/skills/yida-canvas-custom-page/scripts/build-canvas-theme.js +3 -29
  85. package/yida-skills/skills/yida-canvas-custom-page/scripts/canvas-theme-provider.template.jsx +6 -69
  86. package/yida-skills/skills/yida-canvas-data-binding/SKILL.md +0 -26
  87. package/yida-skills/skills/yida-create-app/SKILL.md +0 -2
  88. package/yida-skills/skills/yida-create-form-page/SKILL.md +58 -72
  89. package/yida-skills/skills/yida-create-form-page/references/advanced-form-modes.md +5 -5
  90. package/yida-skills/skills/yida-create-form-page/references/association-form-field.md +4 -4
  91. package/yida-skills/skills/yida-create-form-page/references/batch-forms.md +5 -6
  92. package/yida-skills/skills/yida-create-form-page/references/field-definition-guide.md +19 -7
  93. package/yida-skills/skills/yida-create-form-page/references/form-field-properties.md +44 -62
  94. package/yida-skills/skills/yida-create-page/SKILL.md +6 -14
  95. package/yida-skills/skills/yida-create-process/SKILL.md +2 -13
  96. package/yida-skills/skills/yida-custom-page/SKILL.md +0 -2
  97. package/yida-skills/skills/yida-custom-page/references/design-system.md +1 -1
  98. package/yida-skills/skills/yida-dashboard/SKILL.md +4 -5
  99. package/yida-skills/skills/yida-data-management/SKILL.md +2 -4
  100. package/yida-skills/skills/yida-data-management/references/data-format-guide.md +4 -4
  101. package/yida-skills/skills/yida-design/SKILL.md +14 -29
  102. package/yida-skills/skills/yida-design/references/app/blueprint.md +70 -0
  103. package/yida-skills/skills/yida-design/references/app/navigation-patterns.md +43 -0
  104. package/yida-skills/skills/yida-design/references/app/role-journey.md +30 -0
  105. package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +42 -67
  106. package/yida-skills/skills/yida-design/references/asset-workflow.md +2 -6
  107. package/yida-skills/skills/yida-design/references/design-mode.md +4 -4
  108. package/yida-skills/skills/yida-design/references/page-quality-gates.md +38 -26
  109. package/yida-skills/skills/yida-design/references/style-design-selection.md +137 -0
  110. package/yida-skills/skills/yida-design/references/style-designs/_design-md-template.md +185 -0
  111. package/yida-skills/skills/yida-design/references/style-designs/aqua-service-progress-dashboard.md +242 -0
  112. package/yida-skills/skills/yida-design/references/style-designs/blue-insight-operations-dashboard.md +243 -0
  113. package/yida-skills/skills/yida-design/references/style-designs/blue-productivity-insight-workbench.md +242 -0
  114. package/yida-skills/skills/yida-design/references/style-designs/command-filter-card-console.md +304 -0
  115. package/yida-skills/skills/yida-design/references/style-designs/contrast-command-analytics-workbench.md +261 -0
  116. package/yida-skills/skills/yida-design/references/style-designs/dark-stage-analytic-dashboard.md +369 -0
  117. package/yida-skills/skills/yida-design/references/style-designs/filterable-card-catalog.md +354 -0
  118. package/yida-skills/skills/yida-design/references/style-designs/green-timeline-progress-workbench.md +250 -0
  119. package/yida-skills/skills/yida-design/references/style-designs/registry.md +117 -0
  120. package/yida-skills/skills/yida-design/references/style-designs/soft-analytic-workbench.md +348 -0
  121. package/yida-skills/skills/yida-design/references/style-designs/soft-blue-grid-analytic-dashboard.md +658 -0
  122. package/yida-skills/skills/yida-design/references/style-designs/soft-bordered-analytic-workbench.md +385 -0
  123. package/yida-skills/skills/yida-design/references/style-designs/soft-curated-filter-gallery.md +300 -0
  124. package/yida-skills/skills/yida-design/references/style-designs/soft-modular-analytic-workbench.md +404 -0
  125. package/yida-skills/skills/yida-design/references/style-designs/soft-progress-analytics-workbench.md +382 -0
  126. package/yida-skills/skills/yida-design/references/style-designs/soft-timeline-analytics-workbench.md +367 -0
  127. package/yida-skills/skills/yida-design/references/style-designs/teal-rail-analytics-workbench.md +341 -0
  128. package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +432 -350
  129. package/yida-skills/skills/yida-design/references/visual-decision-engine.md +143 -19
  130. package/yida-skills/skills/yida-design/references/visual-scaffold-recipes.md +27 -15
  131. package/yida-skills/skills/yida-design/sub_skill/page-design/SKILL.md +0 -4
  132. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +8 -22
  133. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/README.md +10 -14
  134. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/build-plan-template.html +4 -9
  135. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +27 -49
  136. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +154 -33
  137. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-design.md +127 -48
  138. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-theme-selection.md +51 -37
  139. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +48 -43
  140. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/validate_design_themes.py +190 -0
  141. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/README.md +98 -0
  142. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-media-grid.md +339 -0
  143. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-modular-clarity.md +348 -0
  144. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-structured-clarity.md +344 -0
  145. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ambient-halo-layered.md +345 -0
  146. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-focus-layered.md +355 -0
  147. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-luminous-modular.md +377 -0
  148. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/deep-stage-duotone.md +352 -0
  149. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/hairline-runway-clarity.md +389 -0
  150. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/high-contrast-modular.md +364 -0
  151. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/index.json +329 -0
  152. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/interlocked-vivid-modules.md +348 -0
  153. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/matrix-grid-focus.md +345 -0
  154. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/media-rail-inspector.md +379 -0
  155. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mist-layered-signal.md +347 -0
  156. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/modular-rail-signal.md +352 -0
  157. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mono-grid-signal.md +386 -0
  158. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ribbon-ledger-lift.md +384 -0
  159. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/segmented-meter-clarity.md +388 -0
  160. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/split-rail-precision.md +341 -0
  161. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/status-framed-media-grid.md +361 -0
  162. package/yida-skills/skills/yida-design/workflow/output-design.md +375 -117
  163. package/yida-skills/skills/yida-design/workflow/output-prd.md +185 -0
  164. package/yida-skills/skills/yida-design/workflow/step-1-read-brief.md +1 -1
  165. package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +29 -33
  166. package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +1 -3
  167. package/yida-skills/skills/yida-design/workflow/step-5-visual-states.md +106 -22
  168. package/yida-skills/skills/yida-design/workflow/step-6-handoff.md +22 -15
  169. package/yida-skills/skills/yida-form-permission/SKILL.md +0 -6
  170. package/yida-skills/skills/yida-image-assets/SKILL.md +50 -73
  171. package/yida-skills/skills/yida-image-assets/references/manifest-contract.md +52 -82
  172. package/yida-skills/skills/yida-image-assets/references/source-policy.md +15 -14
  173. package/yida-skills/skills/yida-integration/SKILL.md +0 -1
  174. package/yida-skills/skills/yida-login/SKILL.md +0 -2
  175. package/yida-skills/skills/yida-nav-group/SKILL.md +2 -4
  176. package/yida-skills/skills/yida-nav-shell/SKILL.md +12 -36
  177. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +136 -79
  178. package/yida-skills/skills/yida-page-config/SKILL.md +4 -13
  179. package/yida-skills/skills/yida-prd/SKILL.md +3 -5
  180. package/yida-skills/skills/yida-prd/references/app/blueprint.md +4 -4
  181. package/yida-skills/skills/yida-prd/references/app/navigation-patterns.md +3 -6
  182. package/yida-skills/skills/yida-prd/references/app/role-journey.md +3 -5
  183. package/yida-skills/skills/yida-prd/references/plan-content.md +0 -4
  184. package/yida-skills/skills/yida-prd/workflow/output-prd.md +11 -18
  185. package/yida-skills/skills/yida-prd/workflow/plan-business.md +4 -4
  186. package/yida-skills/skills/yida-prd/workflow/step-2-information-architecture.md +8 -11
  187. package/yida-skills/skills/yida-publish-page/SKILL.md +1 -9
  188. package/yida-skills/skills/yida-requirement-analysis/SKILL.md +39 -10
  189. package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +71 -40
  190. package/yida-skills/skills-index.json +16 -36
  191. package/lib/app/application-entry-urls.js +0 -31
  192. package/lib/app/application-style.js +0 -69
  193. package/lib/app/canvas-icon-exports.json +0 -6160
  194. package/lib/app/canvas-icon-guard.js +0 -87
  195. package/lib/app/canvas-navigation-guard.js +0 -84
  196. package/lib/app/canvas-path-guard.js +0 -78
  197. package/lib/app/canvas-theme-guard.js +0 -184
  198. package/lib/app/form-data-response-guard.js +0 -57
  199. package/lib/asset/asset-execution.js +0 -79
  200. package/lib/core/css-structure.js +0 -37
  201. package/lib/design/check-design.js +0 -51
  202. package/lib/design/document.js +0 -458
  203. package/lib/design/icon-contrast.js +0 -85
  204. package/lib/design/page-content.js +0 -11
  205. package/lib/design-plan/artifact-updates.js +0 -117
  206. package/lib/design-plan/confirmation.js +0 -13
  207. package/lib/design-plan/entry-navigation.js +0 -97
  208. package/lib/design-plan/navigation-policy.js +0 -38
  209. package/lib/design-plan/rebase.js +0 -60
  210. package/lib/design-plan/themes.js +0 -101
  211. package/lib/design-plan/visual-policy.js +0 -42
  212. package/lib/samples/openyida-scaffold/canvas-admin-entry.jsx +0 -62
  213. package/lib/samples/openyida-scaffold/canvas-navigation.jsx +0 -56
  214. package/lib/samples/openyida-scaffold/canvas-view-state.jsx +0 -74
  215. package/yida-skills/skills/yida-app/references/entry-navigation.md +0 -193
  216. package/yida-skills/skills/yida-canvas-custom-page/references/view-state-recovery.md +0 -52
  217. package/yida-skills/skills/yida-canvas-data-binding/references/business-action-permissions.md +0 -31
  218. package/yida-skills/skills/yida-design/references/application-style-library.md +0 -93
  219. package/yida-skills/skills/yida-design/references/application-theme-consistency.md +0 -150
  220. package/yida-skills/skills/yida-design/references/native-form-styles.md +0 -208
  221. package/yida-skills/skills/yida-design/references/navigation-decision.md +0 -53
  222. package/yida-skills/skills/yida-design/references/page-continuity.md +0 -42
  223. package/yida-skills/skills/yida-design/references/theme/application-style-recipes.css +0 -58
  224. package/yida-skills/skills/yida-design/references/theme-selection.md +0 -67
  225. package/yida-skills/skills/yida-design/scripts/validate_design_themes.py +0 -302
  226. package/yida-skills/skills/yida-design/templates/application-styles.json +0 -398
  227. package/yida-skills/skills/yida-design/templates/design-themes/README.md +0 -73
  228. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/app_theme.css +0 -748
  229. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/design.md +0 -274
  230. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/form-layout.json +0 -15
  231. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/app_theme.css +0 -748
  232. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/design.md +0 -274
  233. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/form-layout.json +0 -14
  234. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/app_theme.css +0 -748
  235. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/design.md +0 -274
  236. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/form-layout.json +0 -13
  237. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/app_theme.css +0 -748
  238. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/design.md +0 -274
  239. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/form-layout.json +0 -14
  240. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/app_theme.css +0 -748
  241. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/design.md +0 -274
  242. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/form-layout.json +0 -14
  243. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/app_theme.css +0 -748
  244. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/design.md +0 -274
  245. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/form-layout.json +0 -14
  246. package/yida-skills/skills/yida-design/templates/design-themes/app-line/app_theme.css +0 -748
  247. package/yida-skills/skills/yida-design/templates/design-themes/app-line/design.md +0 -274
  248. package/yida-skills/skills/yida-design/templates/design-themes/app-line/form-layout.json +0 -13
  249. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/app_theme.css +0 -748
  250. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/design.md +0 -274
  251. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/form-layout.json +0 -14
  252. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/app_theme.css +0 -754
  253. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/design.md +0 -279
  254. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/form-layout.json +0 -13
  255. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/app_theme.css +0 -748
  256. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/design.md +0 -274
  257. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/form-layout.json +0 -13
  258. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/app_theme.css +0 -748
  259. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/design.md +0 -274
  260. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/form-layout.json +0 -14
  261. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/app_theme.css +0 -748
  262. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/design.md +0 -274
  263. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/form-layout.json +0 -14
  264. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/app_theme.css +0 -758
  265. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/design.md +0 -281
  266. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/form-layout.json +0 -14
  267. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/app_theme.css +0 -748
  268. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/design.md +0 -274
  269. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/form-layout.json +0 -14
  270. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/app_theme.css +0 -748
  271. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/design.md +0 -274
  272. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/form-layout.json +0 -14
  273. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/app_theme.css +0 -754
  274. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/design.md +0 -279
  275. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/form-layout.json +0 -14
  276. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/app_theme.css +0 -752
  277. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/design.md +0 -278
  278. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/form-layout.json +0 -13
  279. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/app_theme.css +0 -748
  280. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/design.md +0 -274
  281. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/form-layout.json +0 -14
  282. package/yida-skills/skills/yida-design/templates/design-themes/basic-tokens.json +0 -118
  283. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/app_theme.css +0 -690
  284. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/design.md +0 -382
  285. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/form-layout.json +0 -13
  286. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +0 -691
  287. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/design.md +0 -380
  288. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/form-layout.json +0 -13
  289. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/app_theme.css +0 -696
  290. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/design.md +0 -378
  291. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/form-layout.json +0 -13
  292. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/app_theme.css +0 -689
  293. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/design.md +0 -238
  294. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/form-layout.json +0 -13
  295. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/app_theme.css +0 -692
  296. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/design.md +0 -375
  297. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/form-layout.json +0 -13
  298. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/app_theme.css +0 -691
  299. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/design.md +0 -362
  300. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/form-layout.json +0 -13
  301. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/app_theme.css +0 -691
  302. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/design.md +0 -409
  303. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/form-layout.json +0 -13
  304. package/yida-skills/skills/yida-design/templates/design-themes/index.json +0 -464
  305. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/app_theme.css +0 -701
  306. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/design.md +0 -379
  307. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/form-layout.json +0 -13
  308. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/app_theme.css +0 -691
  309. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/design.md +0 -404
  310. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/form-layout.json +0 -13
  311. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/app_theme.css +0 -698
  312. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/design.md +0 -389
  313. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/form-layout.json +0 -13
  314. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/app_theme.css +0 -691
  315. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/design.md +0 -372
  316. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/form-layout.json +0 -13
  317. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/app_theme.css +0 -690
  318. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/design.md +0 -455
  319. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/form-layout.json +0 -13
  320. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/app_theme.css +0 -698
  321. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/design.md +0 -394
  322. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/form-layout.json +0 -13
  323. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/app_theme.css +0 -692
  324. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/design.md +0 -391
  325. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/form-layout.json +0 -13
  326. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/app_theme.css +0 -711
  327. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/design.md +0 -408
  328. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/form-layout.json +0 -13
  329. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/app_theme.css +0 -692
  330. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/design.md +0 -383
  331. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/form-layout.json +0 -13
  332. package/yida-skills/skills/yida-design/templates/navigation-styles.json +0 -769
  333. package/yida-skills/skills/yida-requirement-analysis/references/experience-groups.md +0 -79
  334. package/yida-skills/skills/yida-requirement-analysis/references/handoff.md +0 -68
@@ -2,10 +2,18 @@
2
2
 
3
3
  const path = require('path');
4
4
  const { CliError } = require('../core/cli-error');
5
- const { t } = require('../core/i18n');
6
5
  const { readJson } = require('./files');
7
6
 
8
- const { PLAN_SKILL_ROOT, loadThemeIndex, themeNavTheme } = require('./themes');
7
+ const PACKAGE_ROOT = path.resolve(__dirname, '..', '..');
8
+ const PLAN_SKILL_ROOT = path.join(
9
+ PACKAGE_ROOT,
10
+ 'yida-skills',
11
+ 'skills',
12
+ 'yida-design',
13
+ 'sub_skill',
14
+ 'yida-design-plan'
15
+ );
16
+ const THEME_INDEX_PATH = path.join(PLAN_SKILL_ROOT, 'templates', 'design-themes', 'index.json');
9
17
  const PAGE_PATTERN_INDEX_PATH = path.join(PLAN_SKILL_ROOT, 'templates', 'page-patterns', 'index.json');
10
18
 
11
19
  function clone(value) {
@@ -20,53 +28,6 @@ function compactSchema(plan) {
20
28
  return /^2(?:\.|$)/.test(String(plan.schemaVersion || ''));
21
29
  }
22
30
 
23
- // Validate before normalization writes properties (a string previously caused
24
- // a raw TypeError), and reuse this contract at fragment / init boundaries.
25
- function assertVisualFieldObjects(forUser, options = {}) {
26
- const prefix = options.prefix || 'visualStyle.forUser';
27
- const object = value => value !== null && typeof value === 'object' && !Array.isArray(value);
28
- const examples = {
29
- visualDirection: { label: '<label>', description: '<description>' },
30
- navigationStyle: { structure: 'top' },
31
- };
32
- const issues = [];
33
- const check = (value, field, example) => {
34
- if (value === undefined || object(value)) { return; }
35
- issues.push({ path: field, expectedType: 'object', receivedType: value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value,
36
- example, message: t('cli.design_plan_visual_object_required', field, JSON.stringify(example)) });
37
- };
38
- check(forUser, prefix, examples);
39
- if (object(forUser)) {
40
- for (const [field, example] of Object.entries(examples)) { check(forUser[field], `${prefix}.${field}`, example); }
41
- }
42
- if (issues.length) {
43
- throw new CliError(issues.map(issue => issue.message).join('\n'), {
44
- code: 'DESIGN_PLAN_VISUAL_FIELD_TYPE_INVALID',
45
- details: { ...issues[0], issues, ...(options.sourcePath ? { sourcePath: options.sourcePath } : {}) },
46
- });
47
- }
48
- }
49
-
50
- // Ordered business blocks provide one source for content, priority and coverage.
51
- // Explicit overrides remain authoritative; incomplete blocks stay visible to validation.
52
- function derivePageContent(page) {
53
- const blocks = page?.blocks;
54
- const filled = value => typeof value === 'string' && value.trim().length > 0;
55
- if (!Array.isArray(blocks) || !blocks.length || !blocks.every(block => block && typeof block === 'object'
56
- && !Array.isArray(block) && filled(block.name) && filled(block.purpose)
57
- && Object.keys(block).every(key => ['name', 'purpose'].includes(key)))) {return page;}
58
- const descriptions = blocks.map(block => `${block.name}:${block.purpose}`);
59
- return {
60
- ...page,
61
- blocks: descriptions,
62
- contentPriority: page.contentPriority === undefined ? blocks.map(block => block.name) : page.contentPriority,
63
- contentRichness: {
64
- ...page.contentRichness,
65
- contentLayers: page.contentRichness?.contentLayers === undefined ? descriptions : page.contentRichness.contentLayers,
66
- },
67
- };
68
- }
69
-
70
31
  function normalizeEquivalentAuthoring(plan) {
71
32
  const summary = plan.overview?.rolePermissionSummary;
72
33
  if (Array.isArray(summary)) {
@@ -219,7 +180,6 @@ function ensurePageRules(plan, pagePatternIndex) {
219
180
  const patterns = new Map(list(pagePatternIndex.patterns).map(pattern => [pattern.id, pattern]));
220
181
  const richnessDefaults = pagePatternIndex.contentRichness || {};
221
182
  for (const page of list((plan.pages || {}).customPageDetails)) {
222
- Object.assign(page, derivePageContent(page));
223
183
  const pattern = page.layoutPattern = page.layoutPattern || {};
224
184
  pattern.id = pattern.id || 'custom-page-pattern';
225
185
  const preset = patterns.get(pattern.id);
@@ -270,7 +230,7 @@ function selectedTheme(plan, themeIndex) {
270
230
  details: { themeId: selected.themeId },
271
231
  });
272
232
  }
273
- if (selected.templatePath && selected.templatePath !== theme.templatePath && selected.templatePath !== theme.legacyTemplatePath) {
233
+ if (selected.templatePath && selected.templatePath !== theme.templatePath) {
274
234
  throw new CliError('selectedTheme 的 themeId 与 templatePath 不属于主题索引中的同一记录', {
275
235
  code: 'DESIGN_PLAN_THEME_MISMATCH',
276
236
  details: { selectedTheme: selected },
@@ -278,42 +238,34 @@ function selectedTheme(plan, themeIndex) {
278
238
  }
279
239
  selected.label = selected.label || theme.label;
280
240
  selected.templatePath = theme.templatePath;
281
- selected.summary = selected.summary || [theme.styleSummary, selected.customText].filter(Boolean).join(';');
241
+ selected.summary = selected.summary || [theme.description, selected.customText].filter(Boolean).join(';');
282
242
  assertThemeProfile(forUser.themeProfile, theme);
283
243
  forUser.themeProfile = { ...(theme.defaultProfile || {}) };
284
- return { ...theme, navTheme: themeNavTheme(theme) };
244
+ return theme;
285
245
  }
286
246
 
287
- function pageApplicationDefaults(page) {
247
+ function pageApplicationDefaults(page, color) {
288
248
  const pattern = page.layoutPattern || {};
249
+ const colorUsage = color.usage || `${color.primaryColorName || '主题色'}用于主操作、关键焦点和选中状态,页面与卡片按项目配色适配保持协调`;
289
250
  return {
290
251
  pageId: page.pageId,
291
252
  pageName: page.name,
292
253
  layoutPatternMode: pattern.mode,
293
254
  layoutPatternId: pattern.id,
294
- firstScreenFocus: '',
295
- layout: '',
296
- responsive: '',
297
- acceptanceChecks: [],
298
255
  visualApplication: `继承项目设计系统的完整 Token、组件、状态与响应式规则,不改变 ${page.name} 的 ${pattern.id} 页面模式。`,
299
256
  surface: '画布、容器、边框、圆角与阴影按项目设计系统执行,不另写页面级标准。',
300
- primaryAction: '',
257
+ primaryAction: `按钮与动作层级按项目设计系统执行;${colorUsage}。`,
301
258
  states: '默认、悬停、按下、聚焦、禁用、加载、空态、错误、无权限和选中状态按项目设计系统执行。',
302
259
  };
303
260
  }
304
261
 
305
- function ensureVisual(plan, theme) {
262
+ function ensureVisual(plan) {
306
263
  const visual = plan.visualStyle;
307
264
  const forUser = visual.forUser;
308
265
  const selected = visual.internal.selectedTheme;
309
266
  const direction = forUser.visualDirection || {};
310
267
  const color = forUser.colorStrategy = forUser.colorStrategy || {};
311
- const navigation = forUser.navigationStyle = forUser.navigationStyle || {};
312
- if (theme.mode !== 'creative') {navigation.tone = theme.navTheme;}
313
- navigation.toneSource = theme.mode === 'creative' ? 'project_defined' : 'theme_derived';
314
- if (!['light', 'dark'].includes(navigation.tone)) {
315
- throw new CliError('visualStyle.forUser.navigationStyle.tone 必须是 light 或 dark', { code: 'DESIGN_PLAN_INVALID_NAVIGATION_TONE' });
316
- }
268
+ const navigation = forUser.navigationStyle || {};
317
269
  if (!direction.label || !direction.description) {
318
270
  throw new CliError('schemaVersion 2.0 必须提供 visualStyle.forUser.visualDirection.label 和 description', {
319
271
  code: 'DESIGN_PLAN_VISUAL_DIRECTION_REQUIRED',
@@ -325,10 +277,16 @@ function ensureVisual(plan, theme) {
325
277
  details: { structure: navigation.structure },
326
278
  });
327
279
  }
280
+ if (!['light', 'dark'].includes(navigation.tone)) {
281
+ throw new CliError('visualStyle.forUser.navigationStyle.tone 必须是 light 或 dark', {
282
+ code: 'DESIGN_PLAN_INVALID_NAVIGATION_TONE',
283
+ details: { tone: navigation.tone },
284
+ });
285
+ }
328
286
  const sourceApplications = new Map(list(forUser.pageApplications).map(item => [item.pageId || item.pageName, item]));
329
287
  forUser.pageApplications = list((plan.pages || {}).customPageDetails).map(page => {
330
288
  const source = sourceApplications.get(page.pageId) || sourceApplications.get(page.name) || {};
331
- const application = { ...pageApplicationDefaults(page), ...source };
289
+ const application = { ...pageApplicationDefaults(page, color), ...source };
332
290
  application.pageId = page.pageId;
333
291
  application.pageName = page.name;
334
292
  application.layoutPatternMode = (page.layoutPattern || {}).mode;
@@ -355,7 +313,7 @@ function ensureVisual(plan, theme) {
355
313
  missingAssets: [],
356
314
  notes: '需要图片时使用 yida-image-assets。',
357
315
  };
358
- forUser.designMdReady = forUser.designMdReady || '页面配色、布局和组件样式将整理为完整设计说明。';
316
+ forUser.designMdReady = forUser.designMdReady || 'materialize 将从所选完整主题模板生成 design.md。';
359
317
 
360
318
  const forDesignMd = visual.forDesignMd = visual.forDesignMd || {};
361
319
  forDesignMd.designTemplate = {
@@ -397,21 +355,18 @@ function normalizePlan(sourcePlan) {
397
355
  return sourcePlan;
398
356
  }
399
357
  const plan = clone(sourcePlan);
400
- assertVisualFieldObjects(plan.visualStyle?.forUser);
401
358
  normalizeEquivalentAuthoring(plan);
402
- const themeIndex = loadThemeIndex();
359
+ const themeIndex = readJson(THEME_INDEX_PATH, '主题索引');
403
360
  const pagePatternIndex = readJson(PAGE_PATTERN_INDEX_PATH, '页面模式索引');
404
361
  ensureOverview(plan);
405
362
  ensurePageRules(plan, pagePatternIndex);
406
- const theme = selectedTheme(plan, themeIndex);
407
- ensureVisual(plan, theme);
363
+ selectedTheme(plan, themeIndex);
364
+ ensureVisual(plan);
408
365
  return plan;
409
366
  }
410
367
 
411
368
  module.exports = {
412
369
  normalizePlan,
413
- assertVisualFieldObjects,
414
- derivePageContent,
415
370
  assertThemeProfile,
416
371
  ensureOverview,
417
372
  };
@@ -2,9 +2,7 @@
2
2
 
3
3
  const { createHash } = require('crypto');
4
4
  const { CliError } = require('../core/cli-error');
5
- const { t } = require('../core/i18n');
6
5
  const { readJson } = require('./files');
7
- const { assertVisualFieldObjects } = require('./normalize');
8
6
 
9
7
  const object = value => value && typeof value === 'object' && !Array.isArray(value);
10
8
 
@@ -12,14 +10,13 @@ function planBase(plan) {
12
10
  return { revision: plan.meta?.revision, digest: createHash('sha256').update(JSON.stringify(plan)).digest('hex') };
13
11
  }
14
12
 
15
- function readPart(file, role, base, allowed, supplied) {
16
- const part = supplied || readJson(file, `${role} 规划片段`);
13
+ function readPart(file, role, base, allowed) {
14
+ const part = readJson(file, `${role} 规划片段`);
17
15
  if (!object(part) || part.ready !== true || !object(part.facts)) {
18
16
  throw new CliError(`${role} 规划尚未完成,请补齐 facts 并设置 ready=true`, { code: 'DESIGN_PLAN_PART_NOT_READY' });
19
17
  }
20
18
  if (part.base?.revision !== base.revision || part.base?.digest !== base.digest) {
21
- throw new CliError(`${role} 规划来自旧版本,请根据当前计划重新整理`, { code: 'DESIGN_PLAN_STALE_PART',
22
- details: { sourcePath: file, expectedBase: base, actualBase: part.base, nextStep: t('design_plan.rebase_required') } });
19
+ throw new CliError(`${role} 规划来自旧版本,请根据当前计划重新整理`, { code: 'DESIGN_PLAN_STALE_PART' });
23
20
  }
24
21
  const unknown = Object.keys(part.facts).filter(key => !allowed.includes(key));
25
22
  if (unknown.length) {
@@ -28,64 +25,10 @@ function readPart(file, role, base, allowed, supplied) {
28
25
  return part.facts;
29
26
  }
30
27
 
31
- // Report all binding defects at once so agents can repair the existing part.
32
- function assertPageBindings(pages, applications, visualFile, businessFile) {
33
- const prefix = 'facts.visualStyle.forUser.pageApplications';
34
- const issues = [];
35
- const pageIds = [];
36
- pages.forEach((page, index) => {
37
- const field = `facts.pages.customPageDetails[${index}].pageId`;
38
- if (!object(page) || typeof page.pageId !== 'string' || !page.pageId.trim()) {
39
- issues.push({ sourcePath: businessFile, path: field, code: 'expected_nonempty_string' });
40
- } else if (pageIds.includes(page.pageId)) {
41
- issues.push({ sourcePath: businessFile, path: field, code: 'duplicate_page', pageId: page.pageId });
42
- } else { pageIds.push(page.pageId); }
43
- });
44
- const seen = new Set();
45
- if (!Array.isArray(applications)) {
46
- issues.push({ sourcePath: visualFile, path: prefix, code: 'expected_array' });
47
- } else {
48
- applications.forEach((item, index) => {
49
- const field = `${prefix}[${index}]`;
50
- if (!object(item)) {
51
- issues.push({ sourcePath: visualFile, path: field, code: 'expected_object' });
52
- return;
53
- }
54
- if (typeof item.pageId !== 'string' || !item.pageId.trim()) {
55
- issues.push({ sourcePath: visualFile, path: `${field}.pageId`, code: 'expected_nonempty_string' });
56
- } else {
57
- if (!pageIds.includes(item.pageId)) {
58
- issues.push({ sourcePath: visualFile, path: `${field}.pageId`, code: 'unexpected_page', pageId: item.pageId });
59
- }
60
- if (seen.has(item.pageId)) {
61
- issues.push({ sourcePath: visualFile, path: `${field}.pageId`, code: 'duplicate_page', pageId: item.pageId });
62
- }
63
- seen.add(item.pageId);
64
- }
65
- if (!Array.isArray(item.visualMemoryApplications)) {
66
- issues.push({ sourcePath: visualFile, path: `${field}.visualMemoryApplications`, code: 'expected_array' });
67
- }
68
- });
69
- }
70
- pageIds.filter(pageId => !seen.has(pageId)).forEach(pageId => {
71
- issues.push({ sourcePath: visualFile, path: prefix, code: 'missing_page', pageId });
72
- });
73
- if (issues.length) {
74
- const nextStep = t('design_plan.repair_page_bindings');
75
- const summary = issues.map(issue => `${issue.path}: ${issue.code}${issue.pageId ? ` (${issue.pageId})` : ''}`).join('; ');
76
- throw new CliError(`${nextStep} ${summary}`, {
77
- code: 'DESIGN_PLAN_PAGE_BINDINGS_REQUIRED',
78
- details: { sourcePath: visualFile, expectedPageIds: pageIds, issues, nextStep },
79
- });
80
- }
81
- }
82
-
83
- function mergeParts(source, businessFile, visualFile, options = {}) {
28
+ function mergeParts(source, businessFile, visualFile) {
84
29
  const base = planBase(source);
85
- const rebased = options.rebaseParts ? require('./rebase').rebaseParts(source, options.input, businessFile, visualFile) : [];
86
- const business = readPart(businessFile, 'business', base, ['overview', 'dataModels', 'businessFlows', 'pages', 'execution', 'meta'], rebased[0]);
87
- const visual = readPart(visualFile, 'visual', base, ['visualStyle'], rebased[1]);
88
- assertVisualFieldObjects(visual.visualStyle?.forUser, { prefix: 'facts.visualStyle.forUser', sourcePath: visualFile });
30
+ const business = readPart(businessFile, 'business', base, ['overview', 'dataModels', 'businessFlows', 'pages', 'execution', 'meta']);
31
+ const visual = readPart(visualFile, 'visual', base, ['visualStyle']);
89
32
  if (!object(business.overview) || !Array.isArray(business.dataModels) || !Array.isArray(business.businessFlows)
90
33
  || !Array.isArray(business.pages?.customPageDetails) || !object(visual.visualStyle)) {
91
34
  throw new CliError('业务片段需包含 overview/dataModels/businessFlows/pages;视觉片段需包含 visualStyle', { code: 'DESIGN_PLAN_PART_INCOMPLETE' });
@@ -94,17 +37,19 @@ function mergeParts(source, businessFile, visualFile, options = {}) {
94
37
  || Object.keys(business.meta).some(key => !['businessDomain', 'experienceTopology'].includes(key)))) {
95
38
  throw new CliError('业务 meta 仅填写 businessDomain/experienceTopology,版本由 CLI 维护', { code: 'DESIGN_PLAN_PART_CONFLICT' });
96
39
  }
97
- assertPageBindings(business.pages.customPageDetails, visual.visualStyle.forUser?.pageApplications, visualFile, businessFile);
40
+ const pageIds = business.pages.customPageDetails.map(page => page.pageId);
41
+ const applications = visual.visualStyle.forUser?.pageApplications;
42
+ if (!Array.isArray(applications) || applications.length !== pageIds.length
43
+ || new Set(applications.map(item => item.pageId)).size !== pageIds.length
44
+ || applications.some(item => !pageIds.includes(item.pageId) || !Array.isArray(item.visualMemoryApplications))) {
45
+ throw new CliError('视觉规划需按业务页面逐一完成 pageApplications,再合并产物', { code: 'DESIGN_PLAN_PAGE_BINDINGS_REQUIRED' });
46
+ }
98
47
  const plan = JSON.parse(JSON.stringify({ ...source, ...business, ...visual, meta: { ...source.meta, ...business.meta },
99
- ...(source.execution || business.execution ? { execution: { ...source.execution, ...business.execution,
100
- ...(source.execution?.appConfig || business.execution?.appConfig
101
- ? { appConfig: { ...source.execution?.appConfig, ...business.execution?.appConfig } } : {}),
102
- } } : {}),
48
+ execution: { ...source.execution, ...business.execution, appConfig: { ...source.execution?.appConfig, ...business.execution?.appConfig } },
103
49
  }));
104
50
  // Load after module initialization: patch also uses the materializer.
105
- if (require('./patch').invalidateConfirmation(plan, source) || plan.meta.status === 'draft') {
106
- plan.meta.status = 'awaiting_confirmation';
107
- }
51
+ require('./patch').invalidateConfirmation(plan);
52
+ plan.meta.status = 'awaiting_confirmation';
108
53
  return plan;
109
54
  }
110
55
 
@@ -1,9 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('path');
4
- const { isDeepStrictEqual } = require('util');
5
4
  const { CliError } = require('../core/cli-error');
6
- const { prepareArtifacts, prepareArtifactUpdate } = require('./materialize');
5
+ const { prepareArtifacts } = require('./materialize');
7
6
  const { readJson, writeFiles } = require('./files');
8
7
 
9
8
  const PROTECTED_PATHS = [
@@ -12,13 +11,10 @@ const PROTECTED_PATHS = [
12
11
  'meta.updatedAt',
13
12
  'meta.planState',
14
13
  'visualStyle.forUser.themeProfile',
15
- 'visualStyle.forUser.navigationStyle.tone',
16
- 'visualStyle.forUser.navigationStyle.toneSource',
17
- 'execution.appConfig.navTheme',
18
14
  ];
19
15
  const DANGEROUS_SEGMENTS = new Set(['__proto__', 'prototype', 'constructor']);
20
16
 
21
- function parsePath(pathExpression, options = {}) {
17
+ function parsePath(pathExpression) {
22
18
  const expression = String(pathExpression || '').trim();
23
19
  if (!expression || !/^[A-Za-z_$][\w$-]*(?:(?:\.(?:[A-Za-z_$][\w$-]*|--[\w-]+))|(?:\[\d+\]))*$/.test(expression)) {
24
20
  throw new CliError(`无效字段路径:${expression || '(empty)'}`, {
@@ -31,16 +27,11 @@ function parsePath(pathExpression, options = {}) {
31
27
  code: 'DESIGN_PLAN_UNSAFE_PATH',
32
28
  });
33
29
  }
34
- const protectedPaths = options.creative ? PROTECTED_PATHS.filter(field => field !== 'visualStyle.forUser.navigationStyle.tone') : PROTECTED_PATHS;
35
- if (protectedPaths.some(protectedPath => expression === protectedPath
30
+ if (PROTECTED_PATHS.some(protectedPath => expression === protectedPath
36
31
  || expression.startsWith(`${protectedPath}.`)
37
32
  || expression.startsWith(`${protectedPath}[`)
38
33
  || protectedPath.startsWith(`${expression}.`))) {
39
- const hint = expression.includes('themeProfile')
40
- ? ';themeProfile 只读,请改 visualStyle.tokens 或 colorStrategy.primaryColor'
41
- : /(?:navigationStyle\.(?:tone|toneSource)|appConfig\.navTheme)/.test(expression)
42
- ? ';导航明暗由所选主题模板派生,请改选主题'
43
- : '';
34
+ const hint = expression.includes('themeProfile') ? ';themeProfile 只读,请改 visualStyle.tokens 或 colorStrategy.primaryColor' : '';
44
35
  throw new CliError(`字段 ${expression} 由 design-plan patch 自动维护,不能通过 --set 修改${hint}`, {
45
36
  code: 'DESIGN_PLAN_PROTECTED_PATH',
46
37
  });
@@ -57,7 +48,7 @@ function parseValue(rawValue) {
57
48
  }
58
49
  }
59
50
 
60
- function parseSetExpression(expression, options = {}) {
51
+ function parseSetExpression(expression) {
61
52
  const separator = String(expression || '').indexOf('=');
62
53
  if (separator <= 0) {
63
54
  throw new CliError(`--set 必须使用 path=value 格式:${expression || '(empty)'}`, {
@@ -67,21 +58,19 @@ function parseSetExpression(expression, options = {}) {
67
58
  const pathExpression = expression.slice(0, separator).trim();
68
59
  return {
69
60
  path: pathExpression,
70
- segments: parsePath(pathExpression, options),
61
+ segments: parsePath(pathExpression),
71
62
  value: parseValue(expression.slice(separator + 1)),
72
63
  };
73
64
  }
74
65
 
75
66
  const OPTIONAL_PATHS = [
76
67
  /^execution$/,
77
- /^execution\.(resourceBlueprint|resourceCreationOrder|pageImplementationOrder|navigationOrder|navigationFallback|entryRecommendation|sampleDataPlan|interactionStates|acceptanceCriteria|explicitScope|appConfig)$/,
78
- /^execution\.appConfig\.(appType|corpId|baseUrl|navigationType|hideAppNav|layoutDirection|logoSource)$/,
68
+ /^execution\.(resourceBlueprint|resourceCreationOrder|pageImplementationOrder|navigationOrder|navigationFallback|sampleDataPlan|interactionStates|acceptanceCriteria|explicitScope|appConfig)$/,
69
+ /^execution\.appConfig\.(appType|corpId|baseUrl|navigationType|hideAppNav|layoutDirection|navTheme|logoSource)$/,
79
70
  /^execution\.interactionStates\.(empty|loading|error|formEntry|detail)$/,
80
71
  /^visualStyle\.tokens(?:\.--[\w-]+)?$/,
81
- /^visualStyle\.forUser\.iconSystem(?:\.(library|mappings|colorPairs))?$/,
82
- /^visualStyle\.forUser\.assetStrategy\.(materialStatus|missingAssets)$/,
83
72
  /^pages\.customPageDetails\[\d+\]\.(scene|sceneKey|pageStructure|entryMode|dataSources|dataBinding|emptyReason|pageSpecHandoff)$/,
84
- /^pages\.customPageDetails\[\d+\]\.pageSpecHandoff\.(scene|pageStructure|entryMode|navigation|contentBlocks|dataSources|dataBinding|emptyReason|primaryAction|themeSummary|designFile|designRefs)$/,
73
+ /^pages\.customPageDetails\[\d+\]\.pageSpecHandoff\.(scene|pageStructure|entryMode|contentBlocks|dataSources|dataBinding|emptyReason|primaryAction|themeSummary|designFile|designRefs)$/,
85
74
  /^dataModels\[\d+\]\.(sampleRecords|skipSampleReason)$/,
86
75
  ];
87
76
 
@@ -118,15 +107,9 @@ function incrementRevision(revision) {
118
107
  return value ? `${value}-01` : `${date}-01`;
119
108
  }
120
109
 
121
- function invalidateConfirmation(plan, original) {
122
- if (original && isDeepStrictEqual(plan, original)) { return false; }
110
+ function invalidateConfirmation(plan) {
123
111
  plan.meta = plan.meta || {};
124
- const state = plan.meta.planState;
125
- // Legacy plans without presentation facts keep conservative version invalidation.
126
- if (!state || state.presentedRevision === plan.meta.revision
127
- || state.confirmedRevision === plan.meta.revision || state.planConfirmed === true || plan.meta.status === 'confirmed') {
128
- plan.meta.revision = incrementRevision(plan.meta.revision);
129
- }
112
+ plan.meta.revision = incrementRevision(plan.meta.revision);
130
113
  plan.meta.status = 'draft';
131
114
  plan.meta.updatedAt = new Date().toISOString();
132
115
  plan.meta.planState = plan.meta.planState || {};
@@ -135,21 +118,6 @@ function invalidateConfirmation(plan, original) {
135
118
  plan.meta.planState.planConfirmed = false;
136
119
  plan.meta.planState.confirmationInteractionId = '';
137
120
  plan.meta.planState.confirmedAt = '';
138
- return true;
139
- }
140
-
141
- // Collection results describe execution progress; the approved design stays the same.
142
- function isAssetProgressOnly(original, patched) {
143
- const withoutProgress = (plan) => {
144
- const copy = JSON.parse(JSON.stringify(plan));
145
- const strategy = copy.visualStyle?.forUser?.assetStrategy;
146
- if (strategy) {
147
- delete strategy.materialStatus;
148
- delete strategy.missingAssets;
149
- }
150
- return JSON.stringify(copy);
151
- };
152
- return withoutProgress(original) === withoutProgress(patched);
153
121
  }
154
122
 
155
123
  function patchPlan(inputPath, setExpressions, options = {}) {
@@ -162,17 +130,12 @@ function patchPlan(inputPath, setExpressions, options = {}) {
162
130
  }
163
131
  const original = readJson(resolvedInput);
164
132
  const patched = JSON.parse(JSON.stringify(original));
165
- const selectedTheme = original.visualStyle?.internal?.selectedTheme || original.visualStyle?.forUser?.selectedTheme;
166
- const creative = selectedTheme?.themeId === 'free-creative';
167
- const changes = expressions.map(expression => parseSetExpression(expression, { creative })).map(change => ({
133
+ const changes = expressions.map(parseSetExpression).map(change => ({
168
134
  ...change,
169
135
  previousValue: setExistingPath(patched, change),
170
136
  }));
171
137
  const effectiveChanges = changes.filter(change => JSON.stringify(change.previousValue) !== JSON.stringify(change.value));
172
138
  if (JSON.stringify(original) === JSON.stringify(patched)) {
173
- if (options.materialize) {
174
- return { ...require('./materialize').materialize(resolvedInput, { outputDir: options.outputDir }), changed: false, materialized: true, changedPaths: [], confirmationInvalidated: false };
175
- }
176
139
  return {
177
140
  success: true,
178
141
  changed: false,
@@ -182,21 +145,13 @@ function patchPlan(inputPath, setExpressions, options = {}) {
182
145
  changedPaths: [],
183
146
  confirmationInvalidated: false,
184
147
  materialized: false,
185
- updated: [],
186
148
  };
187
149
  }
188
150
  const previousRevision = (patched.meta || {}).revision || null;
189
- const assetProgressOnly = isAssetProgressOnly(original, patched);
190
- if (assetProgressOnly) {
191
- patched.meta.updatedAt = new Date().toISOString();
192
- } else {
193
- invalidateConfirmation(patched);
194
- }
195
- const outputDir = path.resolve(options.outputDir || path.dirname(resolvedInput));
196
- const artifacts = prepareArtifacts(patched, outputDir, undefined, { renderHtml: options.materialize === true });
197
- const updates = options.materialize ? prepareArtifactUpdate(artifacts, outputDir, () => prepareArtifacts(original, outputDir)) : null;
151
+ invalidateConfirmation(patched);
152
+ const artifacts = prepareArtifacts(patched, path.resolve(options.outputDir || path.dirname(resolvedInput)));
198
153
  const files = [[resolvedInput, `${JSON.stringify(patched, null, 2)}\n`]];
199
- if (updates) {files.push(...updates.files);}
154
+ if (options.materialize) {files.push(...artifacts.files);}
200
155
  writeFiles(files);
201
156
  return {
202
157
  success: true,
@@ -205,11 +160,9 @@ function patchPlan(inputPath, setExpressions, options = {}) {
205
160
  previousRevision,
206
161
  revision: patched.meta.revision,
207
162
  changedPaths: effectiveChanges.map(change => change.path),
208
- confirmationInvalidated: !assetProgressOnly,
163
+ confirmationInvalidated: true,
209
164
  materialized: options.materialize === true,
210
165
  outputs: options.materialize ? artifacts.outputs : undefined,
211
- ...(options.materialize ? { confirmation: require('./confirmation').confirmationPayload(artifacts.outputs, artifacts.revision) } : {}),
212
- updated: updates?.updated || [],
213
166
  };
214
167
  }
215
168
 
@@ -121,9 +121,12 @@ function preview(inputPath, options = {}) {
121
121
  for (const [key, fragment] of Object.entries(fragments)) { html = updateBlock(html, key, fragment); }
122
122
  const files = [[outputs.prd, prd], [outputs.html, html]];
123
123
  if (accepted.visualStyle && changed.some(key => ['visualStyle', 'pages'].includes(key))) {
124
- // Optional theme recipes do not determine whether a real page exists.
125
- // Preserve accepted page drafts; final materialization checks completeness.
126
- const design = renderDesign(plan, { outputDir: dir, draft: true });
124
+ const applications = plan.visualStyle.forUser?.pageApplications || [];
125
+ const pages = plan.pages.customPageDetails || [];
126
+ const bindingsReady = pages.every(page => applications.some(item => item.pageId === page.pageId && item.visualMemoryApplications?.length));
127
+ const designPlan = clone(plan);
128
+ if (!bindingsReady) { designPlan.pages = { customPageDetails: [] }; }
129
+ const design = renderDesign(designPlan);
127
130
  const oldDesign = hadVisual && fs.existsSync(outputs.design) ? fs.readFileSync(outputs.design, 'utf8') : undefined;
128
131
  const css = hadVisual && fs.existsSync(outputs.theme) ? fs.readFileSync(outputs.theme, 'utf8') : fs.readFileSync(CSS_TEMPLATE, 'utf8');
129
132
  files.push([outputs.design, design], [outputs.theme, applyDesignTokens(css, design, oldDesign)]);
@@ -143,9 +146,8 @@ function finalizePreview(source, stateFile) {
143
146
  const { facts } = readPart(stateFile, planBase(source));
144
147
  if (MODULES.some(key => !(key in facts))) { invalid('complete all preview modules before final validation'); }
145
148
  const merged = clone({ ...source, ...facts });
146
- if (require('./patch').invalidateConfirmation(merged, source) || merged.meta.status === 'draft') {
147
- merged.meta.status = 'awaiting_confirmation';
148
- }
149
+ require('./patch').invalidateConfirmation(merged);
150
+ merged.meta.status = 'awaiting_confirmation';
149
151
  return merged;
150
152
  }
151
153