create-yss-spec 1.1.2 → 1.1.4

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 (278) hide show
  1. package/package.json +1 -1
  2. package/template/.agents/skills/excalidraw-diagram-generator/SKILL.md +3 -3
  3. package/template/.agents/skills/grill-me/SKILL.md +7 -0
  4. package/template/.agents/skills/grilling/SKILL.md +12 -0
  5. package/template/.agents/skills/handoff/SKILL.md +16 -0
  6. package/template/.agents/skills/to-issues/SKILL.md +2 -2
  7. package/template/.claude/skills/grill-me/SKILL.md +7 -0
  8. package/template/.claude/skills/grilling/SKILL.md +12 -0
  9. package/template/.claude/skills/handoff/SKILL.md +16 -0
  10. package/template/.claude/skills/to-issues/SKILL.md +2 -2
  11. package/template/.codex/skills/cross-repo-implementation-routing/SKILL.md +1 -1
  12. package/template/.codex/skills/data-analytics/.app.json +84 -0
  13. package/template/.codex/skills/data-analytics/.codex-plugin/plugin.json +66 -0
  14. package/template/.codex/skills/data-analytics/.mcp.json +30 -0
  15. package/template/.codex/skills/data-analytics/AGENTS.md +20 -0
  16. package/template/.codex/skills/data-analytics/DEPENDENCIES.MD +27 -0
  17. package/template/.codex/skills/data-analytics/README.md +60 -0
  18. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html +16 -0
  19. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part001 +1 -0
  20. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part002 +1 -0
  21. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part003 +1 -0
  22. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part004 +1 -0
  23. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part005 +1 -0
  24. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part006 +1 -0
  25. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html +16 -0
  26. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part001 +1 -0
  27. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part002 +1 -0
  28. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part003 +1 -0
  29. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part004 +1 -0
  30. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part005 +1 -0
  31. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part006 +1 -0
  32. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part007 +1 -0
  33. package/template/.codex/skills/data-analytics/assets/datascience-small.svg +5 -0
  34. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html +16 -0
  35. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part001 +1 -0
  36. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part002 +1 -0
  37. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part003 +1 -0
  38. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part004 +1 -0
  39. package/template/.codex/skills/data-analytics/assets/datascience.png +0 -0
  40. package/template/.codex/skills/data-analytics/assets/datascience.svg +10 -0
  41. package/template/.codex/skills/data-analytics/mcp/server.cjs +2963 -0
  42. package/template/.codex/skills/data-analytics/package-lock.json +3048 -0
  43. package/template/.codex/skills/data-analytics/package.json +43 -0
  44. package/template/.codex/skills/data-analytics/scripts/normalize-widget-assets.mjs +75 -0
  45. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/SKILL.md +160 -0
  46. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/agents/openai.yaml +6 -0
  47. package/template/.codex/skills/data-analytics/skills/build-dashboard/SKILL.md +148 -0
  48. package/template/.codex/skills/data-analytics/skills/build-dashboard/agents/openai.yaml +6 -0
  49. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/bi-platform-dashboard.md +18 -0
  50. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/html-dashboard.md +24 -0
  51. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/mcp-artifact-dashboard.md +71 -0
  52. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/streamlit-dashboard.md +85 -0
  53. package/template/.codex/skills/data-analytics/skills/build-report/SKILL.md +207 -0
  54. package/template/.codex/skills/data-analytics/skills/build-report/agents/openai.yaml +6 -0
  55. package/template/.codex/skills/data-analytics/skills/build-report/assets/executive-report-shell.html +70 -0
  56. package/template/.codex/skills/data-analytics/skills/build-report/assets/technical-report-shell.html +66 -0
  57. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/SKILL.md +118 -0
  58. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/agents/openai.yaml +6 -0
  59. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/__init__.py +1 -0
  60. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/cli.py +57 -0
  61. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/constants.py +61 -0
  62. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/docx_writer.py +362 -0
  63. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/html_parser.py +829 -0
  64. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/model.py +30 -0
  65. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/plan.py +129 -0
  66. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/quality.py +374 -0
  67. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/rendering.py +613 -0
  68. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/table_utils.py +54 -0
  69. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/utils.py +16 -0
  70. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc_plan.py +9 -0
  71. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/SKILL.md +78 -0
  72. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/agents/openai.yaml +6 -0
  73. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/scripts/report_to_google_slides.py +2379 -0
  74. package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/SKILL.md +88 -0
  75. package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/agents/openai.yaml +6 -0
  76. package/template/.codex/skills/data-analytics/skills/build-report/specifications/executive-report.md +97 -0
  77. package/template/.codex/skills/data-analytics/skills/build-report/specifications/mcp-app-report.md +59 -0
  78. package/template/.codex/skills/data-analytics/skills/build-report/specifications/technical-report.md +75 -0
  79. package/template/.codex/skills/data-analytics/skills/design-kpis/SKILL.md +103 -0
  80. package/template/.codex/skills/data-analytics/skills/design-kpis/agents/openai.yaml +6 -0
  81. package/template/.codex/skills/data-analytics/skills/gather-business-context/SKILL.md +68 -0
  82. package/template/.codex/skills/data-analytics/skills/gather-business-context/agents/openai.yaml +6 -0
  83. package/template/.codex/skills/data-analytics/skills/index/SKILL.md +251 -0
  84. package/template/.codex/skills/data-analytics/skills/index/agents/openai.yaml +6 -0
  85. package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/SKILL.md +131 -0
  86. package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/agents/openai.yaml +6 -0
  87. package/template/.codex/skills/data-analytics/skills/kpi-reporting/SKILL.md +141 -0
  88. package/template/.codex/skills/data-analytics/skills/kpi-reporting/agents/openai.yaml +6 -0
  89. package/template/.codex/skills/data-analytics/skills/kpi-reporting/references/report-templates.md +32 -0
  90. package/template/.codex/skills/data-analytics/skills/market-sizing/SKILL.md +106 -0
  91. package/template/.codex/skills/data-analytics/skills/market-sizing/agents/openai.yaml +6 -0
  92. package/template/.codex/skills/data-analytics/skills/metric-diagnostics/SKILL.md +130 -0
  93. package/template/.codex/skills/data-analytics/skills/metric-diagnostics/agents/openai.yaml +6 -0
  94. package/template/.codex/skills/data-analytics/skills/product-business-analysis/SKILL.md +141 -0
  95. package/template/.codex/skills/data-analytics/skills/product-business-analysis/agents/openai.yaml +6 -0
  96. package/template/.codex/skills/data-analytics/skills/spreadsheets/SKILL.md +178 -0
  97. package/template/.codex/skills/data-analytics/skills/spreadsheets/agents/openai.yaml +9 -0
  98. package/template/.codex/skills/data-analytics/skills/spreadsheets/assets/file-spreadsheet.png +0 -0
  99. package/template/.codex/skills/data-analytics/skills/spreadsheets/charts.md +31 -0
  100. package/template/.codex/skills/data-analytics/skills/spreadsheets/references/artifact_tool_api.md +466 -0
  101. package/template/.codex/skills/data-analytics/skills/spreadsheets/style_guidelines.md +99 -0
  102. package/template/.codex/skills/data-analytics/skills/user-context/SKILL.md +195 -0
  103. package/template/.codex/skills/data-analytics/skills/user-context/agents/openai.yaml +6 -0
  104. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/automation-config.md +26 -0
  105. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/source-category-config.json +51 -0
  106. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/user-context-config.md +66 -0
  107. package/template/.codex/skills/data-analytics/skills/user-context/references/automation.md +69 -0
  108. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-examples.md +204 -0
  109. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-state-template.json +87 -0
  110. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding.md +497 -0
  111. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/connector-playbook.md +74 -0
  112. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/setup.md +65 -0
  113. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/skill-template.md +160 -0
  114. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/source-intake.md +75 -0
  115. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/weekly-polling-automation.md +96 -0
  116. package/template/.codex/skills/data-analytics/skills/user-context/references/source-category-runtime.md +263 -0
  117. package/template/.codex/skills/data-analytics/skills/user-context/scripts/data_analytics_preflight.py +1460 -0
  118. package/template/.codex/skills/data-analytics/skills/user-context/scripts/init_user_context_state.py +128 -0
  119. package/template/.codex/skills/data-analytics/skills/user-context/scripts/reset_user_context_state.py +101 -0
  120. package/template/.codex/skills/data-analytics/skills/user-context/scripts/validate_user_context_preflight.py +499 -0
  121. package/template/.codex/skills/data-analytics/skills/user-context/tests/test_state_helpers.py +978 -0
  122. package/template/.codex/skills/data-analytics/skills/validate-data/SKILL.md +190 -0
  123. package/template/.codex/skills/data-analytics/skills/validate-data/agents/openai.yaml +6 -0
  124. package/template/.codex/skills/data-analytics/skills/visualize-data/SKILL.md +157 -0
  125. package/template/.codex/skills/data-analytics/skills/visualize-data/agents/openai.yaml +6 -0
  126. package/template/.codex/skills/data-analytics/skills/visualize-data/references/seaborn-templates.md +774 -0
  127. package/template/.codex/skills/data-analytics/src/DESIGN.md +222 -0
  128. package/template/.codex/skills/data-analytics/src/analytics-app/App.tsx +3666 -0
  129. package/template/.codex/skills/data-analytics/src/analytics-app/analytics-layout.test.mjs +136 -0
  130. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartFrame.tsx +54 -0
  131. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartLegend.tsx +96 -0
  132. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartRenderer.tsx +1647 -0
  133. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartTooltip.tsx +245 -0
  134. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-app-helpers.tsx +462 -0
  135. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-capabilities.ts +107 -0
  136. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-compatibility.ts +164 -0
  137. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-contract.ts +192 -0
  138. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-theme.ts +203 -0
  139. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-tokens.css +619 -0
  140. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-transforms.ts +402 -0
  141. package/template/.codex/skills/data-analytics/src/analytics-app/fonts/SystemSansVariableVF.woff2 +0 -0
  142. package/template/.codex/skills/data-analytics/src/analytics-app/imageExport.ts +370 -0
  143. package/template/.codex/skills/data-analytics/src/analytics-app/layout/AnalyticsLayoutCanvas.tsx +536 -0
  144. package/template/.codex/skills/data-analytics/src/analytics-app/layout/RichMarkdown.tsx +681 -0
  145. package/template/.codex/skills/data-analytics/src/analytics-app/layout/analyticsLayoutCore.ts +164 -0
  146. package/template/.codex/skills/data-analytics/src/analytics-app/main.tsx +21 -0
  147. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/chart_contract.py +472 -0
  148. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/check_analytics_app_runtime_links.py +75 -0
  149. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/design_contract.py +142 -0
  150. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/package_utils.py +142 -0
  151. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/tests/test_package_utils.py +377 -0
  152. package/template/.codex/skills/data-analytics/src/analytics-app/styles.css +3468 -0
  153. package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.d.ts +44 -0
  154. package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.jsx +639 -0
  155. package/template/.codex/skills/data-analytics/src/analytics-app/tables/data-table.css +327 -0
  156. package/template/.codex/skills/data-analytics/src/analytics-app/tokens.css +225 -0
  157. package/template/.codex/skills/data-analytics/src/analytics-app/types.ts +204 -0
  158. package/template/.codex/skills/data-analytics/src/analytics-app-core.md +85 -0
  159. package/template/.codex/skills/data-analytics/src/codex-style-contract.md +30 -0
  160. package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.html +12 -0
  161. package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.jsx +1008 -0
  162. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.css +2117 -0
  163. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.html +122 -0
  164. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.js +3588 -0
  165. package/template/.codex/skills/data-analytics/src/datascience-table-widget.css +483 -0
  166. package/template/.codex/skills/data-analytics/src/datascience-table-widget.html +32 -0
  167. package/template/.codex/skills/data-analytics/src/datascience-table-widget.js +333 -0
  168. package/template/.codex/skills/data-analytics/src/mcp-host.js +153 -0
  169. package/template/.codex/skills/data-analytics/src/recharts-config.js +315 -0
  170. package/template/.codex/skills/data-analytics/src/recharts-renderer.jsx +294 -0
  171. package/template/.codex/skills/data-analytics/src/sql-source-view.css +33 -0
  172. package/template/.codex/skills/data-analytics/src/sql-source-view.js +157 -0
  173. package/template/.codex/skills/data-analytics/src/styles/codex-theme.css +121 -0
  174. package/template/.codex/skills/data-analytics/src/table-renderer.jsx +28 -0
  175. package/template/.codex/skills/data-analytics/tests/chart-transforms.test.mjs +87 -0
  176. package/template/.codex/skills/data-analytics/tests/funnel-smoke.html +105 -0
  177. package/template/.codex/skills/data-analytics/tests/inline-widget-compare.html +233 -0
  178. package/template/.codex/skills/data-analytics/tests/mcp-server.test.mjs +1500 -0
  179. package/template/.codex/skills/data-analytics/tests/native-style-contract.test.mjs +219 -0
  180. package/template/.codex/skills/data-analytics/tests/recharts-config.test.mjs +144 -0
  181. package/template/.codex/skills/data-analytics/tests/recharts-renderer.test.mjs +11 -0
  182. package/template/.codex/skills/data-analytics/tests/rich-markdown.test.mjs +54 -0
  183. package/template/.codex/skills/data-analytics/tests/widget-render-harness.html +321 -0
  184. package/template/.codex/skills/data-analytics/tsconfig.json +19 -0
  185. package/template/.codex/skills/data-analytics/vite.config.ts +46 -0
  186. package/template/.codex/skills/product-design/.app.json +7 -0
  187. package/template/.codex/skills/product-design/.codex-plugin/plugin.json +50 -0
  188. package/template/.codex/skills/product-design/README.md +50 -0
  189. package/template/.codex/skills/product-design/agents/openai.yaml +4 -0
  190. package/template/.codex/skills/product-design/assets/composerIcon.svg +9 -0
  191. package/template/.codex/skills/product-design/assets/logo.png +0 -0
  192. package/template/.codex/skills/product-design/package.json +11 -0
  193. package/template/.codex/skills/product-design/references/browser-order.md +9 -0
  194. package/template/.codex/skills/product-design/references/communication-protocol.md +45 -0
  195. package/template/.codex/skills/product-design/references/critical-overrides.md +58 -0
  196. package/template/.codex/skills/product-design/references/local-prototype-preflight.md +16 -0
  197. package/template/.codex/skills/product-design/scripts/bootstrap-prototype.mjs +147 -0
  198. package/template/.codex/skills/product-design/skills/audit/SKILL.md +159 -0
  199. package/template/.codex/skills/product-design/skills/audit/agents/openai.yaml +6 -0
  200. package/template/.codex/skills/product-design/skills/audit/references/design-audit-framework.md +73 -0
  201. package/template/.codex/skills/product-design/skills/design-qa/SKILL.md +133 -0
  202. package/template/.codex/skills/product-design/skills/design-qa/agents/openai.yaml +6 -0
  203. package/template/.codex/skills/product-design/skills/design-qa/references/qa-rubric.md +61 -0
  204. package/template/.codex/skills/product-design/skills/get-context/SKILL.md +81 -0
  205. package/template/.codex/skills/product-design/skills/get-context/agents/openai.yaml +6 -0
  206. package/template/.codex/skills/product-design/skills/ideate/SKILL.md +179 -0
  207. package/template/.codex/skills/product-design/skills/ideate/agents/openai.yaml +6 -0
  208. package/template/.codex/skills/product-design/skills/image-to-code/SKILL.md +105 -0
  209. package/template/.codex/skills/product-design/skills/image-to-code/agents/openai.yaml +6 -0
  210. package/template/.codex/skills/product-design/skills/index/SKILL.md +126 -0
  211. package/template/.codex/skills/product-design/skills/index/agents/openai.yaml +6 -0
  212. package/template/.codex/skills/product-design/skills/prototype/SKILL.md +128 -0
  213. package/template/.codex/skills/product-design/skills/prototype/agents/openai.yaml +6 -0
  214. package/template/.codex/skills/product-design/skills/prototype/references/existing-codebase-edits.md +18 -0
  215. package/template/.codex/skills/product-design/skills/research/SKILL.md +92 -0
  216. package/template/.codex/skills/product-design/skills/research/agents/openai.yaml +6 -0
  217. package/template/.codex/skills/product-design/skills/share/SKILL.md +41 -0
  218. package/template/.codex/skills/product-design/skills/share/agents/openai.yaml +6 -0
  219. package/template/.codex/skills/product-design/skills/url-to-code/SKILL.md +124 -0
  220. package/template/.codex/skills/product-design/skills/url-to-code/agents/openai.yaml +6 -0
  221. package/template/.codex/skills/product-design/skills/user-context/SKILL.md +147 -0
  222. package/template/.codex/skills/product-design/skills/user-context/agents/openai.yaml +6 -0
  223. package/template/.codex/skills/product-design/skills/user-context/plugin-author-config/user-context-template.md +63 -0
  224. package/template/.codex/skills/product-design/skills/user-context/references/onboarding.md +66 -0
  225. package/template/.codex/skills/product-design/skills/user-context/scripts/init_user_context.py +86 -0
  226. package/template/.codex/skills/product-design/skills/user-context/scripts/user_context_preflight.py +204 -0
  227. package/template/.codex/skills/product-design/templates/prototype/AGENTS.md +7 -0
  228. package/template/.codex/skills/product-design/templates/prototype/index.html +12 -0
  229. package/template/.codex/skills/product-design/templates/prototype/package.json +18 -0
  230. package/template/.codex/skills/product-design/templates/prototype/src/App.jsx +5 -0
  231. package/template/.codex/skills/product-design/templates/prototype/src/main.jsx +10 -0
  232. package/template/.codex/skills/product-design/templates/prototype/src/styles.css +13 -0
  233. package/template/.codex/skills/product-design/templates/prototype/vite.config.mjs +14 -0
  234. package/template/.codex/skills/product-design-prototype/SKILL.md +1 -1
  235. package/template/.codex/skills/yss-api-integration/SKILL.md +1 -1
  236. package/template/.codex/skills/yss-ddd-scaffold-generator/references/yss-backend-scaffold-parent/SKILL.md +1 -1
  237. package/template/.codex/skills/yss-filerunner/SKILL.md +1 -1
  238. package/template/.codex/skills/yss-openapi/SKILL.md +1 -1
  239. package/template/.codex/skills/yss-openapi-draft-review/SKILL.md +1 -1
  240. package/template/.codex/skills/yss-openapi-governance/SKILL.md +3 -3
  241. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +23 -7
  242. package/template/.codex/skills/yss-router/SKILL.md +1 -2
  243. package/template/.codex/skills/yss-router/references/boundaries.md +0 -1
  244. package/template/.codex/skills/yss-source-index/references/source-map-config.md +0 -1
  245. package/template/.codex/skills/yss-source-index/scripts/refresh-yss-skill-index.py +0 -3
  246. package/template/.hermes/skills/grill-me/SKILL.md +7 -0
  247. package/template/.hermes/skills/grilling/SKILL.md +12 -0
  248. package/template/.hermes/skills/handoff/SKILL.md +16 -0
  249. package/template/.hermes/skills/to-issues/SKILL.md +2 -2
  250. package/template/.pi/skills/grill-me/SKILL.md +7 -0
  251. package/template/.pi/skills/grilling/SKILL.md +12 -0
  252. package/template/.pi/skills/handoff/SKILL.md +16 -0
  253. package/template/.pi/skills/to-issues/SKILL.md +2 -2
  254. package/template/.trae/skills/grill-me/SKILL.md +7 -0
  255. package/template/.trae/skills/grilling/SKILL.md +12 -0
  256. package/template/.trae/skills/handoff/SKILL.md +16 -0
  257. package/template/.trae/skills/to-issues/SKILL.md +2 -2
  258. package/template/AGENTS.md +11 -3
  259. package/template/docs/adr/adr-product-design-prototype-entrypoint.md +54 -0
  260. package/template/docs/api/templates/openapi-draft-review-checklist.md +4 -2
  261. package/template/docs/design/README.md +8 -4
  262. package/template/docs/design/templates/interaction-spec-template.md +4 -1
  263. package/template/docs/design/templates/prototype-confirmation-template.md +57 -0
  264. package/template/docs/design/templates/prototype-review-checklist.md +6 -2
  265. package/template/docs/design/templates/state-matrix-template.md +1 -1
  266. package/template/docs/process/MATT-POCOCK-ENGINEERING-SKILLS.md +22 -3
  267. package/template/docs/process/harness-executive-blueprint.md +2 -1
  268. package/template/docs/process/harness-process-tailoring.md +8 -1
  269. package/template/docs/process/harness-work-unit-map.md +1 -1
  270. package/template/docs/process/lifecycle-artifact-map.md +17 -8
  271. package/template/docs/process/product-prototype-workflow.md +82 -0
  272. package/template/docs/user-guide/product-lifecycle-workflow.md +2 -2
  273. package/template/docs/user-guide/product-rd-lifecycle-best-practices.md +15 -10
  274. package/template/scripts/verify-template +0 -14
  275. package/template/skills-lock.json +70 -27
  276. package/template/.codex/skills/yss-anti-scheduler/SKILL.md +0 -53
  277. package/template/.codex/skills/yss-anti-scheduler/agents/openai.yaml +0 -4
  278. package/template/.codex/skills/yss-anti-scheduler/references/source-index.md +0 -157
@@ -0,0 +1,462 @@
1
+ import {
2
+ Boxes,
3
+ ChartArea,
4
+ ChartBar,
5
+ ChartColumn,
6
+ ChartColumnStacked,
7
+ ChartLine,
8
+ ChartNoAxesColumn,
9
+ ChartNoAxesCombined,
10
+ ChartScatter,
11
+ ChartSpline,
12
+ Filter as FunnelIcon,
13
+ Table2,
14
+ Tally3,
15
+ } from "lucide-react";
16
+ import {
17
+ chartTypeSectionsForOptions as sharedChartTypeSectionsForOptions,
18
+ compatibleChartTypesForDataShape as sharedCompatibleChartTypesForDataShape,
19
+ compatibleChartTypesFor as sharedCompatibleChartTypesFor,
20
+ isChartType as sharedIsChartType,
21
+ } from "./chart-compatibility";
22
+ import { isDateAxisValue } from "./chart-transforms";
23
+
24
+ export const CHART_TYPE_LABELS = {
25
+ area: "Area",
26
+ bar: "Bar",
27
+ boxPlot: "Box plot",
28
+ funnel: "Funnel",
29
+ heatmap: "Heatmap",
30
+ histogram: "Histogram",
31
+ horizontalBar: "Horizontal bar",
32
+ horizontalStackedBar: "Horizontal stacked bar",
33
+ horizontalStackedBar100: "100% horizontal stacked bar",
34
+ leaderboard: "Leaderboard",
35
+ line: "Line",
36
+ pie: "Pie",
37
+ scatter: "Scatter",
38
+ sparkline: "Sparkline",
39
+ stackedArea: "Stacked area",
40
+ stackedBar: "Stacked bar",
41
+ stackedBar100: "100% stacked bar",
42
+ waterfall: "Waterfall",
43
+ };
44
+
45
+ function asArray(value) {
46
+ return Array.isArray(value) ? value : [];
47
+ }
48
+
49
+ function asNumber(value) {
50
+ if (typeof value === "number" && Number.isFinite(value)) return value;
51
+ if (typeof value === "string" && value.trim() !== "") {
52
+ const numeric = Number(value.replace(/,/g, ""));
53
+ if (Number.isFinite(numeric)) return numeric;
54
+ }
55
+ return null;
56
+ }
57
+
58
+ function plainObject(value) {
59
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
60
+ }
61
+
62
+ export function chartTypeIcon(type) {
63
+ const iconProps = { "aria-hidden": true, size: 18, strokeWidth: 2 };
64
+ if (type === "area") return <ChartArea {...iconProps} />;
65
+ if (type === "bar") return <ChartColumn {...iconProps} />;
66
+ if (type === "boxPlot") return <Boxes {...iconProps} />;
67
+ if (type === "funnel") return <FunnelIcon {...iconProps} />;
68
+ if (type === "heatmap") return <Table2 {...iconProps} />;
69
+ if (type === "histogram") return <ChartNoAxesColumn {...iconProps} />;
70
+ if (type === "horizontalBar") return <ChartBar {...iconProps} />;
71
+ if (type === "horizontalStackedBar" || type === "horizontalStackedBar100") return <ChartColumnStacked {...iconProps} />;
72
+ if (type === "leaderboard") return <Tally3 {...iconProps} />;
73
+ if (type === "line") return <ChartLine {...iconProps} />;
74
+ if (type === "pie") return <ChartNoAxesCombined {...iconProps} />;
75
+ if (type === "scatter") return <ChartScatter {...iconProps} />;
76
+ if (type === "sparkline") return <ChartSpline {...iconProps} />;
77
+ if (type === "stackedArea") return <ChartArea {...iconProps} />;
78
+ if (type === "stackedBar" || type === "stackedBar100") return <ChartColumnStacked {...iconProps} />;
79
+ return <ChartNoAxesCombined {...iconProps} />;
80
+ }
81
+
82
+ function chartTypePreviewKind(type) {
83
+ if (type === "boxPlot") return "box-plot";
84
+ if (type === "horizontalBar") return "horizontal-bar";
85
+ if (type === "horizontalStackedBar") return "horizontal-stacked-bar";
86
+ if (type === "horizontalStackedBar100") return "horizontal-stacked-bar-100";
87
+ if (type === "stackedArea") return "stacked-area";
88
+ if (type === "stackedBar") return "stacked-bar";
89
+ if (type === "stackedBar100") return "stacked-bar-100";
90
+ return type;
91
+ }
92
+
93
+ export function chartTypePreviewIcon(type) {
94
+ const kind = chartTypePreviewKind(type);
95
+ const stroke = "currentColor";
96
+ const fill = "color-mix(in srgb, currentColor 28%, transparent)";
97
+ const fillStrong = "color-mix(in srgb, currentColor 48%, transparent)";
98
+ const grid = <path d="M8 8v48h80" fill="none" opacity=".44" stroke={stroke} strokeLinecap="round" strokeWidth="3" />;
99
+ const frame = (body) => (
100
+ <svg aria-hidden="true" fill="none" viewBox="0 0 96 64">
101
+ {grid}
102
+ {body}
103
+ </svg>
104
+ );
105
+ const rect = (x, y, width, height) => (
106
+ <rect fill={fill} height={height} rx="2" stroke={stroke} strokeWidth="2.5" width={width} x={x} y={y} />
107
+ );
108
+ const segment = (x, y, width, height, strong = false, key) => (
109
+ <rect fill={strong ? fillStrong : fill} height={height} key={key} rx="1.5" stroke={stroke} strokeWidth="2.2" width={width} x={x} y={y} />
110
+ );
111
+ if (kind === "bar") {
112
+ return frame(<>{rect(18, 34, 7, 22)}{rect(28, 24, 7, 32)}{rect(47, 42, 7, 14)}{rect(57, 18, 7, 38)}{rect(76, 29, 7, 27)}</>);
113
+ }
114
+ if (kind === "stacked-bar" || kind === "stacked-bar-100") {
115
+ return frame(<>{segment(20, 38, 12, 18)}{segment(20, 24, 12, 14, true)}{segment(45, 32, 12, 24)}{segment(45, 15, 12, 17, true)}{segment(70, 43, 12, 13)}{segment(70, 28, 12, 15, true)}</>);
116
+ }
117
+ if (kind === "horizontal-bar") {
118
+ return frame(<>{rect(18, 16, 22, 6)}{rect(18, 25, 36, 6)}{rect(18, 40, 28, 6)}{rect(18, 49, 53, 6)}</>);
119
+ }
120
+ if (kind === "horizontal-stacked-bar" || kind === "horizontal-stacked-bar-100") {
121
+ return frame(<>{segment(18, 18, 30, 9)}{segment(48, 18, 22, 9, true)}{segment(18, 39, 22, 9)}{segment(40, 39, 38, 9, true)}</>);
122
+ }
123
+ if (kind === "line" || kind === "sparkline") {
124
+ return frame(<>
125
+ <path d="M18 45 34 29l14 9 17-21 17 15" stroke={stroke} strokeLinecap="round" strokeLinejoin="round" strokeWidth="4" />
126
+ {[["18", "45"], ["34", "29"], ["65", "17"], ["82", "32"]].map(([cx, cy]) => <circle cx={cx} cy={cy} fill={fillStrong} key={`${cx}-${cy}`} r="3" stroke={stroke} strokeWidth="2" />)}
127
+ </>);
128
+ }
129
+ if (kind === "area" || kind === "stacked-area") {
130
+ return frame(<>
131
+ <path d="M18 47 34 35l14 8 18-23 17 10v26H18Z" fill={fill} />
132
+ <path d="M18 47 34 35l14 8 18-23 17 10" stroke={stroke} strokeLinecap="round" strokeLinejoin="round" strokeWidth="4" />
133
+ </>);
134
+ }
135
+ if (kind === "histogram") {
136
+ const heights = [12, 22, 35, 29, 18, 9];
137
+ return frame(<>{[16, 27, 38, 49, 60, 71].map((x, index) => segment(x, 56 - heights[index], 9, heights[index], index === 2 || index === 3, `hist-${index}`))}</>);
138
+ }
139
+ if (kind === "scatter") {
140
+ return frame(<>{[[20, 45], [31, 34], [42, 40], [51, 25], [63, 31], [74, 18], [82, 28]].map(([cx, cy]) => <circle cx={cx} cy={cy} fill={fillStrong} key={`${cx}-${cy}`} r="4" stroke={stroke} strokeWidth="2.5" />)}</>);
141
+ }
142
+ if (kind === "heatmap") {
143
+ return frame(<>{[0, 1, 2].flatMap((row) => [0, 1, 2, 3].map((col) => {
144
+ const strong = (row + col) % 3 === 0;
145
+ const opacity = [".18", ".3", ".46", ".62"][(row * 2 + col) % 4];
146
+ return <rect fill={strong ? fillStrong : fill} height="10" key={`${row}-${col}`} opacity={opacity} rx="1.5" stroke={stroke} strokeWidth="1.8" width="13" x={18 + col * 16} y={16 + row * 12} />;
147
+ }))}</>);
148
+ }
149
+ if (kind === "pie") {
150
+ return <svg aria-hidden="true" fill="none" viewBox="0 0 96 64"><path d="M48 8a24 24 0 1 1-20.8 36" fill={fill} stroke={stroke} strokeLinejoin="round" strokeWidth="3" /><path d="M48 8v24l20.8 12A24 24 0 0 0 48 8Z" fill={fillStrong} stroke={stroke} strokeLinejoin="round" strokeWidth="3" /><path d="M48 32 27.2 44" stroke={stroke} strokeLinecap="round" strokeWidth="3" /></svg>;
151
+ }
152
+ if (kind === "funnel") {
153
+ return <svg aria-hidden="true" fill="none" viewBox="0 0 96 64"><path d="M18 10h60L68 24H28Z" fill={fillStrong} stroke={stroke} strokeWidth="3" /><path d="M30 28h36L58 42H38Z" fill={fill} stroke={stroke} strokeWidth="3" /><path d="M40 46h16l-4 10h-8Z" fill={fill} stroke={stroke} strokeWidth="3" /></svg>;
154
+ }
155
+ if (kind === "waterfall") {
156
+ return frame(<>{segment(18, 40, 12, 16)}{segment(38, 26, 12, 30, true)}{segment(58, 34, 12, 22)}{segment(78, 20, 8, 36, true)}</>);
157
+ }
158
+ if (kind === "leaderboard") {
159
+ return frame(<>{segment(18, 17, 58, 8, true)}{segment(18, 31, 44, 8)}{segment(18, 45, 30, 8)}</>);
160
+ }
161
+ if (kind === "box-plot") {
162
+ return frame(<><path d="M22 24h52M22 42h42" stroke={stroke} strokeLinecap="round" strokeWidth="3" /><rect fill={fill} height="12" rx="2" stroke={stroke} strokeWidth="2.5" width="24" x="34" y="18" /><rect fill={fillStrong} height="12" rx="2" stroke={stroke} strokeWidth="2.5" width="22" x="30" y="36" /></>);
163
+ }
164
+ return frame(rect(20, 22, 52, 28));
165
+ }
166
+
167
+ export function withChartType(chart, type) {
168
+ return chart.type === type ? chart : { ...chart, type };
169
+ }
170
+
171
+ function chartWidgetBarType(type, settings) {
172
+ const rawType = String(type ?? "").trim();
173
+ if (rawType !== "bar") return sharedIsChartType(rawType) ? rawType : null;
174
+ const orientation = String(settings?.orientation ?? "").toLowerCase();
175
+ const groupMode = String(settings?.group_mode ?? settings?.groupMode ?? "").toLowerCase();
176
+ if (orientation === "horizontal" && groupMode === "stacked100") return "horizontalStackedBar100";
177
+ if (orientation === "horizontal" && groupMode === "stacked") return "horizontalStackedBar";
178
+ if (orientation === "horizontal") return "horizontalBar";
179
+ if (groupMode === "stacked100") return "stackedBar100";
180
+ if (groupMode === "stacked") return "stackedBar";
181
+ return "bar";
182
+ }
183
+
184
+ export function chartSpecOverrideFromWidgetSpec(chart, widgetSpec) {
185
+ const spec = plainObject(widgetSpec);
186
+ const encodings = plainObject(spec.encodings);
187
+ const settings = plainObject(spec.settings);
188
+ const originalSettings = plainObject(chart.settings);
189
+ const override = {};
190
+ const nextType = chartWidgetBarType(spec.visualization_type, settings);
191
+ if (nextType && nextType !== chart.type) override.type = nextType;
192
+ const chartFields = new Set(chartUsedFields(chart));
193
+ const xField = plainObject(encodings.x).field;
194
+ if (typeof xField === "string" && chartFields.has(xField) && xField !== chart.xField) override.xField = xField;
195
+ const yField = plainObject(encodings.y).field;
196
+ const currentSeries = asArray(chart.series);
197
+ if (typeof yField === "string" && chartFields.has(yField) && currentSeries[0]?.field !== yField) {
198
+ override.series = [{ ...currentSeries[0], field: yField, label: currentSeries.find((series) => series.field === yField)?.label ?? currentSeries[0]?.label ?? yField }];
199
+ }
200
+ const sizeField = plainObject(encodings.size).field;
201
+ if (typeof sizeField === "string" && chartFields.has(sizeField) && chartEncodingField(chart, "size") !== sizeField) {
202
+ override.encodings = { ...plainObject(chart.encodings), size: { ...plainObject(chartEncoding(chart, "size")), field: sizeField } };
203
+ }
204
+ const nextSettings = {};
205
+ const orientation = settings.orientation === "horizontal" || settings.orientation === "vertical" ? settings.orientation : null;
206
+ if (orientation && originalSettings.orientation !== orientation) nextSettings.orientation = orientation;
207
+ const groupMode = settings.group_mode ?? settings.groupMode;
208
+ if (["grouped", "stacked", "stacked100"].includes(groupMode) && originalSettings.groupMode !== groupMode) nextSettings.groupMode = groupMode;
209
+ if (Object.keys(nextSettings).length) override.settings = { ...originalSettings, ...nextSettings };
210
+ return override;
211
+ }
212
+
213
+ export function applyChartSpecOverride(chart, override) {
214
+ if (!override || typeof override !== "object") return chart;
215
+ return {
216
+ ...chart,
217
+ ...(sharedIsChartType(override.type) ? { type: override.type } : {}),
218
+ ...(typeof override.xField === "string" ? { xField: override.xField } : {}),
219
+ ...(override.encodings && typeof override.encodings === "object" ? { encodings: { ...chart.encodings, ...override.encodings } } : {}),
220
+ ...(Array.isArray(override.series) && override.series.length ? { series: override.series } : {}),
221
+ ...(override.settings && typeof override.settings === "object" ? { settings: { ...chart.settings, ...override.settings } } : {}),
222
+ };
223
+ }
224
+
225
+ export function chartEncoding(chart, role) {
226
+ return chart?.encodings && typeof chart.encodings === "object" && chart.encodings[role] && typeof chart.encodings[role] === "object" ? chart.encodings[role] : {};
227
+ }
228
+
229
+ export function chartEncodingField(chart, role) {
230
+ const field = chartEncoding(chart, role).field;
231
+ return typeof field === "string" && field.trim() ? field : null;
232
+ }
233
+
234
+ export function chartEncodingFields(chart, role) {
235
+ const encoding = chartEncoding(chart, role);
236
+ return Array.isArray(encoding.fields) ? encoding.fields.filter((field) => typeof field === "string" && field.trim()) : [];
237
+ }
238
+
239
+ export function chartEncodingLabel(chart, role, fallback) {
240
+ const label = chartEncoding(chart, role).label;
241
+ return typeof label === "string" && label.trim() ? label : fallback;
242
+ }
243
+
244
+ function chartEncodingAxisTitle(chart, role, fallback) {
245
+ const label = chartEncodingLabel(chart, role, fallback);
246
+ const unit = (
247
+ chartEncoding(chart, role).unit ??
248
+ (role === "y" ? chart.unit : undefined)
249
+ )?.trim();
250
+ if (!unit || label.toLowerCase().includes(unit.toLowerCase())) return label;
251
+ return `${label} (${unit})`;
252
+ }
253
+
254
+ function chartTooltipEncodings(chart) {
255
+ return Array.isArray(chart?.encodings?.tooltip) ? chart.encodings.tooltip : [];
256
+ }
257
+
258
+ export function chartHasEncodingSpec(chart) {
259
+ return Boolean(chart?.encodings && typeof chart.encodings === "object" && chartEncodingField(chart, "x") && (chartEncodingField(chart, "y") || chartEncodingFields(chart, "y").length));
260
+ }
261
+
262
+ export function chartUsedFields(chart) {
263
+ const fields = [
264
+ chart.xField,
265
+ ...asArray(chart.series).map((series) => series?.field),
266
+ chartEncodingField(chart, "x"),
267
+ chartEncodingField(chart, "y"),
268
+ ...chartEncodingFields(chart, "y"),
269
+ chartEncodingField(chart, "color"),
270
+ chartEncodingField(chart, "lineStyle"),
271
+ chartEncodingField(chart, "size"),
272
+ chartEncodingField(chart, "facet"),
273
+ chartEncodingField(chart, "label"),
274
+ ...chartTooltipEncodings(chart).map((tooltip) => tooltip?.field),
275
+ ];
276
+ return [...new Set(fields.filter((field) => typeof field === "string" && field.trim()))];
277
+ }
278
+
279
+ function syntheticSeriesField(value, index) {
280
+ const slug = String(value ?? "value").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 40);
281
+ return `__series_${index}_${slug || "value"}`;
282
+ }
283
+
284
+ function normalizedLineStyle(value) {
285
+ return value === "solid" || value === "dashed" || value === "dotted" ? value : undefined;
286
+ }
287
+
288
+ function rowLineStyle(row, lineStyleField) {
289
+ return lineStyleField ? normalizedLineStyle(row?.[lineStyleField]) : undefined;
290
+ }
291
+
292
+ function inferredSeriesRole(value) {
293
+ const normalized = String(value ?? "").trim().toLowerCase();
294
+ if (/\b(actual|actuals|observed)\b/.test(normalized)) return "actual";
295
+ if (/\b(baseline|benchmark)\b/.test(normalized)) return "baseline";
296
+ if (/\b(target|goal)\b/.test(normalized)) return "target";
297
+ if (/\b(estimate|estimated|forecast|projected|projection)\b/.test(normalized)) return "forecast";
298
+ if (/\b(plan|planned|budget|quota)\b/.test(normalized)) return "plan";
299
+ return undefined;
300
+ }
301
+
302
+ function isSignedCategoryValue(value) {
303
+ const normalized = String(value ?? "").trim().toLowerCase();
304
+ return normalized === "positive" || normalized === "negative" || normalized === "neutral" || normalized === "zero";
305
+ }
306
+
307
+ function shouldKeepSignedBarAsSingleSeries(chart, rows, colorField) {
308
+ if (chart.type !== "bar" && chart.type !== "horizontalBar") return false;
309
+ const colorLabel = `${colorField ?? ""} ${chartEncodingLabel(chart, "color", "")}`.toLowerCase();
310
+ if (!colorLabel.includes("movement") && !colorLabel.includes("direction") && !colorLabel.includes("sign")) return false;
311
+ let observed = false;
312
+ for (const row of rows) {
313
+ const value = row[colorField];
314
+ if (value == null || value === "") continue;
315
+ observed = true;
316
+ if (!isSignedCategoryValue(value)) return false;
317
+ }
318
+ return observed;
319
+ }
320
+
321
+ export function rechartsChartFromEncodedSpec(chart, rows) {
322
+ if (!chartHasEncodingSpec(chart)) return { chart, rows };
323
+ const xField = chartEncodingField(chart, "x");
324
+ const yField = chartEncodingField(chart, "y");
325
+ const yFields = chartEncodingFields(chart, "y");
326
+ const colorField = chartEncodingField(chart, "color");
327
+ const lineStyleField = chartEncodingField(chart, "lineStyle");
328
+ if (yFields.length) {
329
+ return {
330
+ chart: {
331
+ ...chart,
332
+ xField,
333
+ xAxisTitle: chart.xAxisTitle ?? chartEncodingAxisTitle(chart, "x", xField),
334
+ yAxisTitle: chart.yAxisTitle ?? chartEncodingAxisTitle(chart, "y", "Value"),
335
+ series: yFields.map((field) => ({ field, label: field, semanticRole: inferredSeriesRole(field) })),
336
+ },
337
+ rows,
338
+ };
339
+ }
340
+ if (!yField) return { chart, rows };
341
+ if (chart.type === "funnel" || !colorField || shouldKeepSignedBarAsSingleSeries(chart, rows, colorField)) {
342
+ const lineStyle = rowLineStyle(rows.find((row) => rowLineStyle(row, lineStyleField)), lineStyleField);
343
+ return {
344
+ chart: {
345
+ ...chart,
346
+ xField,
347
+ xAxisTitle: chart.xAxisTitle ?? chartEncodingAxisTitle(chart, "x", xField),
348
+ yAxisTitle: chart.yAxisTitle ?? chartEncodingAxisTitle(chart, "y", yField),
349
+ series: [{ field: yField, label: chartEncodingLabel(chart, "y", yField), lineStyle, semanticRole: inferredSeriesRole(chartEncodingLabel(chart, "y", yField)) }],
350
+ },
351
+ rows,
352
+ };
353
+ }
354
+ const seriesValues = [];
355
+ const seriesLineStyles = new Map();
356
+ for (const row of rows) {
357
+ const value = row[colorField];
358
+ if (value == null || value === "") continue;
359
+ const key = String(value);
360
+ if (!seriesValues.includes(key)) seriesValues.push(key);
361
+ const lineStyle = rowLineStyle(row, lineStyleField);
362
+ if (lineStyle && !seriesLineStyles.has(key)) seriesLineStyles.set(key, lineStyle);
363
+ }
364
+ const seriesFields = new Map(seriesValues.map((value, index) => [value, syntheticSeriesField(value, index)]));
365
+ if (chart.type === "scatter") {
366
+ return {
367
+ chart: {
368
+ ...chart,
369
+ xField,
370
+ xAxisTitle: chart.xAxisTitle ?? chartEncodingAxisTitle(chart, "x", xField),
371
+ yAxisTitle: chart.yAxisTitle ?? chartEncodingAxisTitle(chart, "y", yField),
372
+ series: seriesValues.map((value) => ({ field: seriesFields.get(value), label: value, lineStyle: seriesLineStyles.get(value), semanticRole: inferredSeriesRole(value) })),
373
+ },
374
+ rows: rows.map((row) => {
375
+ const seriesField = seriesFields.get(String(row[colorField] ?? ""));
376
+ return seriesField ? { ...row, [seriesField]: row[yField] } : row;
377
+ }),
378
+ };
379
+ }
380
+ const rowsByX = new Map();
381
+ for (const row of rows) {
382
+ const xValue = row[xField];
383
+ const xKey = String(xValue ?? "");
384
+ if (!rowsByX.has(xKey)) rowsByX.set(xKey, { [xField]: xValue });
385
+ const seriesField = seriesFields.get(String(row[colorField] ?? ""));
386
+ if (seriesField) rowsByX.get(xKey)[seriesField] = row[yField];
387
+ }
388
+ return {
389
+ chart: {
390
+ ...chart,
391
+ xField,
392
+ xAxisTitle: chart.xAxisTitle ?? chartEncodingAxisTitle(chart, "x", xField),
393
+ yAxisTitle: chart.yAxisTitle ?? chartEncodingAxisTitle(chart, "y", yField),
394
+ series: seriesValues.map((value) => ({ field: seriesFields.get(value), label: value, lineStyle: seriesLineStyles.get(value), semanticRole: inferredSeriesRole(value) })),
395
+ },
396
+ rows: [...rowsByX.values()],
397
+ };
398
+ }
399
+
400
+ export function chartHasNumericSeries(chart, rows) {
401
+ if (!rows.length) return false;
402
+ return chart.series.every((series) => rows.some((row) => asNumber(row[series.field]) != null));
403
+ }
404
+
405
+ export function chartHasNonNegativeSeries(chart, rows) {
406
+ let observed = false;
407
+ for (const row of rows) {
408
+ for (const series of chart.series) {
409
+ const value = asNumber(row[series.field]);
410
+ if (value == null) continue;
411
+ observed = true;
412
+ if (value < 0) return false;
413
+ }
414
+ }
415
+ return observed;
416
+ }
417
+
418
+ export function hasNumericXAxis(chart, rows) {
419
+ let observed = false;
420
+ const xField = chartEncodingField(chart, "x") ?? chart.xField;
421
+ for (const row of rows) {
422
+ const value = row[xField];
423
+ if (value == null) continue;
424
+ observed = true;
425
+ if (asNumber(value) == null) return false;
426
+ }
427
+ return observed;
428
+ }
429
+
430
+ function chartContextText(chart) {
431
+ return `${chart.id} ${chart.title} ${chart.subtitle ?? ""} ${chartEncodingField(chart, "x") ?? chart.xField ?? ""}`.toLowerCase();
432
+ }
433
+
434
+ function chartHasContextMarker(chart, markers) {
435
+ const context = chartContextText(chart);
436
+ return markers.some((marker) => context.includes(marker));
437
+ }
438
+
439
+ export function hasTemporalXAxis(chart, rows) {
440
+ if (chartHasContextMarker(chart, ["date", "day", "month", "quarter", "time", "week", "year", "period"])) return true;
441
+ const xField = chartEncodingField(chart, "x") ?? chart.xField;
442
+ return rows.some((row) => isDateAxisValue(row[xField]));
443
+ }
444
+
445
+ export function chartHasBoxPlotFields(chart) {
446
+ const fields = new Set(asArray(chart.series).map((series) => series?.field).filter((field) => typeof field === "string").map((field) => field.toLowerCase()));
447
+ return ["min", "q1", "median", "q3", "max"].every((marker) => [...fields].some((field) => field.includes(marker)));
448
+ }
449
+
450
+ export function compatibleChartTypesFor(chart, rows) {
451
+ const rechartsChart = rechartsChartFromEncodedSpec(chart, rows);
452
+ return sharedCompatibleChartTypesFor(rechartsChart.chart, rechartsChart.rows);
453
+ }
454
+
455
+ export function compatibleChartTypesForArtifactCard(chart, rows) {
456
+ const rechartsChart = rechartsChartFromEncodedSpec(chart, rows);
457
+ return sharedCompatibleChartTypesForDataShape(rechartsChart.chart, rechartsChart.rows);
458
+ }
459
+
460
+ export function chartTypeSectionsForOptions(options) {
461
+ return sharedChartTypeSectionsForOptions(options);
462
+ }
@@ -0,0 +1,107 @@
1
+ import type { ChartPaletteKind, ChartType } from "./chart-contract";
2
+
3
+ export type ChartCapability =
4
+ | "axisFormatting"
5
+ | "categoryColor"
6
+ | "interactiveLegend"
7
+ | "referenceLines"
8
+ | "seriesLineStyle"
9
+ | "stacking"
10
+ | "timeSeries"
11
+ | "valueLabels";
12
+
13
+ export type ChartCapabilitySpec = {
14
+ capabilities: ChartCapability[];
15
+ paletteKinds: ChartPaletteKind[];
16
+ };
17
+
18
+ const TREND_PALETTES: ChartPaletteKind[] = ["categorical", "semantic", "identity"];
19
+ const COMPARISON_PALETTES: ChartPaletteKind[] = ["categorical", "semantic", "identity"];
20
+ const INTENSITY_PALETTES: ChartPaletteKind[] = ["sequential", "diverging"];
21
+
22
+ export const CHART_CAPABILITIES: Record<ChartType, ChartCapabilitySpec> = {
23
+ area: {
24
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines", "seriesLineStyle", "timeSeries", "valueLabels"],
25
+ paletteKinds: TREND_PALETTES,
26
+ },
27
+ bar: {
28
+ capabilities: ["axisFormatting", "categoryColor", "interactiveLegend", "referenceLines", "stacking", "valueLabels"],
29
+ paletteKinds: COMPARISON_PALETTES,
30
+ },
31
+ boxPlot: {
32
+ capabilities: ["axisFormatting"],
33
+ paletteKinds: ["semantic", "identity"],
34
+ },
35
+ funnel: {
36
+ capabilities: [],
37
+ paletteKinds: ["sequential", "identity"],
38
+ },
39
+ heatmap: {
40
+ capabilities: ["axisFormatting"],
41
+ paletteKinds: INTENSITY_PALETTES,
42
+ },
43
+ histogram: {
44
+ capabilities: ["axisFormatting", "referenceLines", "valueLabels"],
45
+ paletteKinds: ["sequential", "semantic", "identity"],
46
+ },
47
+ horizontalBar: {
48
+ capabilities: ["axisFormatting", "categoryColor", "interactiveLegend", "referenceLines", "valueLabels"],
49
+ paletteKinds: COMPARISON_PALETTES,
50
+ },
51
+ horizontalStackedBar: {
52
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines", "stacking", "valueLabels"],
53
+ paletteKinds: COMPARISON_PALETTES,
54
+ },
55
+ horizontalStackedBar100: {
56
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines", "stacking", "valueLabels"],
57
+ paletteKinds: COMPARISON_PALETTES,
58
+ },
59
+ leaderboard: {
60
+ capabilities: ["axisFormatting"],
61
+ paletteKinds: ["semantic", "identity"],
62
+ },
63
+ line: {
64
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines", "seriesLineStyle", "timeSeries", "valueLabels"],
65
+ paletteKinds: TREND_PALETTES,
66
+ },
67
+ pie: {
68
+ capabilities: [],
69
+ paletteKinds: COMPARISON_PALETTES,
70
+ },
71
+ scatter: {
72
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines"],
73
+ paletteKinds: COMPARISON_PALETTES,
74
+ },
75
+ sparkline: {
76
+ capabilities: ["seriesLineStyle", "timeSeries", "valueLabels"],
77
+ paletteKinds: TREND_PALETTES,
78
+ },
79
+ stackedArea: {
80
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines", "seriesLineStyle", "stacking", "timeSeries", "valueLabels"],
81
+ paletteKinds: COMPARISON_PALETTES,
82
+ },
83
+ stackedBar: {
84
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines", "stacking", "valueLabels"],
85
+ paletteKinds: COMPARISON_PALETTES,
86
+ },
87
+ stackedBar100: {
88
+ capabilities: ["axisFormatting", "interactiveLegend", "referenceLines", "stacking", "valueLabels"],
89
+ paletteKinds: COMPARISON_PALETTES,
90
+ },
91
+ waterfall: {
92
+ capabilities: ["axisFormatting", "referenceLines"],
93
+ paletteKinds: ["diverging", "semantic", "identity"],
94
+ },
95
+ };
96
+
97
+ export function chartCapabilitiesFor(type: ChartType): ChartCapabilitySpec {
98
+ return CHART_CAPABILITIES[type];
99
+ }
100
+
101
+ export function chartSupportsCapability(type: ChartType, capability: ChartCapability): boolean {
102
+ return chartCapabilitiesFor(type).capabilities.includes(capability);
103
+ }
104
+
105
+ export function chartSupportsPaletteKind(type: ChartType, paletteKind: ChartPaletteKind): boolean {
106
+ return chartCapabilitiesFor(type).paletteKinds.includes(paletteKind);
107
+ }