@sarjallab09/figma-intelligence 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/LICENSE +26 -0
  2. package/README.md +327 -0
  3. package/bin/cli.js +859 -0
  4. package/design-bridge/.env.example +5 -0
  5. package/design-bridge/bridge.js +196 -0
  6. package/design-bridge/lib/assets.js +367 -0
  7. package/design-bridge/lib/prompt.js +85 -0
  8. package/design-bridge/lib/server.js +66 -0
  9. package/design-bridge/lib/stitch.js +37 -0
  10. package/design-bridge/lib/tokens.js +82 -0
  11. package/design-bridge/package-lock.json +579 -0
  12. package/design-bridge/package.json +19 -0
  13. package/figma-bridge-plugin/README.md +97 -0
  14. package/figma-bridge-plugin/anthropic-chat-runner.js +192 -0
  15. package/figma-bridge-plugin/bridge-relay.js +2363 -0
  16. package/figma-bridge-plugin/chat-runner.js +459 -0
  17. package/figma-bridge-plugin/code.js +1528 -0
  18. package/figma-bridge-plugin/codex-runner.js +505 -0
  19. package/figma-bridge-plugin/component-schemas.js +110 -0
  20. package/figma-bridge-plugin/content-context.js +869 -0
  21. package/figma-bridge-plugin/create-button.js +216 -0
  22. package/figma-bridge-plugin/gemini-cli-runner.js +291 -0
  23. package/figma-bridge-plugin/gemini-runner.js +187 -0
  24. package/figma-bridge-plugin/html-to-figma.js +927 -0
  25. package/figma-bridge-plugin/knowledge-hub/.gitkeep +0 -0
  26. package/figma-bridge-plugin/knowledge-hub/uspec-references/anatomy-spec.md +159 -0
  27. package/figma-bridge-plugin/knowledge-hub/uspec-references/api-spec.md +162 -0
  28. package/figma-bridge-plugin/knowledge-hub/uspec-references/color-spec.md +148 -0
  29. package/figma-bridge-plugin/knowledge-hub/uspec-references/full-spec-template.md +314 -0
  30. package/figma-bridge-plugin/knowledge-hub/uspec-references/property-spec.md +175 -0
  31. package/figma-bridge-plugin/knowledge-hub/uspec-references/screen-reader-spec.md +180 -0
  32. package/figma-bridge-plugin/knowledge-hub/uspec-references/structure-spec.md +165 -0
  33. package/figma-bridge-plugin/manifest.json +21 -0
  34. package/figma-bridge-plugin/package-lock.json +1936 -0
  35. package/figma-bridge-plugin/package.json +20 -0
  36. package/figma-bridge-plugin/perplexity-runner.js +188 -0
  37. package/figma-bridge-plugin/references/SKILL.md +178 -0
  38. package/figma-bridge-plugin/references/anatomy-spec.md +159 -0
  39. package/figma-bridge-plugin/references/api-spec.md +162 -0
  40. package/figma-bridge-plugin/references/color-spec.md +148 -0
  41. package/figma-bridge-plugin/references/full-spec-template.md +314 -0
  42. package/figma-bridge-plugin/references/property-spec.md +175 -0
  43. package/figma-bridge-plugin/references/screen-reader-spec.md +180 -0
  44. package/figma-bridge-plugin/references/structure-spec.md +165 -0
  45. package/figma-bridge-plugin/shared-prompt-config.js +604 -0
  46. package/figma-bridge-plugin/spec-helpers/build-table.js +269 -0
  47. package/figma-bridge-plugin/spec-helpers/classify-elements.js +189 -0
  48. package/figma-bridge-plugin/spec-helpers/index.js +35 -0
  49. package/figma-bridge-plugin/spec-helpers/parse-figma-link.js +49 -0
  50. package/figma-bridge-plugin/spec-helpers/position-markers.js +158 -0
  51. package/figma-bridge-plugin/stitch-auth.js +322 -0
  52. package/figma-bridge-plugin/stitch-runner.js +1427 -0
  53. package/figma-bridge-plugin/token-resolver.js +107 -0
  54. package/figma-bridge-plugin/ui.html +4467 -0
  55. package/figma-intelligence-layer/.env.example +39 -0
  56. package/figma-intelligence-layer/docs/local-image-generation.md +60 -0
  57. package/figma-intelligence-layer/examples/comfyui-workflow-template.example.json +101 -0
  58. package/figma-intelligence-layer/jest.config.js +14 -0
  59. package/figma-intelligence-layer/mcp-config.json +19 -0
  60. package/figma-intelligence-layer/package-lock.json +5892 -0
  61. package/figma-intelligence-layer/package.json +48 -0
  62. package/figma-intelligence-layer/scripts/setup-comfyui-local.sh +67 -0
  63. package/figma-intelligence-layer/scripts/start-comfyui.sh +33 -0
  64. package/figma-intelligence-layer/src/index.ts +2233 -0
  65. package/figma-intelligence-layer/src/shared/auto-layout-validator.ts +404 -0
  66. package/figma-intelligence-layer/src/shared/cache.ts +187 -0
  67. package/figma-intelligence-layer/src/shared/color-operations.ts +533 -0
  68. package/figma-intelligence-layer/src/shared/color-utils.ts +138 -0
  69. package/figma-intelligence-layer/src/shared/component-script-builder.ts +413 -0
  70. package/figma-intelligence-layer/src/shared/component-templates.ts +2767 -0
  71. package/figma-intelligence-layer/src/shared/concept-taxonomy.ts +694 -0
  72. package/figma-intelligence-layer/src/shared/decision-log.ts +128 -0
  73. package/figma-intelligence-layer/src/shared/design-system-context.ts +568 -0
  74. package/figma-intelligence-layer/src/shared/design-system-intelligence.ts +131 -0
  75. package/figma-intelligence-layer/src/shared/design-system-matcher.ts +184 -0
  76. package/figma-intelligence-layer/src/shared/design-system-normalizers.ts +196 -0
  77. package/figma-intelligence-layer/src/shared/design-system-tokens.ts +295 -0
  78. package/figma-intelligence-layer/src/shared/dtcg-validator.ts +530 -0
  79. package/figma-intelligence-layer/src/shared/enrichment-pipeline.ts +671 -0
  80. package/figma-intelligence-layer/src/shared/figma-bridge.ts +1408 -0
  81. package/figma-intelligence-layer/src/shared/font-config.ts +126 -0
  82. package/figma-intelligence-layer/src/shared/icon-catalog.ts +360 -0
  83. package/figma-intelligence-layer/src/shared/icon-fetch.ts +80 -0
  84. package/figma-intelligence-layer/src/shared/prototype-script-builder.ts +162 -0
  85. package/figma-intelligence-layer/src/shared/response-compression.ts +440 -0
  86. package/figma-intelligence-layer/src/shared/semantic-token-catalog.ts +324 -0
  87. package/figma-intelligence-layer/src/shared/token-binder.ts +505 -0
  88. package/figma-intelligence-layer/src/shared/token-math.ts +427 -0
  89. package/figma-intelligence-layer/src/shared/token-naming.ts +468 -0
  90. package/figma-intelligence-layer/src/shared/token-utils.ts +420 -0
  91. package/figma-intelligence-layer/src/shared/types.ts +346 -0
  92. package/figma-intelligence-layer/src/shared/typography-presets.ts +94 -0
  93. package/figma-intelligence-layer/src/shared/unsplash.ts +165 -0
  94. package/figma-intelligence-layer/src/shared/vision-client.ts +607 -0
  95. package/figma-intelligence-layer/src/shared/vision-provider-anthropic.ts +334 -0
  96. package/figma-intelligence-layer/src/shared/vision-provider-openai.ts +446 -0
  97. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-handler.ts +782 -0
  98. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-renderer.ts +496 -0
  99. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotation-kit.ts +230 -0
  100. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/colorblind-sim.ts +66 -0
  101. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/index.ts +810 -0
  102. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-analyzer.ts +1191 -0
  103. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-figma-page.ts +1346 -0
  104. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-handler.ts +148 -0
  105. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-figma-page.ts +499 -0
  106. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-report.ts +910 -0
  107. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-checker.ts +989 -0
  108. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-criteria.ts +1160 -0
  109. package/figma-intelligence-layer/src/tools/phase1-vision/design-from-ref/index.ts +424 -0
  110. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/component-recognizer.ts +38 -0
  111. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/ds-matcher.ts +111 -0
  112. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/font-matcher.ts +114 -0
  113. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/icon-resolver.ts +103 -0
  114. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/index.ts +1060 -0
  115. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/layout-segmenter.ts +18 -0
  116. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/token-inferencer.ts +39 -0
  117. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/vision-pipeline.ts +58 -0
  118. package/figma-intelligence-layer/src/tools/phase1-vision/sketch-to-design/index.ts +298 -0
  119. package/figma-intelligence-layer/src/tools/phase1-vision/visual-audit/index.ts +197 -0
  120. package/figma-intelligence-layer/src/tools/phase2-accuracy/component-audit/index.ts +494 -0
  121. package/figma-intelligence-layer/src/tools/phase2-accuracy/intent-translator/index.ts +356 -0
  122. package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/container-patterns.ts +123 -0
  123. package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/index.ts +663 -0
  124. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/built-in-rules.yaml +56 -0
  125. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/index.ts +614 -0
  126. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/rule-engine.ts +113 -0
  127. package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/color-theory.ts +178 -0
  128. package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/index.ts +470 -0
  129. package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/index.ts +429 -0
  130. package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/token-override-maps.ts +226 -0
  131. package/figma-intelligence-layer/src/tools/phase3-generation/ai-image-insert/index.ts +535 -0
  132. package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/index.ts +660 -0
  133. package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/pattern-fingerprints.ts +209 -0
  134. package/figma-intelligence-layer/src/tools/phase3-generation/composition-builder/index.ts +540 -0
  135. package/figma-intelligence-layer/src/tools/phase3-generation/figma-animated-build.ts +391 -0
  136. package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/index.ts +2019 -0
  137. package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/screen-templates.ts +131 -0
  138. package/figma-intelligence-layer/src/tools/phase3-generation/prototype-map/index.ts +381 -0
  139. package/figma-intelligence-layer/src/tools/phase3-generation/prototype-wire/index.ts +565 -0
  140. package/figma-intelligence-layer/src/tools/phase3-generation/swarm-build/index.ts +764 -0
  141. package/figma-intelligence-layer/src/tools/phase3-generation/system-drift/index.ts +535 -0
  142. package/figma-intelligence-layer/src/tools/phase3-generation/unsplash-search/index.ts +84 -0
  143. package/figma-intelligence-layer/src/tools/phase3-generation/url-to-frame/index.ts +401 -0
  144. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/css-animations.ts +68 -0
  145. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/framer-motion.ts +78 -0
  146. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/swift-animations.ts +93 -0
  147. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/index.ts +596 -0
  148. package/figma-intelligence-layer/src/tools/phase4-sync/ci-check/index.ts +462 -0
  149. package/figma-intelligence-layer/src/tools/phase4-sync/export-tokens/index.ts +1470 -0
  150. package/figma-intelligence-layer/src/tools/phase4-sync/generate-component-code/index.ts +829 -0
  151. package/figma-intelligence-layer/src/tools/phase4-sync/handoff-spec/index.ts +702 -0
  152. package/figma-intelligence-layer/src/tools/phase4-sync/icon-library-sync/index.ts +483 -0
  153. package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/index.ts +501 -0
  154. package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/storybook-parser.ts +106 -0
  155. package/figma-intelligence-layer/src/tools/phase4-sync/watch-docs/index.ts +676 -0
  156. package/figma-intelligence-layer/src/tools/phase4-sync/webhook-listener/index.ts +560 -0
  157. package/figma-intelligence-layer/src/tools/phase5-governance/apg-doc/index.ts +1043 -0
  158. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/component-detection.ts +620 -0
  159. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/anatomy.ts +331 -0
  160. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/color-tokens.ts +77 -0
  161. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/properties.ts +54 -0
  162. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/snapshot.ts +287 -0
  163. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/spacing.ts +71 -0
  164. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/states.ts +43 -0
  165. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/typography.ts +71 -0
  166. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/index.ts +221 -0
  167. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/_default.ts +166 -0
  168. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/accordion.ts +232 -0
  169. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/alert.ts +234 -0
  170. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar-group.ts +270 -0
  171. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar.ts +249 -0
  172. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/badge.ts +231 -0
  173. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/banner.ts +293 -0
  174. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/breadcrumb.ts +240 -0
  175. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/button.ts +243 -0
  176. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/calendar.ts +307 -0
  177. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/card.ts +143 -0
  178. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/checkbox.ts +227 -0
  179. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/chip.ts +233 -0
  180. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/combobox.ts +282 -0
  181. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/datepicker.ts +276 -0
  182. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/divider.ts +223 -0
  183. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/drawer.ts +255 -0
  184. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/dropdown-menu.ts +289 -0
  185. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/empty-state.ts +261 -0
  186. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/file-uploader.ts +290 -0
  187. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/form.ts +265 -0
  188. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/grid.ts +238 -0
  189. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/icon.ts +255 -0
  190. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/index.ts +128 -0
  191. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-edit.ts +286 -0
  192. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-message.ts +255 -0
  193. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/input.ts +330 -0
  194. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/link.ts +247 -0
  195. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/list.ts +250 -0
  196. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/menu.ts +247 -0
  197. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/modal.ts +144 -0
  198. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navbar.ts +264 -0
  199. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navigation.ts +251 -0
  200. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/number-input.ts +261 -0
  201. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/pagination.ts +248 -0
  202. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/popover.ts +270 -0
  203. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/progress.ts +251 -0
  204. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/radio.ts +142 -0
  205. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/range-slider.ts +282 -0
  206. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/rating.ts +250 -0
  207. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/search.ts +258 -0
  208. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/segmented-control.ts +265 -0
  209. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/select.ts +319 -0
  210. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/skeleton.ts +256 -0
  211. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/slider.ts +232 -0
  212. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/spinner.ts +239 -0
  213. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/status-dot.ts +252 -0
  214. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/stepper.ts +270 -0
  215. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/table.ts +244 -0
  216. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tabs.ts +143 -0
  217. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tag.ts +243 -0
  218. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/textarea.ts +259 -0
  219. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/time-picker.ts +293 -0
  220. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toast.ts +144 -0
  221. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toggle.ts +289 -0
  222. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toolbar.ts +267 -0
  223. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tooltip.ts +232 -0
  224. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/treeview.ts +257 -0
  225. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/typography.ts +319 -0
  226. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/legacy-compat.ts +121 -0
  227. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/anatomy-diagram.ts +430 -0
  228. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/figma-page.ts +312 -0
  229. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/json.ts +129 -0
  230. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/markdown.ts +78 -0
  231. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/visual-doc.ts +2333 -0
  232. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/accessibility.ts +100 -0
  233. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/anatomy.ts +32 -0
  234. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/color-tokens.ts +59 -0
  235. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/content-guidance.ts +18 -0
  236. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/design-tokens.ts +53 -0
  237. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/interaction-rules.ts +19 -0
  238. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/overview.ts +91 -0
  239. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/properties-api.ts +71 -0
  240. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/qa-criteria.ts +19 -0
  241. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/related-components.ts +110 -0
  242. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/responsive.ts +19 -0
  243. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/size-specs.ts +67 -0
  244. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/spacing-structure.ts +58 -0
  245. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/state-specs.ts +79 -0
  246. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/states.ts +50 -0
  247. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/type-hierarchy.ts +33 -0
  248. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/typography.ts +55 -0
  249. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/usage-guidelines.ts +73 -0
  250. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/variants.ts +81 -0
  251. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/types.ts +409 -0
  252. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/index.ts +198 -0
  253. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/renderer.ts +701 -0
  254. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/types.ts +88 -0
  255. package/figma-intelligence-layer/src/tools/phase5-governance/decision-log/index.ts +135 -0
  256. package/figma-intelligence-layer/src/tools/phase5-governance/design-decision-log/index.ts +491 -0
  257. package/figma-intelligence-layer/src/tools/phase5-governance/ds-primitives/index.ts +416 -0
  258. package/figma-intelligence-layer/src/tools/phase5-governance/ds-scaffolder/index.ts +722 -0
  259. package/figma-intelligence-layer/src/tools/phase5-governance/ds-variables/index.ts +449 -0
  260. package/figma-intelligence-layer/src/tools/phase5-governance/health-report/index.ts +393 -0
  261. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/index.ts +406 -0
  262. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/figma-page.ts +292 -0
  263. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/json.ts +24 -0
  264. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/markdown.ts +172 -0
  265. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/naming-guide.ts +409 -0
  266. package/figma-intelligence-layer/src/tools/phase5-governance/token-analytics/index.ts +594 -0
  267. package/figma-intelligence-layer/src/tools/phase5-governance/token-docs/index.ts +710 -0
  268. package/figma-intelligence-layer/src/tools/phase5-governance/token-migrate/index.ts +458 -0
  269. package/figma-intelligence-layer/src/tools/phase5-governance/token-naming/index.ts +134 -0
  270. package/figma-intelligence-layer/tests/apg-doc.test.ts +101 -0
  271. package/figma-intelligence-layer/tests/design-system-context.test.ts +152 -0
  272. package/figma-intelligence-layer/tests/design-system-matcher.test.ts +144 -0
  273. package/figma-intelligence-layer/tests/figma-bridge.test.ts +83 -0
  274. package/figma-intelligence-layer/tests/generate-image-and-insert.test.ts +56 -0
  275. package/figma-intelligence-layer/tests/screen-cloner-regression.test.ts +69 -0
  276. package/figma-intelligence-layer/tests/smoke.test.ts +174 -0
  277. package/figma-intelligence-layer/tests/spec-generator.test.ts +127 -0
  278. package/figma-intelligence-layer/tests/token-migrate.test.ts +21 -0
  279. package/figma-intelligence-layer/tests/token-naming.test.ts +30 -0
  280. package/figma-intelligence-layer/tsconfig.json +19 -0
  281. package/package.json +35 -0
  282. package/scripts/clean-existing-chunks.js +179 -0
  283. package/scripts/connect-ai-tool.js +490 -0
  284. package/scripts/convert-hub-pdfs.js +425 -0
  285. package/scripts/figma-mcp-status.js +349 -0
  286. package/scripts/register-codex-mcp.js +96 -0
@@ -0,0 +1,676 @@
1
+ // ─────────────────────────────────────────────────────────────────────────────
2
+ // figma_watch_docs — Auto-updating documentation
3
+ //
4
+ // Monitors components for changes and regenerates documentation when drift is
5
+ // detected. Produces changelogs, tracks doc freshness, and integrates with
6
+ // the webhook system for real-time updates.
7
+ //
8
+ // Features:
9
+ // - Compare current component state against last-known spec snapshot
10
+ // - Detect what changed (variants added, tokens changed, states modified)
11
+ // - Auto-regenerate component spec when drift is detected
12
+ // - Generate human-readable changelog entries
13
+ // - Track doc freshness scores across the entire file
14
+ // - Register webhook triggers for automated doc updates
15
+ // ─────────────────────────────────────────────────────────────────────────────
16
+
17
+ import fs from "fs/promises";
18
+ import path from "path";
19
+ import { getBridge } from "../../../shared/figma-bridge.js";
20
+ import { componentSpecHandler } from "../../phase5-governance/component-spec/index.js";
21
+
22
+ // ─── Types ──────────────────────────────────────────────────────────────────
23
+
24
+ export interface WatchDocsArgs {
25
+ /** Action to perform */
26
+ action: "check" | "regenerate" | "changelog" | "freshness" | "register-webhook";
27
+ /** Component node IDs to watch (omit for all components on current page) */
28
+ nodeIds?: string[];
29
+ /** Path to store spec snapshots for comparison */
30
+ snapshotDir?: string;
31
+ /** Auto-regenerate specs that are stale */
32
+ autoRegenerate?: boolean;
33
+ /** Output format for regenerated specs */
34
+ specFormat?: "json" | "markdown" | "figma-page" | "all";
35
+ /** Webhook file key (for register-webhook action) */
36
+ fileKey?: string;
37
+ }
38
+
39
+ interface ComponentSnapshot {
40
+ nodeId: string;
41
+ name: string;
42
+ timestamp: string;
43
+ variantCount: number;
44
+ variantAxes: Array<{ name: string; values: string[] }>;
45
+ stateCount: number;
46
+ states: string[];
47
+ tokenCount: number;
48
+ tokenNames: string[];
49
+ properties: Array<{ name: string; type: string }>;
50
+ description: string;
51
+ hash: string;
52
+ }
53
+
54
+ interface DriftEntry {
55
+ nodeId: string;
56
+ componentName: string;
57
+ driftType: "variant-added" | "variant-removed" | "token-changed" | "state-changed" | "property-changed" | "new-component" | "description-changed";
58
+ field: string;
59
+ before: string;
60
+ after: string;
61
+ severity: "major" | "minor" | "patch";
62
+ }
63
+
64
+ interface ChangelogEntry {
65
+ version: string;
66
+ date: string;
67
+ component: string;
68
+ changes: Array<{
69
+ type: "added" | "changed" | "removed" | "fixed";
70
+ description: string;
71
+ }>;
72
+ }
73
+
74
+ // ─── Snapshot management ───────────────────────────────────────────────────
75
+
76
+ function defaultSnapshotDir(): string {
77
+ return path.join(process.cwd(), ".figma-docs-snapshots");
78
+ }
79
+
80
+ async function ensureSnapshotDir(dir: string): Promise<void> {
81
+ try {
82
+ await fs.mkdir(dir, { recursive: true });
83
+ } catch { /* exists */ }
84
+ }
85
+
86
+ async function loadSnapshot(dir: string, nodeId: string): Promise<ComponentSnapshot | null> {
87
+ const filePath = path.join(dir, `${nodeId.replace(/[:/]/g, "_")}.json`);
88
+ try {
89
+ const data = await fs.readFile(filePath, "utf-8");
90
+ return JSON.parse(data);
91
+ } catch {
92
+ return null;
93
+ }
94
+ }
95
+
96
+ async function saveSnapshot(dir: string, snapshot: ComponentSnapshot): Promise<void> {
97
+ const filePath = path.join(dir, `${snapshot.nodeId.replace(/[:/]/g, "_")}.json`);
98
+ await fs.writeFile(filePath, JSON.stringify(snapshot, null, 2), "utf-8");
99
+ }
100
+
101
+ function hashSnapshot(snap: Omit<ComponentSnapshot, "hash" | "timestamp">): string {
102
+ const str = JSON.stringify({
103
+ variantAxes: snap.variantAxes,
104
+ states: snap.states,
105
+ tokenNames: snap.tokenNames,
106
+ properties: snap.properties,
107
+ description: snap.description,
108
+ });
109
+ // Simple hash for change detection
110
+ let hash = 0;
111
+ for (let i = 0; i < str.length; i++) {
112
+ const char = str.charCodeAt(i);
113
+ hash = ((hash << 5) - hash) + char;
114
+ hash |= 0;
115
+ }
116
+ return Math.abs(hash).toString(36);
117
+ }
118
+
119
+ // ─── Component scanning ───────────────────────────────────────────────────
120
+
121
+ async function scanComponents(nodeIds?: string[]): Promise<ComponentSnapshot[]> {
122
+ const bridge = await getBridge();
123
+
124
+ const script = nodeIds?.length
125
+ ? `
126
+ (async () => {
127
+ var results = [];
128
+ var ids = ${JSON.stringify(nodeIds)};
129
+ for (var i = 0; i < ids.length; i++) {
130
+ var node = figma.getNodeById(ids[i]);
131
+ if (!node) continue;
132
+ results.push(extractComponent(node));
133
+ }
134
+ function extractComponent(node) {
135
+ var axes = [];
136
+ var states = [];
137
+ var tokenNames = [];
138
+ var props = [];
139
+
140
+ if (node.variantGroupProperties) {
141
+ var vgp = node.variantGroupProperties;
142
+ for (var key in vgp) {
143
+ axes.push({ name: key, values: vgp[key].values || [] });
144
+ if (key.toLowerCase() === 'state') {
145
+ states = vgp[key].values || [];
146
+ }
147
+ }
148
+ }
149
+
150
+ if (node.componentPropertyDefinitions) {
151
+ var cpd = node.componentPropertyDefinitions;
152
+ for (var key in cpd) {
153
+ props.push({ name: key, type: cpd[key].type });
154
+ }
155
+ }
156
+
157
+ // Scan for tokens
158
+ function scanTokens(n) {
159
+ var bound = n.boundVariables || {};
160
+ for (var prop in bound) {
161
+ var binding = bound[prop];
162
+ if (binding && binding.id) {
163
+ try {
164
+ var v = figma.variables.getVariableById(binding.id);
165
+ if (v && tokenNames.indexOf(v.name) === -1) tokenNames.push(v.name);
166
+ } catch (e) {}
167
+ }
168
+ if (Array.isArray(binding)) {
169
+ for (var j = 0; j < binding.length; j++) {
170
+ if (binding[j] && binding[j].id) {
171
+ try {
172
+ var v = figma.variables.getVariableById(binding[j].id);
173
+ if (v && tokenNames.indexOf(v.name) === -1) tokenNames.push(v.name);
174
+ } catch (e) {}
175
+ }
176
+ }
177
+ }
178
+ }
179
+ if (n.children) {
180
+ for (var i = 0; i < n.children.length; i++) {
181
+ scanTokens(n.children[i]);
182
+ }
183
+ }
184
+ }
185
+ scanTokens(node);
186
+
187
+ return {
188
+ nodeId: node.id,
189
+ name: node.name,
190
+ variantCount: node.children ? node.children.length : 0,
191
+ variantAxes: axes,
192
+ stateCount: states.length,
193
+ states: states,
194
+ tokenCount: tokenNames.length,
195
+ tokenNames: tokenNames,
196
+ properties: props,
197
+ description: node.description || ''
198
+ };
199
+ }
200
+ return results;
201
+ })();
202
+ `
203
+ : `
204
+ (async () => {
205
+ var results = [];
206
+ var page = figma.currentPage;
207
+ var components = page.findAll(function(n) {
208
+ return n.type === 'COMPONENT_SET' || (n.type === 'COMPONENT' && !n.parent.type.includes('COMPONENT'));
209
+ });
210
+ for (var i = 0; i < Math.min(components.length, 50); i++) {
211
+ var node = components[i];
212
+ var axes = [];
213
+ var states = [];
214
+ var tokenNames = [];
215
+ var props = [];
216
+
217
+ if (node.variantGroupProperties) {
218
+ var vgp = node.variantGroupProperties;
219
+ for (var key in vgp) {
220
+ axes.push({ name: key, values: vgp[key].values || [] });
221
+ if (key.toLowerCase() === 'state') states = vgp[key].values || [];
222
+ }
223
+ }
224
+
225
+ if (node.componentPropertyDefinitions) {
226
+ var cpd = node.componentPropertyDefinitions;
227
+ for (var key in cpd) {
228
+ props.push({ name: key, type: cpd[key].type });
229
+ }
230
+ }
231
+
232
+ function scanTokens(n, names) {
233
+ var bound = n.boundVariables || {};
234
+ for (var prop in bound) {
235
+ var binding = bound[prop];
236
+ if (binding && binding.id) {
237
+ try {
238
+ var v = figma.variables.getVariableById(binding.id);
239
+ if (v && names.indexOf(v.name) === -1) names.push(v.name);
240
+ } catch(e) {}
241
+ }
242
+ if (Array.isArray(binding)) {
243
+ for (var j = 0; j < binding.length; j++) {
244
+ if (binding[j] && binding[j].id) {
245
+ try {
246
+ var v = figma.variables.getVariableById(binding[j].id);
247
+ if (v && names.indexOf(v.name) === -1) names.push(v.name);
248
+ } catch(e) {}
249
+ }
250
+ }
251
+ }
252
+ }
253
+ if (n.children) {
254
+ for (var c = 0; c < n.children.length; c++) scanTokens(n.children[c], names);
255
+ }
256
+ }
257
+ scanTokens(node, tokenNames);
258
+
259
+ results.push({
260
+ nodeId: node.id,
261
+ name: node.name,
262
+ variantCount: node.children ? node.children.length : 0,
263
+ variantAxes: axes,
264
+ stateCount: states.length,
265
+ states: states,
266
+ tokenCount: tokenNames.length,
267
+ tokenNames: tokenNames,
268
+ properties: props,
269
+ description: node.description || ''
270
+ });
271
+ }
272
+ return results;
273
+ })();
274
+ `;
275
+
276
+ const result = await bridge.execute(script);
277
+ if (!result.success || !result.result) {
278
+ throw new Error(result.error || "Failed to scan components");
279
+ }
280
+
281
+ const rawSnapshots = result.result as Array<Omit<ComponentSnapshot, "hash" | "timestamp">>;
282
+ const now = new Date().toISOString();
283
+
284
+ return rawSnapshots.map((s) => ({
285
+ ...s,
286
+ timestamp: now,
287
+ hash: hashSnapshot(s),
288
+ }));
289
+ }
290
+
291
+ // ─── Drift detection ──────────────────────────────────────────────────────
292
+
293
+ function detectDrift(old: ComponentSnapshot, current: ComponentSnapshot): DriftEntry[] {
294
+ const drifts: DriftEntry[] = [];
295
+
296
+ // Check variant axes
297
+ for (const axis of current.variantAxes) {
298
+ const oldAxis = old.variantAxes.find((a) => a.name === axis.name);
299
+ if (!oldAxis) {
300
+ drifts.push({
301
+ nodeId: current.nodeId,
302
+ componentName: current.name,
303
+ driftType: "variant-added",
304
+ field: `variantAxis:${axis.name}`,
305
+ before: "(none)",
306
+ after: axis.values.join(", "),
307
+ severity: "major",
308
+ });
309
+ } else {
310
+ const added = axis.values.filter((v) => !oldAxis.values.includes(v));
311
+ const removed = oldAxis.values.filter((v) => !axis.values.includes(v));
312
+ for (const v of added) {
313
+ drifts.push({
314
+ nodeId: current.nodeId,
315
+ componentName: current.name,
316
+ driftType: "variant-added",
317
+ field: `${axis.name}:${v}`,
318
+ before: oldAxis.values.join(", "),
319
+ after: axis.values.join(", "),
320
+ severity: "minor",
321
+ });
322
+ }
323
+ for (const v of removed) {
324
+ drifts.push({
325
+ nodeId: current.nodeId,
326
+ componentName: current.name,
327
+ driftType: "variant-removed",
328
+ field: `${axis.name}:${v}`,
329
+ before: oldAxis.values.join(", "),
330
+ after: axis.values.join(", "),
331
+ severity: "major",
332
+ });
333
+ }
334
+ }
335
+ }
336
+
337
+ // Check removed axes
338
+ for (const oldAxis of old.variantAxes) {
339
+ if (!current.variantAxes.find((a) => a.name === oldAxis.name)) {
340
+ drifts.push({
341
+ nodeId: current.nodeId,
342
+ componentName: current.name,
343
+ driftType: "variant-removed",
344
+ field: `variantAxis:${oldAxis.name}`,
345
+ before: oldAxis.values.join(", "),
346
+ after: "(removed)",
347
+ severity: "major",
348
+ });
349
+ }
350
+ }
351
+
352
+ // Check states
353
+ const addedStates = current.states.filter((s) => !old.states.includes(s));
354
+ const removedStates = old.states.filter((s) => !current.states.includes(s));
355
+ for (const s of addedStates) {
356
+ drifts.push({ nodeId: current.nodeId, componentName: current.name, driftType: "state-changed", field: `state:${s}`, before: "(none)", after: s, severity: "minor" });
357
+ }
358
+ for (const s of removedStates) {
359
+ drifts.push({ nodeId: current.nodeId, componentName: current.name, driftType: "state-changed", field: `state:${s}`, before: s, after: "(removed)", severity: "major" });
360
+ }
361
+
362
+ // Check tokens
363
+ const addedTokens = current.tokenNames.filter((t) => !old.tokenNames.includes(t));
364
+ const removedTokens = old.tokenNames.filter((t) => !current.tokenNames.includes(t));
365
+ for (const t of addedTokens) {
366
+ drifts.push({ nodeId: current.nodeId, componentName: current.name, driftType: "token-changed", field: t, before: "(none)", after: t, severity: "patch" });
367
+ }
368
+ for (const t of removedTokens) {
369
+ drifts.push({ nodeId: current.nodeId, componentName: current.name, driftType: "token-changed", field: t, before: t, after: "(removed)", severity: "minor" });
370
+ }
371
+
372
+ // Check properties
373
+ const currentPropNames = current.properties.map((p) => p.name);
374
+ const oldPropNames = old.properties.map((p) => p.name);
375
+ for (const p of current.properties) {
376
+ if (!oldPropNames.includes(p.name)) {
377
+ drifts.push({ nodeId: current.nodeId, componentName: current.name, driftType: "property-changed", field: p.name, before: "(none)", after: `${p.name} (${p.type})`, severity: "minor" });
378
+ }
379
+ }
380
+ for (const p of old.properties) {
381
+ if (!currentPropNames.includes(p.name)) {
382
+ drifts.push({ nodeId: current.nodeId, componentName: current.name, driftType: "property-changed", field: p.name, before: `${p.name} (${p.type})`, after: "(removed)", severity: "major" });
383
+ }
384
+ }
385
+
386
+ // Check description
387
+ if (old.description !== current.description) {
388
+ drifts.push({ nodeId: current.nodeId, componentName: current.name, driftType: "description-changed", field: "description", before: old.description.slice(0, 80), after: current.description.slice(0, 80), severity: "patch" });
389
+ }
390
+
391
+ return drifts;
392
+ }
393
+
394
+ // ─── Changelog generator ──────────────────────────────────────────────────
395
+
396
+ function generateChangelog(drifts: DriftEntry[]): ChangelogEntry[] {
397
+ const byComponent = new Map<string, DriftEntry[]>();
398
+ for (const d of drifts) {
399
+ const existing = byComponent.get(d.componentName) ?? [];
400
+ existing.push(d);
401
+ byComponent.set(d.componentName, existing);
402
+ }
403
+
404
+ const entries: ChangelogEntry[] = [];
405
+ const today = new Date().toISOString().slice(0, 10);
406
+
407
+ for (const [component, componentDrifts] of byComponent) {
408
+ const changes: ChangelogEntry["changes"] = [];
409
+
410
+ for (const d of componentDrifts) {
411
+ switch (d.driftType) {
412
+ case "variant-added":
413
+ changes.push({ type: "added", description: `Added variant ${d.field}: ${d.after}` });
414
+ break;
415
+ case "variant-removed":
416
+ changes.push({ type: "removed", description: `Removed variant ${d.field}` });
417
+ break;
418
+ case "state-changed":
419
+ changes.push({
420
+ type: d.after === "(removed)" ? "removed" : "added",
421
+ description: d.after === "(removed)" ? `Removed state: ${d.before}` : `Added state: ${d.after}`,
422
+ });
423
+ break;
424
+ case "token-changed":
425
+ changes.push({
426
+ type: d.after === "(removed)" ? "removed" : "changed",
427
+ description: d.after === "(removed)" ? `Removed token binding: ${d.before}` : `Added token binding: ${d.after}`,
428
+ });
429
+ break;
430
+ case "property-changed":
431
+ changes.push({
432
+ type: d.after === "(removed)" ? "removed" : "added",
433
+ description: d.after === "(removed)" ? `Removed property: ${d.field}` : `Added property: ${d.after}`,
434
+ });
435
+ break;
436
+ case "description-changed":
437
+ changes.push({ type: "changed", description: `Updated component description` });
438
+ break;
439
+ }
440
+ }
441
+
442
+ // Determine version bump
443
+ const hasMajor = componentDrifts.some((d) => d.severity === "major");
444
+ const hasMinor = componentDrifts.some((d) => d.severity === "minor");
445
+ const version = hasMajor ? "major" : hasMinor ? "minor" : "patch";
446
+
447
+ entries.push({ version, date: today, component, changes });
448
+ }
449
+
450
+ return entries;
451
+ }
452
+
453
+ function renderChangelogMarkdown(entries: ChangelogEntry[]): string {
454
+ const lines: string[] = [];
455
+ lines.push(`# Component Changelog`);
456
+ lines.push(`> Auto-generated by \`figma_watch_docs\``);
457
+ lines.push(``);
458
+
459
+ for (const entry of entries) {
460
+ lines.push(`## ${entry.component} — ${entry.version} (${entry.date})`);
461
+ lines.push(``);
462
+ for (const change of entry.changes) {
463
+ const icon = change.type === "added" ? "➕" : change.type === "removed" ? "➖" : change.type === "fixed" ? "🔧" : "🔄";
464
+ lines.push(`- ${icon} **${change.type}**: ${change.description}`);
465
+ }
466
+ lines.push(``);
467
+ }
468
+
469
+ return lines.join("\n");
470
+ }
471
+
472
+ // ─── Main handler ──────────────────────────────────────────────────────────
473
+
474
+ export async function watchDocsHandler(args: WatchDocsArgs): Promise<unknown> {
475
+ const snapshotDir = args.snapshotDir ?? defaultSnapshotDir();
476
+ await ensureSnapshotDir(snapshotDir);
477
+
478
+ switch (args.action) {
479
+ case "check": {
480
+ // Scan current components and compare against snapshots
481
+ const current = await scanComponents(args.nodeIds);
482
+ const allDrifts: DriftEntry[] = [];
483
+ const staleComponents: string[] = [];
484
+ const freshComponents: string[] = [];
485
+
486
+ for (const snap of current) {
487
+ const old = await loadSnapshot(snapshotDir, snap.nodeId);
488
+ if (!old) {
489
+ allDrifts.push({
490
+ nodeId: snap.nodeId,
491
+ componentName: snap.name,
492
+ driftType: "new-component",
493
+ field: "component",
494
+ before: "(none)",
495
+ after: snap.name,
496
+ severity: "major",
497
+ });
498
+ staleComponents.push(snap.name);
499
+ } else if (old.hash !== snap.hash) {
500
+ const drifts = detectDrift(old, snap);
501
+ allDrifts.push(...drifts);
502
+ if (drifts.length > 0) staleComponents.push(snap.name);
503
+ else freshComponents.push(snap.name);
504
+ } else {
505
+ freshComponents.push(snap.name);
506
+ }
507
+ }
508
+
509
+ // Auto-regenerate if requested
510
+ const regenerated: string[] = [];
511
+ if (args.autoRegenerate && staleComponents.length > 0) {
512
+ for (const snap of current) {
513
+ if (!staleComponents.includes(snap.name)) continue;
514
+ try {
515
+ await componentSpecHandler({
516
+ nodeId: snap.nodeId,
517
+ outputFormat: args.specFormat ?? "markdown",
518
+ });
519
+ await saveSnapshot(snapshotDir, snap);
520
+ regenerated.push(snap.name);
521
+ } catch { /* skip failed */ }
522
+ }
523
+ }
524
+
525
+ // Save all current snapshots
526
+ for (const snap of current) {
527
+ await saveSnapshot(snapshotDir, snap);
528
+ }
529
+
530
+ const changelog = generateChangelog(allDrifts);
531
+
532
+ return {
533
+ action: "check",
534
+ totalComponents: current.length,
535
+ staleCount: staleComponents.length,
536
+ freshCount: freshComponents.length,
537
+ staleComponents,
538
+ freshComponents,
539
+ drifts: allDrifts,
540
+ changelog: changelog.length > 0 ? renderChangelogMarkdown(changelog) : null,
541
+ regenerated: regenerated.length > 0 ? regenerated : undefined,
542
+ freshness: current.length > 0
543
+ ? Math.round((freshComponents.length / current.length) * 100)
544
+ : 100,
545
+ };
546
+ }
547
+
548
+ case "regenerate": {
549
+ // Force-regenerate specs for specified components
550
+ const current = await scanComponents(args.nodeIds);
551
+ const results: Array<{ name: string; success: boolean; error?: string }> = [];
552
+
553
+ for (const snap of current) {
554
+ try {
555
+ await componentSpecHandler({
556
+ nodeId: snap.nodeId,
557
+ outputFormat: args.specFormat ?? "all",
558
+ });
559
+ await saveSnapshot(snapshotDir, snap);
560
+ results.push({ name: snap.name, success: true });
561
+ } catch (err) {
562
+ results.push({ name: snap.name, success: false, error: err instanceof Error ? err.message : String(err) });
563
+ }
564
+ }
565
+
566
+ return {
567
+ action: "regenerate",
568
+ total: results.length,
569
+ succeeded: results.filter((r) => r.success).length,
570
+ failed: results.filter((r) => !r.success).length,
571
+ results,
572
+ };
573
+ }
574
+
575
+ case "changelog": {
576
+ // Generate changelog from drift detection
577
+ const current = await scanComponents(args.nodeIds);
578
+ const allDrifts: DriftEntry[] = [];
579
+
580
+ for (const snap of current) {
581
+ const old = await loadSnapshot(snapshotDir, snap.nodeId);
582
+ if (!old) {
583
+ allDrifts.push({
584
+ nodeId: snap.nodeId,
585
+ componentName: snap.name,
586
+ driftType: "new-component",
587
+ field: "component",
588
+ before: "(none)",
589
+ after: snap.name,
590
+ severity: "major",
591
+ });
592
+ } else if (old.hash !== snap.hash) {
593
+ allDrifts.push(...detectDrift(old, snap));
594
+ }
595
+ }
596
+
597
+ const changelog = generateChangelog(allDrifts);
598
+ const markdown = renderChangelogMarkdown(changelog);
599
+
600
+ // Save updated snapshots
601
+ for (const snap of current) {
602
+ await saveSnapshot(snapshotDir, snap);
603
+ }
604
+
605
+ return {
606
+ action: "changelog",
607
+ entries: changelog,
608
+ markdown,
609
+ totalChanges: allDrifts.length,
610
+ };
611
+ }
612
+
613
+ case "freshness": {
614
+ // Report documentation freshness across all components
615
+ const current = await scanComponents(args.nodeIds);
616
+ const report: Array<{
617
+ name: string;
618
+ nodeId: string;
619
+ fresh: boolean;
620
+ lastUpdated: string | null;
621
+ driftCount: number;
622
+ }> = [];
623
+
624
+ for (const snap of current) {
625
+ const old = await loadSnapshot(snapshotDir, snap.nodeId);
626
+ if (!old) {
627
+ report.push({ name: snap.name, nodeId: snap.nodeId, fresh: false, lastUpdated: null, driftCount: -1 });
628
+ } else {
629
+ const drifts = old.hash === snap.hash ? [] : detectDrift(old, snap);
630
+ report.push({
631
+ name: snap.name,
632
+ nodeId: snap.nodeId,
633
+ fresh: drifts.length === 0,
634
+ lastUpdated: old.timestamp,
635
+ driftCount: drifts.length,
636
+ });
637
+ }
638
+ }
639
+
640
+ const freshCount = report.filter((r) => r.fresh).length;
641
+ const freshness = report.length > 0 ? Math.round((freshCount / report.length) * 100) : 100;
642
+
643
+ return {
644
+ action: "freshness",
645
+ totalComponents: report.length,
646
+ freshCount,
647
+ staleCount: report.length - freshCount,
648
+ freshnessScore: freshness,
649
+ components: report,
650
+ };
651
+ }
652
+
653
+ case "register-webhook": {
654
+ // Return webhook configuration for automated doc updates
655
+ return {
656
+ action: "register-webhook",
657
+ message: "Use figma_webhook_listener to register a webhook that triggers doc regeneration on component changes.",
658
+ suggestedConfig: {
659
+ events: ["FILE_UPDATE", "LIBRARY_PUBLISH"],
660
+ triggers: {
661
+ onComponentChange: "run-audit",
662
+ onLibraryPublish: "run-health-report",
663
+ },
664
+ automatedActions: [
665
+ "On FILE_UPDATE: run figma_watch_docs(action: 'check', autoRegenerate: true)",
666
+ "On LIBRARY_PUBLISH: run figma_watch_docs(action: 'changelog') then figma_ci_check(checks: ['all'])",
667
+ ],
668
+ fileKey: args.fileKey ?? "(provide your Figma file key)",
669
+ },
670
+ };
671
+ }
672
+
673
+ default:
674
+ return { error: `Unknown action: ${args.action}` };
675
+ }
676
+ }