@mmerterden/multi-agent-pipeline 11.1.0 → 11.3.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 (342) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +2 -2
  3. package/docs/FIGMA_PIPELINE.md +12 -25
  4. package/docs/architecture.md +3 -5
  5. package/docs/features.md +8 -8
  6. package/install/_common.mjs +9 -1
  7. package/install/_dev-only-files.mjs +0 -6
  8. package/install/claude.mjs +45 -18
  9. package/install/copilot.mjs +16 -14
  10. package/install/templates/copilot-instructions.md +3 -3
  11. package/package.json +1 -1
  12. package/pipeline/commands/{multi-agent.md → multi-agent/SKILL.md} +39 -39
  13. package/pipeline/commands/multi-agent/{analysis.md → analysis/SKILL.md} +18 -18
  14. package/pipeline/commands/multi-agent/{analysis-resolve.md → analysis-resolve/SKILL.md} +4 -4
  15. package/pipeline/commands/multi-agent/{autopilot.md → autopilot/SKILL.md} +4 -4
  16. package/pipeline/commands/multi-agent/{build-optimize.md → build-optimize/SKILL.md} +1 -1
  17. package/pipeline/commands/multi-agent/{channels.md → channels/SKILL.md} +12 -12
  18. package/pipeline/commands/multi-agent/{dev.md → dev/SKILL.md} +4 -4
  19. package/pipeline/commands/multi-agent/{dev-autopilot.md → dev-autopilot/SKILL.md} +4 -4
  20. package/pipeline/commands/multi-agent/{dev-local.md → dev-local/SKILL.md} +5 -5
  21. package/pipeline/commands/multi-agent/{dev-local-autopilot.md → dev-local-autopilot/SKILL.md} +4 -4
  22. package/pipeline/commands/multi-agent/{finish.md → finish/SKILL.md} +6 -6
  23. package/pipeline/commands/multi-agent/{generate.md → generate/SKILL.md} +3 -3
  24. package/pipeline/commands/multi-agent/{help.md → help/SKILL.md} +4 -4
  25. package/pipeline/commands/multi-agent/{local.md → local/SKILL.md} +5 -5
  26. package/pipeline/commands/multi-agent/{local-autopilot.md → local-autopilot/SKILL.md} +5 -5
  27. package/pipeline/commands/multi-agent/{manual-test.md → manual-test/SKILL.md} +1 -1
  28. package/pipeline/commands/multi-agent/refactor/SKILL.md +257 -0
  29. package/pipeline/commands/multi-agent/{resume.md → resume/SKILL.md} +1 -1
  30. package/pipeline/commands/multi-agent/{review.md → review/SKILL.md} +5 -5
  31. package/pipeline/commands/multi-agent/{setup.md → setup/SKILL.md} +1 -1
  32. package/pipeline/commands/multi-agent/{sync.md → sync/SKILL.md} +20 -58
  33. package/pipeline/{commands/multi-agent → multi-agent-refs}/_account-picker.md +2 -2
  34. package/pipeline/{commands/multi-agent → multi-agent-refs}/_dev-context.md +2 -2
  35. package/pipeline/{commands/multi-agent → multi-agent-refs}/_repo-picker.md +2 -2
  36. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/android-guide.md +1 -1
  37. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/jira.md +1 -1
  38. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/wiki.md +7 -7
  39. package/pipeline/multi-agent-refs/component-dispatch.md +92 -0
  40. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/cross-cli-contract.md +10 -77
  41. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/verify-by-test.md +1 -1
  42. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/generate-issue.md +2 -2
  43. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/issue-jira-triad.md +1 -1
  44. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/keychain.md +1 -1
  45. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/log-format.md +1 -1
  46. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/modes.md +2 -2
  47. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/operations.md +1 -1
  48. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-0-init.md +10 -10
  49. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-1-analysis.md +6 -6
  50. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-2-planning.md +3 -3
  51. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-3-dev.md +10 -10
  52. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-4-review.md +8 -8
  53. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-5-test.md +3 -3
  54. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-6-commit.md +4 -4
  55. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-7-report.md +6 -6
  56. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases.md +12 -12
  57. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/progress-contract.md +4 -4
  58. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/swiftui-guide.md +1 -1
  59. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/tracker-contract.md +3 -3
  60. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/wiki-capture.md +4 -4
  61. package/pipeline/preferences-template.json +17 -1
  62. package/pipeline/rules/figma-pipeline.md +2 -2
  63. package/pipeline/schemas/prefs.schema.json +0 -34
  64. package/pipeline/scripts/README.md +1 -3
  65. package/pipeline/scripts/build-stack-plugins.mjs +1 -1
  66. package/pipeline/scripts/fixtures/install-layout.tsv +6 -5
  67. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
  68. package/pipeline/scripts/phase-banner.sh +2 -2
  69. package/pipeline/scripts/review-scope.mjs +94 -0
  70. package/pipeline/scripts/scan-agent-config.sh +2 -2
  71. package/pipeline/scripts/smoke-agent-log-cost.sh +1 -1
  72. package/pipeline/scripts/smoke-agent-model-routing.sh +4 -4
  73. package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +2 -2
  74. package/pipeline/scripts/smoke-channels-approval-gate.sh +2 -2
  75. package/pipeline/scripts/smoke-channels-flow.sh +5 -5
  76. package/pipeline/scripts/smoke-clarify.sh +1 -1
  77. package/pipeline/scripts/smoke-commands-skills-parity.sh +3 -3
  78. package/pipeline/scripts/smoke-community-gates.sh +1 -1
  79. package/pipeline/scripts/smoke-compliance-skills.sh +2 -2
  80. package/pipeline/scripts/smoke-cost-summary.sh +1 -1
  81. package/pipeline/scripts/smoke-cross-cli-behavior.sh +17 -43
  82. package/pipeline/scripts/smoke-cross-phase-cohesion.sh +1 -1
  83. package/pipeline/scripts/smoke-dev-critic.sh +1 -1
  84. package/pipeline/scripts/smoke-diff-explain.sh +1 -1
  85. package/pipeline/scripts/smoke-diff-risk.sh +1 -1
  86. package/pipeline/scripts/smoke-evidence-gate.sh +1 -1
  87. package/pipeline/scripts/smoke-figma-dispatch.sh +46 -57
  88. package/pipeline/scripts/smoke-gate-hooks.sh +1 -1
  89. package/pipeline/scripts/smoke-generate-issue.sh +8 -8
  90. package/pipeline/scripts/smoke-handoff-contract.sh +3 -3
  91. package/pipeline/scripts/smoke-identity-isolation.sh +2 -2
  92. package/pipeline/scripts/smoke-intent-guard.sh +1 -1
  93. package/pipeline/scripts/smoke-issue-comment-template.sh +2 -2
  94. package/pipeline/scripts/smoke-issue-jira-triad.sh +4 -4
  95. package/pipeline/scripts/smoke-language-axis.sh +6 -6
  96. package/pipeline/scripts/smoke-learnings-ledger.sh +3 -3
  97. package/pipeline/scripts/smoke-mode-dispatch-drift.sh +16 -16
  98. package/pipeline/scripts/smoke-model-fallback.sh +3 -3
  99. package/pipeline/scripts/smoke-multi-repo-integration.sh +2 -2
  100. package/pipeline/scripts/smoke-multi-repo-worktree.sh +1 -1
  101. package/pipeline/scripts/smoke-no-token-prompt.sh +5 -5
  102. package/pipeline/scripts/smoke-phase-0-multi-repo.sh +1 -1
  103. package/pipeline/scripts/smoke-phase-6-multi.sh +1 -1
  104. package/pipeline/scripts/smoke-phase4-gates.sh +45 -0
  105. package/pipeline/scripts/smoke-plan-approval-gate.sh +5 -5
  106. package/pipeline/scripts/smoke-plan-todos.sh +3 -3
  107. package/pipeline/scripts/smoke-pr-review-actions.sh +3 -3
  108. package/pipeline/scripts/smoke-prefs-language.sh +1 -1
  109. package/pipeline/scripts/smoke-progress-contract.sh +2 -2
  110. package/pipeline/scripts/smoke-push-retry.sh +1 -1
  111. package/pipeline/scripts/smoke-repo-map.sh +2 -2
  112. package/pipeline/scripts/smoke-shadow-git.sh +1 -1
  113. package/pipeline/scripts/smoke-skill-authoring.sh +4 -9
  114. package/pipeline/scripts/smoke-tasklist-ordering.sh +10 -10
  115. package/pipeline/scripts/smoke-test-gap.sh +1 -1
  116. package/pipeline/scripts/smoke-token-budget.sh +1 -1
  117. package/pipeline/scripts/smoke-token-preflight.sh +2 -2
  118. package/pipeline/scripts/smoke-tracker-contract.sh +13 -13
  119. package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +5 -5
  120. package/pipeline/scripts/smoke-triage-memory.sh +2 -2
  121. package/pipeline/scripts/smoke-update-check.sh +1 -1
  122. package/pipeline/scripts/smoke-url-enrichment.sh +2 -2
  123. package/pipeline/scripts/smoke-validator-gates.sh +1 -1
  124. package/pipeline/scripts/smoke-verify-by-test.sh +3 -3
  125. package/pipeline/scripts/smoke-wiki-integration.sh +9 -33
  126. package/pipeline/scripts/smoke-work-summary.sh +1 -1
  127. package/pipeline/scripts/smoke-worktree-path-convention.sh +4 -4
  128. package/pipeline/scripts/test-integrity-gate.mjs +83 -0
  129. package/pipeline/scripts/uninstall.mjs +2 -2
  130. package/pipeline/skills/.skill-manifest.json +40 -160
  131. package/pipeline/skills/.skills-index.json +21 -372
  132. package/pipeline/skills/shared/README.md +1 -1
  133. package/pipeline/skills/shared/core/multi-agent/SKILL.md +1 -1
  134. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +2 -2
  135. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +3 -3
  136. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
  137. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +1 -1
  138. package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
  139. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +1 -1
  140. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +116 -51
  141. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +8 -30
  142. package/pipeline/skills/shared/external/backlog/BACKLOG.md +32 -0
  143. package/pipeline/skills/shared/external/backlog/SKILL.md +49 -0
  144. package/pipeline/skills/shared/external/compose-components/SKILL.md +14 -14
  145. package/pipeline/skills/shared/external/skill-creator/SKILL.md +48 -0
  146. package/pipeline/skills/shared/external/skill-creator/audit.md +59 -0
  147. package/pipeline/skills/shared/external/skill-creator/checklist.md +32 -0
  148. package/pipeline/skills/shared/external/skill-creator/examples.md +65 -0
  149. package/pipeline/skills/shared/external/skill-creator/label-check.md +43 -0
  150. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +83 -0
  151. package/pipeline/skills/shared/external/skill-creator/template.md +67 -0
  152. package/pipeline/skills/skills-index.md +4 -43
  153. package/pipeline/commands/multi-agent/refactor.md +0 -188
  154. package/pipeline/commands/multi-agent/refs/component-dispatch.md +0 -92
  155. package/pipeline/scripts/smoke-existing-discovery-gate.sh +0 -71
  156. package/pipeline/scripts/smoke-figma-android-parity.sh +0 -148
  157. package/pipeline/scripts/smoke-figma-credential-store.sh +0 -105
  158. package/pipeline/scripts/smoke-figma-cross-cli-inventory.sh +0 -177
  159. package/pipeline/scripts/smoke-figma-sync.sh +0 -149
  160. package/pipeline/scripts/smoke-sync-delegation.sh +0 -74
  161. package/pipeline/skills/figma-android/README.md +0 -38
  162. package/pipeline/skills/figma-android/figma-component-code-connect/SKILL.md +0 -62
  163. package/pipeline/skills/figma-android/figma-component-implement/SKILL.md +0 -158
  164. package/pipeline/skills/figma-android/figma-component-test/SKILL.md +0 -120
  165. package/pipeline/skills/figma-android/figma-component-wiki/SKILL.md +0 -35
  166. package/pipeline/skills/figma-android/figma-to-component/SKILL.md +0 -124
  167. package/pipeline/skills/figma-common/README.md +0 -64
  168. package/pipeline/skills/figma-common/figma-bottom-sheets/SKILL.md +0 -152
  169. package/pipeline/skills/figma-common/figma-cli-iterate/SKILL.md +0 -282
  170. package/pipeline/skills/figma-common/figma-cli-iterate-mend/SKILL.md +0 -503
  171. package/pipeline/skills/figma-common/figma-cli-lean-iterate/SKILL.md +0 -288
  172. package/pipeline/skills/figma-common/figma-cli-skip/SKILL.md +0 -362
  173. package/pipeline/skills/figma-common/figma-commit/COMMON_REBASE.md +0 -206
  174. package/pipeline/skills/figma-common/figma-commit/REVIEW.md +0 -337
  175. package/pipeline/skills/figma-common/figma-commit/SKILL.md +0 -216
  176. package/pipeline/skills/figma-common/figma-component-confluence-sync/SKILL.md +0 -223
  177. package/pipeline/skills/figma-common/figma-component-start/SKILL.md +0 -251
  178. package/pipeline/skills/figma-common/figma-component-status-update/SKILL.md +0 -78
  179. package/pipeline/skills/figma-common/figma-evolve-component/SKILL.md +0 -61
  180. package/pipeline/skills/figma-common/figma-fix/SKILL.md +0 -321
  181. package/pipeline/skills/figma-common/figma-form-integration/SKILL.md +0 -542
  182. package/pipeline/skills/figma-common/figma-issue/SKILL.md +0 -750
  183. package/pipeline/skills/figma-common/figma-iterate/SKILL.md +0 -208
  184. package/pipeline/skills/figma-common/figma-iteration-commit/SKILL.md +0 -1020
  185. package/pipeline/skills/figma-common/figma-mend/SKILL.md +0 -331
  186. package/pipeline/skills/figma-common/figma-navigation/SKILL.md +0 -156
  187. package/pipeline/skills/figma-common/figma-overlays/SKILL.md +0 -142
  188. package/pipeline/skills/figma-common/figma-price-integration/SKILL.md +0 -398
  189. package/pipeline/skills/figma-common/figma-remote-mcp-auth/SKILL.md +0 -104
  190. package/pipeline/skills/figma-common/figma-review/SKILL.md +0 -400
  191. package/pipeline/skills/figma-common/figma-setup/SKILL.md +0 -514
  192. package/pipeline/skills/figma-common/figma-setup/scripts/fetch-mcp-token.py +0 -592
  193. package/pipeline/skills/figma-common/figma-skip/SKILL.md +0 -129
  194. package/pipeline/skills/figma-common/figma-ui-patterns/SKILL.md +0 -105
  195. package/pipeline/skills/figma-common/figma-ui-patterns/patterns/animated-gradient-border.md +0 -116
  196. package/pipeline/skills/figma-common/figma-utility/SKILL.md +0 -274
  197. package/pipeline/skills/figma-common/figma-utility/scripts/figma-utility.py +0 -808
  198. package/pipeline/skills/figma-common/figma-validate/SKILL.md +0 -633
  199. package/pipeline/skills/figma-common/performance-iteration-commit-all/SKILL.md +0 -716
  200. package/pipeline/skills/figma-common/performance-review-next/SKILL.md +0 -238
  201. package/pipeline/skills/figma-common/performance-start/SKILL.md +0 -430
  202. package/pipeline/skills/figma-common/performance-swiftui/SKILL.md +0 -706
  203. package/pipeline/skills/figma-common/performance-tour/SKILL.md +0 -423
  204. package/pipeline/skills/figma-ios/REVIEW_CHECKLIST.md +0 -67
  205. package/pipeline/skills/figma-ios/figma-component-code-connect/SKILL.md +0 -178
  206. package/pipeline/skills/figma-ios/figma-component-implement/SKILL.md +0 -184
  207. package/pipeline/skills/figma-ios/figma-component-test/SKILL.md +0 -219
  208. package/pipeline/skills/figma-ios/figma-component-wiki/SKILL.md +0 -274
  209. package/pipeline/skills/figma-ios/figma-to-component/SKILL.md +0 -416
  210. package/pipeline/skills/figma-ios/figma-to-component/halt-return-protocol.md +0 -57
  211. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-0-init.md +0 -307
  212. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1-gathering.md +0 -119
  213. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1.5-existing-discovery.md +0 -174
  214. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2-orchestrator.md +0 -333
  215. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2a-testing-identifiers.md +0 -368
  216. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2b-localization.md +0 -393
  217. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2c-accessibility.md +0 -617
  218. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2d-analytics.md +0 -352
  219. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3-orchestrator.md +0 -337
  220. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3a-location.md +0 -206
  221. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3b-tokens.md +0 -235
  222. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3c-nested.md +0 -214
  223. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3d-patterns.md +0 -902
  224. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3e-assets.md +0 -156
  225. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3f-utilities.md +0 -175
  226. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3g-property-coverage.md +0 -176
  227. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3h-variant-config.md +0 -333
  228. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4-orchestrator.md +0 -412
  229. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4a-configuration.md +0 -336
  230. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4b-view.md +0 -705
  231. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4c-documentation.md +0 -332
  232. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4d-preview.md +0 -380
  233. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4e-modifiers.md +0 -262
  234. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5-orchestrator.md +0 -482
  235. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5a-viewinspector.md +0 -274
  236. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5b-snapshot.md +0 -636
  237. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5c-unit.md +0 -142
  238. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-6-code-connect.md +0 -547
  239. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7-wiki.md +0 -39
  240. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-confluence-generate.md +0 -659
  241. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-wiki-generate.md +0 -580
  242. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-8-cleanup.md +0 -51
  243. package/pipeline/skills/figma-ios/figma-to-component/reference/accessibility.md +0 -183
  244. package/pipeline/skills/figma-ios/figma-to-component/reference/analytics-events.md +0 -64
  245. package/pipeline/skills/figma-ios/figma-to-component/reference/code-connect.md +0 -531
  246. package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-api.md +0 -89
  247. package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-xhtml.md +0 -155
  248. package/pipeline/skills/figma-ios/figma-to-component/reference/figma-to-swiftui-effects.md +0 -196
  249. package/pipeline/skills/figma-ios/figma-to-component/reference/halt-return-protocol.md +0 -57
  250. package/pipeline/skills/figma-ios/figma-to-component/reference/localization-naming.md +0 -89
  251. package/pipeline/skills/figma-ios/figma-to-component/reference/macros.md +0 -227
  252. package/pipeline/skills/figma-ios/figma-to-component/reference/missing-tokens.md +0 -157
  253. package/pipeline/skills/figma-ios/figma-to-component/reference/orchestrator-discipline.md +0 -90
  254. package/pipeline/skills/figma-ios/figma-to-component/reference/registry.md +0 -116
  255. package/pipeline/skills/figma-ios/figma-to-component/reference/remote-mcp-script.md +0 -153
  256. package/pipeline/skills/figma-ios/figma-to-component/reference/rest-api-script.md +0 -130
  257. package/pipeline/skills/figma-ios/figma-to-component/reference/scripts-inventory.md +0 -218
  258. package/pipeline/skills/figma-ios/figma-to-component/reference/snapshot-testing.md +0 -188
  259. package/pipeline/skills/figma-ios/figma-to-component/reference/subcomponent-graph.md +0 -93
  260. package/pipeline/skills/figma-ios/figma-to-component/reference/testing-identifiers-naming.md +0 -98
  261. package/pipeline/skills/figma-ios/figma-to-component/reference/tools.md +0 -261
  262. package/pipeline/skills/figma-ios/figma-to-component/reference/viewinspector.md +0 -147
  263. package/pipeline/skills/figma-ios/figma-to-component/reference/wiki-to-confluence-mapping.md +0 -182
  264. package/pipeline/skills/figma-ios/figma-to-component/scripts/apply-author-login-map.py +0 -185
  265. package/pipeline/skills/figma-ios/figma-to-component/scripts/backfill-status.py +0 -609
  266. package/pipeline/skills/figma-ios/figma-to-component/scripts/build-author-registry.py +0 -332
  267. package/pipeline/skills/figma-ios/figma-to-component/scripts/bulk-sync-issues.py +0 -261
  268. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-data-gather.py +0 -184
  269. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-publish.sh +0 -188
  270. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status-upload.py +0 -768
  271. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status.py +0 -191
  272. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-data-gather.py +0 -420
  273. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-page-ids.example.json +0 -9
  274. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-publish.py +0 -336
  275. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-subcomponent-graph.py +0 -391
  276. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-update.py +0 -292
  277. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/__init__.py +0 -1
  278. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/issue_sync_propagate.py +0 -93
  279. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/registry_writer.py +0 -299
  280. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_backfill_status.py +0 -343
  281. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update.py +0 -206
  282. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update_http.py +0 -149
  283. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_phase_clis.py +0 -281
  284. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_registry_writer.py +0 -332
  285. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_issue.py +0 -176
  286. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_review.py +0 -98
  287. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue.py +0 -298
  288. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue_gh.py +0 -195
  289. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase1-gather.py +0 -1298
  290. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase2-finalize.py +0 -228
  291. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase3-scripts.py +0 -1089
  292. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase4-finalize.py +0 -141
  293. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase5-finalize.py +0 -106
  294. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase6-finalize.py +0 -162
  295. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase7-finalize.py +0 -105
  296. package/pipeline/skills/figma-ios/figma-to-component/scripts/register-icons-codeconnect.py +0 -179
  297. package/pipeline/skills/figma-ios/figma-to-component/scripts/remote-mcp-fetch.py +0 -260
  298. package/pipeline/skills/figma-ios/figma-to-component/scripts/resolve-author-logins.py +0 -260
  299. package/pipeline/skills/figma-ios/figma-to-component/scripts/run-uicomponents-tests.sh +0 -86
  300. package/pipeline/skills/figma-ios/figma-to-component/scripts/sidebar-generator.py +0 -321
  301. package/pipeline/skills/figma-ios/figma-to-component/scripts/update-issue-from-registry.py +0 -1470
  302. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase4.sh +0 -176
  303. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase6.sh +0 -147
  304. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase7a.py +0 -629
  305. /package/pipeline/commands/multi-agent/{delete.md → delete/SKILL.md} +0 -0
  306. /package/pipeline/commands/multi-agent/{diff-explain.md → diff-explain/SKILL.md} +0 -0
  307. /package/pipeline/commands/multi-agent/{garbage-collect.md → garbage-collect/SKILL.md} +0 -0
  308. /package/pipeline/commands/multi-agent/{issue.md → issue/SKILL.md} +0 -0
  309. /package/pipeline/commands/multi-agent/{jira.md → jira/SKILL.md} +0 -0
  310. /package/pipeline/commands/multi-agent/{kill.md → kill/SKILL.md} +0 -0
  311. /package/pipeline/commands/multi-agent/{language.md → language/SKILL.md} +0 -0
  312. /package/pipeline/commands/multi-agent/{log.md → log/SKILL.md} +0 -0
  313. /package/pipeline/commands/multi-agent/{prune-logs.md → prune-logs/SKILL.md} +0 -0
  314. /package/pipeline/commands/multi-agent/{purge.md → purge/SKILL.md} +0 -0
  315. /package/pipeline/commands/multi-agent/{scan.md → scan/SKILL.md} +0 -0
  316. /package/pipeline/commands/multi-agent/{search.md → search/SKILL.md} +0 -0
  317. /package/pipeline/commands/multi-agent/{stack.md → stack/SKILL.md} +0 -0
  318. /package/pipeline/commands/multi-agent/{status.md → status/SKILL.md} +0 -0
  319. /package/pipeline/commands/multi-agent/{test.md → test/SKILL.md} +0 -0
  320. /package/pipeline/commands/multi-agent/{update.md → update/SKILL.md} +0 -0
  321. /package/pipeline/{commands/multi-agent → multi-agent-refs}/_input-parser.md +0 -0
  322. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/analysis-template.md +0 -0
  323. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/audit-guide.md +0 -0
  324. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/backend-guide.md +0 -0
  325. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/confluence.md +0 -0
  326. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/issue-comment.md +0 -0
  327. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr-review-actions.md +0 -0
  328. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr.md +0 -0
  329. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/conventions-defaults.md +0 -0
  330. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/autopilot-circuit-breaker.md +0 -0
  331. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/dev-critic.md +0 -0
  332. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/external-context-injection.md +0 -0
  333. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/model-fallback.md +0 -0
  334. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/plan-todos.md +0 -0
  335. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/prior-fix-detection.md +0 -0
  336. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/repo-map.md +0 -0
  337. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/shadow-git.md +0 -0
  338. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/frontend-guide.md +0 -0
  339. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/knowledge.md +0 -0
  340. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/multi-repo-integration-build.md +0 -0
  341. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/picker-contract.md +0 -0
  342. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/rules.md +0 -0
@@ -1,636 +0,0 @@
1
- # PHASE 5B - Snapshot Tests
2
-
3
- Snapshot visual regression tests for ALL Figma variants in light and dark mode.
4
-
5
- PARENT: `phase-5-orchestrator.md`
6
- required - always execute this sub-phase.
7
- PARALLEL WITH: Phase 5A (both read from pass5/_test_index.md independently)
8
-
9
- **FRAMEWORK**: XCTest with swift-snapshot-testing (via ExternalSnapshotTesting)
10
-
11
- ---
12
-
13
- ## PRE-CHECK: Load Test Index
14
-
15
- ```
16
- Read: {artifactPath}/pass5/_test_index.md
17
- ```
18
-
19
- EXTRACT:
20
- - `componentName`
21
- - `sourceModule`
22
- - `componentPath`
23
- - Artifact paths for: component_properties.json, 04b_component_architecture.md, 04_patterns.md
24
-
25
- Then read the actual artifacts to extract:
26
- - Enum properties (variant axes to snapshot)
27
- - Optional properties (boolean states to snapshot)
28
- - Component dimensions (from pass3/04_patterns.md)
29
-
30
- If test index missing → HALT, run orchestrator first.
31
-
32
- ---
33
-
34
- ## GATE 1: DETERMINE_VARIANT_MATRIX
35
-
36
- ### 1.1 Extract Snapshot Axes
37
-
38
- From `pass3/04b_component_architecture.md`, identify all properties that produce visual variations:
39
-
40
- | Property Type | Snapshot Treatment |
41
- |---------------|-------------------|
42
- | Enum (CaseIterable) | Loop through `.allCases` |
43
- | Optional Image? | Test with nil + with value |
44
- | Optional String? | Test with nil + with value |
45
- | Bool toggle | Test true + false |
46
-
47
- ### 1.2 Calculate Matrix
48
-
49
- List all variant axes and their values. Example:
50
-
51
- | Axis | Values | Count |
52
- |------|--------|-------|
53
- | state | success, warning, error, standard, secondary | 5 |
54
- | leftIcon | nil, Image | 2 |
55
- | text | "Lorem", nil | 2 |
56
- | Theme | light, dark | 2 |
57
-
58
- **Snapshot strategy:**
59
- - Snapshot each enum case with default values for other properties → `{enum_count}` snapshots
60
- - Snapshot each optional toggle (with/without) → `{toggle_count}` snapshots
61
- - All of the above × 2 (light + dark) → total
62
-
63
- **DO NOT snapshot full cartesian product** unless total < 20. For large matrices, snapshot:
64
- 1. Each enum case independently (other props at default)
65
- 2. Each optional toggle independently (enum at first case)
66
- 3. Both themes for all above
67
-
68
- ### 1.3 Extract Dimensions
69
-
70
- From `pass3/04_patterns.md`, get component width and height for snapshot frame.
71
- If not available, use defaults: width=375, height based on component type.
72
-
73
- ---
74
-
75
- ## GATE 2: DETERMINE_TEST_LOCATION
76
-
77
- ```
78
- Test Target: {sourceModule}Tests
79
- Test Dir: Tests/{sourceModule}Tests/Snapshot/{componentPath}/
80
- Test File: {componentName}SnapshotTests.swift
81
- ```
82
-
83
- ---
84
-
85
- ## GATE 3: CREATE_SNAPSHOT_TEST_FILE
86
-
87
- ### 3.0 Contrasting Background
88
-
89
- **ALWAYS** wrap the SUT in `Color.Background.backgroundGrey`. This is the app's standard page background, so snapshots show how the component looks in-app and make edges visible.
90
-
91
- ```swift
92
- private func makeSUT(...) -> some View {
93
- ComponentName(...)
94
- .padding(8)
95
- .background(Color.Background.backgroundGrey)
96
- }
97
- ```
98
-
99
- Without this, white components are invisible against the default white snapshot canvas.
100
-
101
- ### 3.0.1 Remote Image Initialization (required if the component uses `RemoteImage` / Kingfisher)
102
-
103
- **CRITICAL - this gate is easy to miss and produces silent false positives.**
104
-
105
- If the component (or any nested component it composes) renders images via `CoreUI.RemoteImage` / Kingfisher / any async image loader, the snapshot test MUST include image-initialization scaffolding. Without it, the snapshot captures the KFImage **placeholder state** - the first and every subsequent run compare placeholder to placeholder, so the tests "pass" while the reference PNGs contain no real image pixels at all.
106
-
107
- **How to detect the need**: if `pass3/04b_component_architecture.md` / `pass3/04_patterns.md` / `pass3/06_assets.md` mentions `RemoteImage`, `Kingfisher`, `KFImage`, image URL, remote image, or the component consumes any protocol/config with an `imageURL: URL` field, you MUST apply this gate. Also check if any **nested** component uses remote images - the parent inherits the requirement transitively.
108
-
109
- **NEVER use `usleep` on the main thread in either the prefetch or the image wait.** Kingfisher dispatches its `retrieveImage` completion handlers and KFImage's view-delivery updates back to the **main queue**. `usleep` blocks the main runloop, so those callbacks never fire, the cache never warms, and the snapshot captures a placeholder. Use `RunLoop.main.run(until:)` to spin the runloop instead - that allows queued main-actor work to drain while you wait. See the sibling `Homepage3rdPartyCardSnapshotTests.swift` for the canonical 20 ms pattern, and `HomepageAdditionalServices3rdPartyGroupSnapshotTests.swift` for the composite-view 4 s pattern (same rule, longer deadline).
110
-
111
- **Required scaffolding** (both references together show the full pattern):
112
-
113
- 1. **Module imports** - `@testable import CoreUI` + `import Kingfisher` in addition to the usual `SnapshotTesting` / `SwiftUI` / `XCTest`.
114
- 2. **Deterministic seeded URLs** - file-scope `let`s like `URL(string: "https://picsum.photos/seed/{slug}/{W}/{H}")!`. Seeds return the same image bytes for identical URLs → stable snapshots. Do NOT use unseeded picsum, placehold.it, or any URL that returns different bytes per request.
115
- 3. **`@MainActor private func prefetchVariantImages(timeout:)`** - kicks `KingfisherManager.shared.retrieveImage(with:)` for every URL and **spins `RunLoop.main.run(until:)`** until every completion callback has fired (not `usleep`, not `isCached` polling). Use a `@MainActor final class` counter (`MainActor.assumeIsolated { counter.remaining -= 1 }` inside the completion) to satisfy Swift 6 concurrency rules - a captured `var Int` inside the closure will not compile. 20 s timeout is safe; the runloop exits early once the counter hits zero.
116
- 4. **`override class func setUp()`** - after `TestDependencies.registerAll()`, set `RemoteImageConfiguration.shared.fadeDuration = 0`. This disables KFImage's crossfade animation so cached pixels appear on the first layout pass instead of fading in mid-snapshot.
117
- 5. **`override func setUp()`** - call `prefetchVariantImages()` before every test, so each test sees warm cache.
118
- 6. **`waitForImages()` helper** - **`RunLoop.main.run(until: Date().addingTimeInterval({seconds}))`**, NOT `usleep`. Call it in every assert helper AFTER `vc.view.layoutIfNeeded()` and BEFORE `SnapshotTesting.assertSnapshot(...)`. Duration depends on how many `RemoteImage` instances the view composes **simultaneously**:
119
-
120
- | Simultaneous async-image views | `waitForImages` duration | Canonical reference |
121
- |---|---|---|
122
- | 1 (single card, single banner, etc.) | 20 ms (`usleep(20_000)` is OK for single-view, but `RunLoop.main.run` is still safer) | `Homepage3rdPartyCardSnapshotTests.swift` |
123
- | 2-4 (group / row / carousel composing multiple cards) | 2-4 s via `RunLoop.main.run(until:)` | `HomepageAdditionalServices3rdPartyGroupSnapshotTests.swift` |
124
- | 5+ (lists, grids, large composites) | 4-6 s via `RunLoop.main.run(until:)`; consider also capping list length to 3-5 in `makeSUT` |
125
-
126
- 7. **Frame width sanity** - if the SUT renders a section title or horizontal carousel, make sure the snapshot frame width is wide enough to include the title and at least one full card. Clipped titles are a visible smoke signal that the frame is too narrow.
127
-
128
- **Skeleton** (adapt to single-view OR composite-view shape per the table above):
129
-
130
- ```swift
131
- @testable import CoreUI
132
- import Kingfisher
133
- import SnapshotTesting
134
- import SwiftUI
135
- import XCTest
136
- @testable import {sourceModule}
137
-
138
- private let imageURL1 = URL(string: "https://picsum.photos/seed/{slug1}/{W}/{H}")!
139
- private let imageURL2 = URL(string: "https://picsum.photos/seed/{slug2}/{W}/{H}")!
140
- private let imageURL3 = URL(string: "https://picsum.photos/seed/{slug3}/{W}/{H}")!
141
-
142
- @MainActor
143
- private final class PrefetchCounter {
144
- var remaining: Int
145
- init(_ n: Int) { self.remaining = n }
146
- }
147
-
148
- /// Warms Kingfisher's memory cache for all variant URLs and spins the main
149
- /// runloop until every completion callback fires (or the deadline expires).
150
- /// Spinning the runloop is required - usleep on main would starve the
151
- /// Kingfisher callbacks and the cache would never warm.
152
- @MainActor
153
- private func prefetchVariantImages(timeout: TimeInterval = 20.0) {
154
- let urls = [imageURL1, imageURL2, imageURL3]
155
- let counter = PrefetchCounter(urls.count)
156
- for url in urls {
157
- KingfisherManager.shared.retrieveImage(with: url) { _ in
158
- MainActor.assumeIsolated { counter.remaining -= 1 }
159
- }
160
- }
161
- let deadline = Date().addingTimeInterval(timeout)
162
- while counter.remaining > 0 && Date() < deadline {
163
- RunLoop.main.run(until: Date().addingTimeInterval(0.05))
164
- }
165
- }
166
-
167
- @MainActor
168
- final class {ComponentName}SnapshotTests: XCTestCase {
169
-
170
- override class func setUp() {
171
- super.setUp()
172
- TestDependencies.registerAll()
173
- RemoteImageConfiguration.shared.fadeDuration = 0 // required
174
- }
175
-
176
- override func setUp() {
177
- super.setUp()
178
- prefetchVariantImages() // required
179
- }
180
-
181
- /// required - uses RunLoop.main.run(until:), never usleep.
182
- /// Duration scales with # of simultaneous RemoteImage views (see table
183
- /// in phase-5b section 3.0.1). 20 ms is enough for a single-card SUT;
184
- /// 2-4 s is required for composite views that render multiple cards
185
- /// at once.
186
- private func waitForImages() {
187
- RunLoop.main.run(until: Date().addingTimeInterval(/* single: 0.02 | composite: 4.0 */))
188
- }
189
-
190
- private func assertSnapshot(_ view: some View, named: String, width: CGFloat, height: CGFloat, ...) {
191
- let vc = UIHostingController(rootView: view)
192
- vc.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
193
- vc.view.layoutIfNeeded()
194
- waitForImages() // required
195
- SnapshotTesting.assertSnapshot(of: vc, as: .image(...), ...)
196
- }
197
- }
198
- ```
199
-
200
- **Verification checklist before committing reference PNGs:**
201
-
202
- 1. Delete any pre-existing PNGs under `__Snapshots__/{ComponentName}SnapshotTests/`.
203
- 2. Run the suite once. Expect failures on first run (`.missing` mode auto-records).
204
- 3. Open at least one recorded PNG visually and confirm every card/image slot shows **real photographic content**, not a Kingfisher placeholder (light gradient + activity spinner) and not an all-blank background.
205
- 4. Check file sizes: real photographic snapshots are typically 100 KB - 2 MB. A composite PNG at <50 KB is a strong signal of placeholder capture.
206
- 5. Run the suite a second time - it MUST pass on the regression run. If not, increase `waitForImages` duration.
207
- 6. Only commit PNGs (if tracked) and the test file together, never separately.
208
-
209
- **Root-cause note (why this gate exists):** the template in section 3.1 below references `ExploreCityDetailAboutCitySnapshotTests.swift`, which does NOT use remote images. A subagent that copies only the section 3.1 template will silently omit the scaffolding above and produce tests that lock in placeholder reference PNGs. This has happened in real runs:
210
-
211
- - `HomepageAdditionalServices3rdPartyGroupSnapshotTests` ({jira.projectKey}-132403): first fix copied the sibling's `usleep(20_000)` wait verbatim - the composite renders **three** `Homepage3rdPartyCard` instances simultaneously, and 20 ms wasn't enough for all three to drain. Second fix replaced both the prefetch poll AND the image wait with `RunLoop.main.run(until:)` and extended the wait to 4 s. Reference PNGs went from 65 KB (placeholder) to 750 KB - 1.76 MB (real photos).
212
-
213
- **If the component renders a single `RemoteImage`, the canonical reference is `Homepage3rdPartyCardSnapshotTests.swift`. If the component composes multiple `RemoteImage` instances simultaneously, the canonical reference is `HomepageAdditionalServices3rdPartyGroupSnapshotTests.swift`.** Neither the Explore reference nor the generic section 3.1 template is appropriate for remote-image components.
214
-
215
- ### 3.1 Template
216
-
217
- Pick the canonical reference based on what the component renders:
218
-
219
- | Component shape | Canonical reference | section 3.0.1 scaffolding |
220
- |---|---|---|
221
- | Pure SwiftUI, no remote images | `ExploreCityDetailAboutCitySnapshotTests.swift` | Not required |
222
- | Single `RemoteImage` / Kingfisher instance | `Homepage3rdPartyCardSnapshotTests.swift` | **Required** (single-view variant) |
223
- | Composite view with 2+ `RemoteImage` instances rendered simultaneously | `HomepageAdditionalServices3rdPartyGroupSnapshotTests.swift` | **Required** (composite variant, 2-4 s `RunLoop.main.run` wait) |
224
-
225
- Then follow the established project pattern from the chosen reference:
226
-
227
- ```swift
228
- //
229
- // {componentName}SnapshotTests.swift
230
- // {sourceModule}Tests
231
- //
232
- // Created by {AUTHOR} on {DD.MM.YYYY}.
233
- //
234
-
235
- import SnapshotTesting
236
- import SwiftUI
237
- import XCTest
238
- @testable import {sourceModule}
239
-
240
- @MainActor
241
- final class {componentName}SnapshotTests: XCTestCase {
242
-
243
- override class func setUp() {
244
- super.setUp()
245
- TestDependencies.registerAll()
246
- }
247
-
248
- override func invokeTest() {
249
- withSnapshotTesting(record: .missing) {
250
- super.invokeTest()
251
- }
252
- }
253
-
254
- // MARK: - Light Mode Snapshots
255
-
256
- // {generated variant tests}
257
-
258
- // MARK: - Dark Mode Snapshots
259
-
260
- // {generated dark mode tests}
261
-
262
- // MARK: - Snapshot Helpers
263
-
264
- private func assertSnapshot(
265
- _ view: some View,
266
- named name: String,
267
- width: CGFloat = {componentWidth},
268
- height: CGFloat = {componentHeight},
269
- filePath: StaticString = #filePath,
270
- testName: String = #function,
271
- line: UInt = #line
272
- ) {
273
- let vc = UIHostingController(rootView: view)
274
- vc.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
275
- vc.view.layoutIfNeeded()
276
-
277
- SnapshotTesting.assertSnapshot(
278
- of: vc,
279
- as: .image(precision: 0.99, perceptualPrecision: 0.98),
280
- named: name,
281
- file: filePath,
282
- testName: testName,
283
- line: line
284
- )
285
- }
286
-
287
- private func assertSnapshotDarkMode(
288
- _ view: some View,
289
- named name: String,
290
- width: CGFloat = {componentWidth},
291
- height: CGFloat = {componentHeight},
292
- filePath: StaticString = #filePath,
293
- testName: String = #function,
294
- line: UInt = #line
295
- ) {
296
- let vc = UIHostingController(rootView: view)
297
- vc.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
298
- vc.overrideUserInterfaceStyle = .dark
299
- vc.view.layoutIfNeeded()
300
-
301
- SnapshotTesting.assertSnapshot(
302
- of: vc,
303
- as: .image(precision: 0.99, perceptualPrecision: 0.98),
304
- named: name,
305
- file: filePath,
306
- testName: testName,
307
- line: line
308
- )
309
- }
310
-
311
- // MARK: - Helpers
312
-
313
- private func makeSUT(/* variant params */) -> {componentName} {
314
- {componentName} { config in
315
- config
316
- .{property1}({value1})
317
- .{property2}({value2})
318
- }
319
- }
320
- }
321
- ```
322
-
323
- ---
324
-
325
- ## GATE 4: GENERATE_ENUM_VARIANT_TESTS
326
-
327
- For each CaseIterable enum property, generate one test per case:
328
-
329
- ### 4.1 Individual Case Tests (Light Mode)
330
-
331
- ```swift
332
- // MARK: - {EnumName} Variants (Light)
333
-
334
- func test_snapshot_light_{caseName}() {
335
- let sut = {componentName} { config in
336
- config
337
- .text("{sampleText}")
338
- .{enumProperty}(.{caseName})
339
- }
340
- assertSnapshot(sut, named: "light_{caseName}")
341
- }
342
- ```
343
-
344
- ### 4.2 Individual Case Tests (Dark Mode)
345
-
346
- ```swift
347
- // MARK: - {EnumName} Variants (Dark)
348
-
349
- func test_snapshot_dark_{caseName}() {
350
- let sut = {componentName} { config in
351
- config
352
- .text("{sampleText}")
353
- .{enumProperty}(.{caseName})
354
- }
355
- assertSnapshotDarkMode(sut, named: "dark_{caseName}")
356
- }
357
- ```
358
-
359
- ---
360
-
361
- ## GATE 5: GENERATE_OPTIONAL_VARIANT_TESTS
362
-
363
- For optional properties (Image?, String?) that change visual output:
364
-
365
- ```swift
366
- // MARK: - Optional Variants
367
-
368
- func test_snapshot_light_withIcon() {
369
- let sut = {componentName} { config in
370
- config
371
- .text("{sampleText}")
372
- .state(.{defaultState})
373
- .leftIcon(Image(systemName: "{iconName}"))
374
- }
375
- assertSnapshot(sut, named: "light_withIcon")
376
- }
377
-
378
- func test_snapshot_light_iconOnly() {
379
- let sut = {componentName} { config in
380
- config
381
- .state(.{defaultState})
382
- .leftIcon(Image(systemName: "{iconName}"))
383
- // text omitted = nil = icon-only mode
384
- }
385
- assertSnapshot(sut, named: "light_iconOnly")
386
- }
387
-
388
- func test_snapshot_dark_withIcon() {
389
- // Same as above with assertSnapshotDarkMode
390
- }
391
- ```
392
-
393
- ---
394
-
395
- ## GATE 5B: GENERATE_RTL_VARIANT_TESTS
396
-
397
- RTL (Right-to-Left) tests verify layout mirroring with Arabic localization.
398
-
399
- **CRITICAL:** RTL tests MUST use `TestDependencies.setLanguage("ar")` to override the app language so localized labels render in Arabic. Reset after each test with `TestDependencies.resetLanguage()`.
400
-
401
- ### 5B.1 RTL State Tests (Light + Dark)
402
-
403
- Test a representative subset of enum states (3 is sufficient: first, middle, last or success/warning/error):
404
-
405
- ```swift
406
- // MARK: - RTL Variants (Light)
407
-
408
- func test_snapshot_rtl_light_{caseName}() {
409
- TestDependencies.setLanguage("ar")
410
- let sut = makeSUT({enumProperty}: .{caseName})
411
- assertSnapshotRTL(sut, named: "rtl_light_{caseName}")
412
- TestDependencies.resetLanguage()
413
- }
414
-
415
- // MARK: - RTL Variants (Dark)
416
-
417
- func test_snapshot_rtl_dark_{caseName}() {
418
- TestDependencies.setLanguage("ar")
419
- let sut = makeSUT({enumProperty}: .{caseName})
420
- assertSnapshotRTLDarkMode(sut, named: "rtl_dark_{caseName}")
421
- TestDependencies.resetLanguage()
422
- }
423
- ```
424
-
425
- ### 5B.2 RTL Optional Variants
426
-
427
- Test icon + text and icon-only in RTL to verify icon position mirroring:
428
-
429
- ```swift
430
- func test_snapshot_rtl_light_withIcon() {
431
- let sut = {componentName} { config in
432
- config
433
- .text("{arabicText}")
434
- .state(.{defaultState})
435
- .leftIcon(Image(systemName: "{iconName}"))
436
- }
437
- assertSnapshotRTL(sut, named: "rtl_light_withIcon")
438
- }
439
-
440
- func test_snapshot_rtl_light_iconOnly() {
441
- let sut = {componentName} { config in
442
- config
443
- .state(.{defaultState})
444
- .leftIcon(Image(systemName: "{iconName}"))
445
- }
446
- assertSnapshotRTL(sut, named: "rtl_light_iconOnly")
447
- }
448
- // + dark variants with assertSnapshotRTLDarkMode
449
- ```
450
-
451
- ### 5B.3 RTL Snapshot Helpers
452
-
453
- Add these helpers alongside the existing assertSnapshot/assertSnapshotDarkMode:
454
-
455
- ```swift
456
- private func assertSnapshotRTL(
457
- _ view: some View,
458
- named name: String,
459
- width: CGFloat = {componentWidth},
460
- height: CGFloat = {componentHeight},
461
- filePath: StaticString = #filePath,
462
- testName: String = #function,
463
- line: UInt = #line
464
- ) {
465
- let rtlView = view.environment(\.layoutDirection, .rightToLeft)
466
- let vc = UIHostingController(rootView: rtlView)
467
- vc.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
468
- vc.view.semanticContentAttribute = .forceRightToLeft
469
- vc.view.layoutIfNeeded()
470
-
471
- SnapshotTesting.assertSnapshot(
472
- of: vc,
473
- as: .image(precision: 0.99, perceptualPrecision: 0.98),
474
- named: name,
475
- file: filePath,
476
- testName: testName,
477
- line: line
478
- )
479
- }
480
-
481
- private func assertSnapshotRTLDarkMode(
482
- _ view: some View,
483
- named name: String,
484
- width: CGFloat = {componentWidth},
485
- height: CGFloat = {componentHeight},
486
- filePath: StaticString = #filePath,
487
- testName: String = #function,
488
- line: UInt = #line
489
- ) {
490
- let rtlView = view.environment(\.layoutDirection, .rightToLeft)
491
- let vc = UIHostingController(rootView: rtlView)
492
- vc.view.frame = CGRect(x: 0, y: 0, width: width, height: height)
493
- vc.view.semanticContentAttribute = .forceRightToLeft
494
- vc.overrideUserInterfaceStyle = .dark
495
- vc.view.layoutIfNeeded()
496
-
497
- SnapshotTesting.assertSnapshot(
498
- of: vc,
499
- as: .image(precision: 0.99, perceptualPrecision: 0.98),
500
- named: name,
501
- file: filePath,
502
- testName: testName,
503
- line: line
504
- )
505
- }
506
- ```
507
-
508
- ### 5B.4 Locale-Specific Variants (TR, EN)
509
-
510
- For components with localized static text, snapshot in Turkish and English to verify translations render correctly. Default (no setLanguage) uses the system language which may not match either.
511
-
512
- ```swift
513
- // MARK: - Turkish Variants (Light)
514
-
515
- func test_snapshot_tr_light_{caseName}() {
516
- TestDependencies.setLanguage("tr")
517
- let sut = makeSUT({enumProperty}: .{caseName})
518
- assertSnapshot(sut, named: "tr_light_{caseName}")
519
- TestDependencies.resetLanguage()
520
- }
521
-
522
- // MARK: - Turkish Variants (Dark)
523
-
524
- func test_snapshot_tr_dark_{caseName}() {
525
- TestDependencies.setLanguage("tr")
526
- let sut = makeSUT({enumProperty}: .{caseName})
527
- assertSnapshotDarkMode(sut, named: "tr_dark_{caseName}")
528
- TestDependencies.resetLanguage()
529
- }
530
-
531
- // MARK: - English Variants (Light)
532
-
533
- func test_snapshot_en_light_{caseName}() {
534
- TestDependencies.setLanguage("en")
535
- let sut = makeSUT({enumProperty}: .{caseName})
536
- assertSnapshot(sut, named: "en_light_{caseName}")
537
- TestDependencies.resetLanguage()
538
- }
539
-
540
- // MARK: - English Variants (Dark)
541
-
542
- func test_snapshot_en_dark_{caseName}() {
543
- TestDependencies.setLanguage("en")
544
- let sut = makeSUT({enumProperty}: .{caseName})
545
- assertSnapshotDarkMode(sut, named: "en_dark_{caseName}")
546
- TestDependencies.resetLanguage()
547
- }
548
- ```
549
-
550
- **When to include locale variants:** Always include TR + EN + AR (RTL) for components with static localized text. For components with only dynamic text (passed as parameters), locale variants are optional since the text comes from the caller.
551
-
552
- ### 5B.5 Arabic Sample Text
553
-
554
- | English | Arabic |
555
- |---------|--------|
556
- | Success | نجاح |
557
- | Warning | تحذير |
558
- | Error | خطأ |
559
- | Standard | قياسي |
560
- | Secondary | ثانوي |
561
- | Lorem | نص |
562
-
563
- ---
564
-
565
- ## GATE 6: RUN_AND_RECORD
566
-
567
- ### 6.1 First Run - Record Reference Snapshots
568
-
569
- **IMPORTANT:** Use `xcodebuild`, NOT `swift test`. The project uses Xcode-specific features (`ColorResource`, `ImageResource`, asset catalogs) that are unavailable in SPM's `swift build`/`swift test`.
570
-
571
- ```bash
572
- cd {repos.components.path} && \
573
- xcodebuild test \
574
- -scheme UIComponents-Package \
575
- -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
576
- -only-testing:{sourceModule}Tests/{componentName}SnapshotTests
577
- ```
578
-
579
- Snapshots auto-recorded to:
580
- ```
581
- Tests/{sourceModule}Tests/__Snapshots__/{componentName}SnapshotTests/
582
- ├── test_snapshot_light_{case1}.light_{case1}.png
583
- ├── test_snapshot_dark_{case1}.dark_{case1}.png
584
- ├── ...
585
- ```
586
-
587
- ### 6.2 Verify Snapshot Count
588
-
589
- | Expected | Actual | Status |
590
- |----------|--------|--------|
591
- | {EXPECTED_COUNT} total | {ACTUAL_COUNT} recorded | pass/fail |
592
-
593
- ### 6.3 Second Run - Verify Regression
594
-
595
- ```bash
596
- cd {repos.components.path} && \
597
- xcodebuild test \
598
- -scheme UIComponents-Package \
599
- -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
600
- -only-testing:{sourceModule}Tests/{componentName}SnapshotTests
601
- ```
602
-
603
- All tests must pass (snapshots match).
604
-
605
- | Result | Action |
606
- |--------|--------|
607
- | All pass | Proceed to OUTPUT |
608
- | Snapshot differs | Review diff images, fix if unintentional |
609
- | Missing snapshot | Run with `record: .missing` |
610
-
611
- FAIL →
612
- ```
613
- STATUS: HALT
614
- PHASE: phase-5b
615
- GATE: RUN_AND_RECORD
616
- REASON: Snapshot tests failed.
617
- FAILED_SNAPSHOTS: {list}
618
- OPTIONS:
619
- 1) Fix visual regression in component
620
- 2) Update snapshots: withSnapshotTesting(record: .all)
621
- 3) Review component against Figma design
622
- ```
623
-
624
- ---
625
-
626
- ## OUTPUT
627
-
628
- ```
629
- STATUS: COMPLETE
630
- PHASE: phase-5b
631
- GATES_PASSED: [PRE_CHECK, DETERMINE_VARIANT_MATRIX, DETERMINE_TEST_LOCATION, CREATE_SNAPSHOT_TEST_FILE, GENERATE_ENUM_VARIANTS, GENERATE_OPTIONAL_VARIANTS, GENERATE_RTL_VARIANTS, RUN_AND_RECORD]
632
- ARTIFACTS_CREATED:
633
- - Tests/{sourceModule}Tests/Snapshot/{componentPath}/{componentName}SnapshotTests.swift
634
- - Tests/{sourceModule}Tests/__Snapshots__/{componentName}SnapshotTests/*.png
635
- SUMMARY: {COUNT} snapshot tests - {ENUM_COUNT} enum variants × 2 themes + {OPTIONAL_COUNT} optional variants × 2 themes + {RTL_COUNT} RTL variants × 2 themes + {LOCALE_COUNT} locale variants (TR/EN) × 2 themes = {TOTAL} snapshots.
636
- ```