@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,629 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Phase 7A validation script.
4
-
5
- Supports two modes:
6
- - confluence: validates Confluence XHTML (main.html + ios.html)
7
- - wiki: validates wiki markdown ({ComponentName}.md)
8
-
9
- Usage:
10
- # Confluence mode (default)
11
- python3 validate-phase7a.py \
12
- --confluence-path "path/to/confluence" \
13
- --component-name "ComponentName"
14
-
15
- # Wiki mode
16
- python3 validate-phase7a.py \
17
- --wiki-path "path/to/wiki/component" \
18
- --component-name "ComponentName" \
19
- --mode wiki
20
-
21
- Exit codes:
22
- 0 = all checks pass
23
- 1 = validation failures found (details in JSON stdout)
24
- """
25
-
26
- import argparse
27
- import json
28
- import os
29
- import re
30
- import sys
31
- from pathlib import Path
32
- from typing import Dict, List, Optional, Set, Tuple
33
-
34
-
35
- def find_image_references(html_content: str) -> List[str]:
36
- """Extract all ri:filename values from <ac:image> and <ri:attachment> tags."""
37
- return re.findall(r'ri:filename="([^"]+)"', html_content)
38
-
39
-
40
- def find_template_variables(html_content: str) -> List[str]:
41
- """Find unreplaced template variables like {ComponentName}, {DESCRIPTION}, etc."""
42
- # Match {WORD} but exclude known Confluence macro params like {printable}
43
- confluence_params = {"true", "false", "disc", "circle", "square", "none"}
44
- matches = re.findall(r"\{([A-Z][A-Za-z_]+)\}", html_content)
45
- return [f"{{{m}}}" for m in matches if m.lower() not in confluence_params]
46
-
47
-
48
- def find_html_comments(html_content: str) -> List[str]:
49
- """Find remaining HTML comments (template conditionals)."""
50
- return re.findall(r"<!--\s*(IF|END|ELSE)[^>]*-->", html_content)
51
-
52
-
53
- def find_swift_code_leaks(html_content: str) -> List[str]:
54
- """Detect Swift code patterns that shouldn't be in main.html."""
55
- patterns = [
56
- (r"import\s+UIComponents", "import UIComponents"),
57
- (r"\.accessibilityIdentifier\(", ".accessibilityIdentifier("),
58
- (r"func\s+test_", "func test_"),
59
- (r"@testable\s+import", "@testable import"),
60
- ]
61
- leaks = []
62
- for pattern, label in patterns:
63
- if re.search(pattern, html_content):
64
- leaks.append(label)
65
- return leaks
66
-
67
-
68
- def check_required_sections(html_content: str, required: List[str]) -> Tuple[List[str], List[str]]:
69
- """Check which required <h2> sections are present/missing."""
70
- present = []
71
- missing = []
72
- for section in required:
73
- if f"<h2>{section}</h2>" in html_content:
74
- present.append(section)
75
- else:
76
- missing.append(section)
77
- return present, missing
78
-
79
-
80
- def check_unescaped_ampersands(html_content: str) -> List[str]:
81
- """Find unescaped & in XML attribute values."""
82
- violations = []
83
- # Check ri:filename and ri:content-title attributes for bare &
84
- for attr in ["ri:filename", "ri:content-title"]:
85
- for match in re.finditer(rf'{attr}="([^"]*)"', html_content):
86
- value = match.group(1)
87
- # Find bare & (not &amp; &lt; &gt; &quot; &apos; &#...)
88
- if re.search(r"&(?!amp;|lt;|gt;|quot;|apos;|#)", value):
89
- violations.append(f'{attr}="{value}"')
90
- return violations
91
-
92
-
93
- def validate_snapshot_coverage(
94
- assets_dir: Path,
95
- snapshot_source_dir: Optional[str],
96
- ios_html: str,
97
- component_name: str,
98
- ) -> dict:
99
- """Validate snapshot test coverage: every variant has assets + XHTML references."""
100
- result = {
101
- "variants_found": [],
102
- "missing_assets": [],
103
- "missing_references": [],
104
- "orphan_assets": [],
105
- "rtl_variants_found": [],
106
- "rtl_missing_assets": [],
107
- "rtl_missing_references": [],
108
- }
109
-
110
- # Collect all ios_ prefixed assets
111
- ios_assets = set()
112
- if assets_dir.exists():
113
- for f in assets_dir.iterdir():
114
- if f.name.startswith("ios_") and f.name.endswith(".png"):
115
- ios_assets.add(f.name)
116
-
117
- # Extract image references from ios.html
118
- ios_refs = set(find_image_references(ios_html))
119
- ios_image_refs = {r for r in ios_refs if r.startswith("ios_")}
120
-
121
- # Determine variants from asset files
122
- # Pattern: ios_light_{variant}.png, ios_dark_{variant}.png
123
- light_variants = set()
124
- dark_variants = set()
125
- rtl_light_variants = set()
126
- rtl_dark_variants = set()
127
-
128
- for asset in ios_assets:
129
- name = asset[:-4] # strip .png
130
- if name.startswith("ios_rtl_light_"):
131
- rtl_light_variants.add(name[len("ios_rtl_light_"):])
132
- elif name.startswith("ios_rtl_dark_"):
133
- rtl_dark_variants.add(name[len("ios_rtl_dark_"):])
134
- elif name.startswith("ios_light_"):
135
- light_variants.add(name[len("ios_light_"):])
136
- elif name.startswith("ios_dark_"):
137
- dark_variants.add(name[len("ios_dark_"):])
138
-
139
- # All variants = union of light and dark
140
- all_variants = light_variants | dark_variants
141
- result["variants_found"] = sorted(all_variants)
142
-
143
- # Check each variant has both light and dark assets
144
- for variant in sorted(all_variants):
145
- light_file = f"ios_light_{variant}.png"
146
- dark_file = f"ios_dark_{variant}.png"
147
- if light_file not in ios_assets:
148
- result["missing_assets"].append(light_file)
149
- if dark_file not in ios_assets:
150
- result["missing_assets"].append(dark_file)
151
- # Check XHTML references
152
- if light_file not in ios_image_refs:
153
- result["missing_references"].append(light_file)
154
- if dark_file not in ios_image_refs:
155
- result["missing_references"].append(dark_file)
156
-
157
- # RTL variants
158
- all_rtl = rtl_light_variants | rtl_dark_variants
159
- result["rtl_variants_found"] = sorted(all_rtl)
160
-
161
- for variant in sorted(all_rtl):
162
- light_file = f"ios_rtl_light_{variant}.png"
163
- dark_file = f"ios_rtl_dark_{variant}.png"
164
- if light_file not in ios_assets:
165
- result["rtl_missing_assets"].append(light_file)
166
- if dark_file not in ios_assets:
167
- result["rtl_missing_assets"].append(dark_file)
168
- if light_file not in ios_image_refs:
169
- result["rtl_missing_references"].append(light_file)
170
- if dark_file not in ios_image_refs:
171
- result["rtl_missing_references"].append(dark_file)
172
-
173
- # Orphan check: ios_ assets not referenced in XHTML
174
- for asset in sorted(ios_assets):
175
- if asset not in ios_image_refs:
176
- result["orphan_assets"].append(asset)
177
-
178
- return result
179
-
180
-
181
- def find_wiki_image_references(md_content: str) -> List[str]:
182
- """Extract all asset filenames from wiki image syntax [[/path/assets/file.png]] or [[/path/assets/file.png|alt]]."""
183
- matches = re.findall(r'\[\[/[^|\]]*?/assets/([^|\]]+?)(?:\|[^\]]*?)?\]\]', md_content)
184
- return matches
185
-
186
-
187
- def check_required_md_sections(md_content: str, required: List[str]) -> Tuple[List[str], List[str]]:
188
- """Check which required ## sections are present/missing in markdown."""
189
- present = []
190
- missing = []
191
- for section in required:
192
- pattern = rf'^## {re.escape(section)}\s*$'
193
- if re.search(pattern, md_content, re.MULTILINE):
194
- present.append(section)
195
- else:
196
- missing.append(section)
197
- return present, missing
198
-
199
-
200
- def check_required_md_subsections(md_content: str, required: List[str]) -> Tuple[List[str], List[str]]:
201
- """Check which required ### sections are present/missing in markdown."""
202
- present = []
203
- missing = []
204
- for section in required:
205
- pattern = rf'^### {re.escape(section)}\s*$'
206
- if re.search(pattern, md_content, re.MULTILINE):
207
- present.append(section)
208
- else:
209
- missing.append(section)
210
- return present, missing
211
-
212
-
213
- def validate_wiki_snapshot_coverage(
214
- assets_dir: Path,
215
- md_content: str,
216
- component_name: str,
217
- ) -> dict:
218
- """Validate snapshot test coverage in wiki markdown."""
219
- result = {
220
- "variants_found": [],
221
- "missing_assets": [],
222
- "missing_references": [],
223
- "orphan_assets": [],
224
- "rtl_variants_found": [],
225
- "rtl_missing_assets": [],
226
- "rtl_missing_references": [],
227
- }
228
-
229
- ios_assets = set()
230
- if assets_dir.exists():
231
- for f in assets_dir.iterdir():
232
- if f.name.startswith("ios_") and f.name.endswith(".png"):
233
- ios_assets.add(f.name)
234
-
235
- md_refs = set(find_wiki_image_references(md_content))
236
- ios_image_refs = {r for r in md_refs if r.startswith("ios_")}
237
-
238
- light_variants = set()
239
- dark_variants = set()
240
- rtl_light_variants = set()
241
- rtl_dark_variants = set()
242
-
243
- for asset in ios_assets:
244
- name = asset[:-4]
245
- if name.startswith("ios_rtl_light_"):
246
- rtl_light_variants.add(name[len("ios_rtl_light_"):])
247
- elif name.startswith("ios_rtl_dark_"):
248
- rtl_dark_variants.add(name[len("ios_rtl_dark_"):])
249
- elif name.startswith("ios_light_"):
250
- light_variants.add(name[len("ios_light_"):])
251
- elif name.startswith("ios_dark_"):
252
- dark_variants.add(name[len("ios_dark_"):])
253
-
254
- all_variants = light_variants | dark_variants
255
- result["variants_found"] = sorted(all_variants)
256
-
257
- for variant in sorted(all_variants):
258
- light_file = f"ios_light_{variant}.png"
259
- dark_file = f"ios_dark_{variant}.png"
260
- if light_file not in ios_assets:
261
- result["missing_assets"].append(light_file)
262
- if dark_file not in ios_assets:
263
- result["missing_assets"].append(dark_file)
264
- if light_file not in ios_image_refs:
265
- result["missing_references"].append(light_file)
266
- if dark_file not in ios_image_refs:
267
- result["missing_references"].append(dark_file)
268
-
269
- all_rtl = rtl_light_variants | rtl_dark_variants
270
- result["rtl_variants_found"] = sorted(all_rtl)
271
-
272
- for variant in sorted(all_rtl):
273
- light_file = f"ios_rtl_light_{variant}.png"
274
- dark_file = f"ios_rtl_dark_{variant}.png"
275
- if light_file not in ios_assets:
276
- result["rtl_missing_assets"].append(light_file)
277
- if dark_file not in ios_assets:
278
- result["rtl_missing_assets"].append(dark_file)
279
- if light_file not in ios_image_refs:
280
- result["rtl_missing_references"].append(light_file)
281
- if dark_file not in ios_image_refs:
282
- result["rtl_missing_references"].append(dark_file)
283
-
284
- for asset in sorted(ios_assets):
285
- if asset not in ios_image_refs:
286
- result["orphan_assets"].append(asset)
287
-
288
- return result
289
-
290
-
291
- def validate_wiki(wiki_path: Path, component_name: str) -> dict:
292
- """Validate wiki markdown documentation."""
293
- violations = []
294
- warnings = []
295
- stats = {}
296
-
297
- assets_dir = wiki_path / "assets"
298
- md_file = wiki_path / f"{component_name}.md"
299
- screenshot_file = assets_dir / "screenshot.png"
300
-
301
- if not md_file.exists():
302
- violations.append(f"{component_name}.md does not exist")
303
- return {"status": "FAIL", "violations": violations, "warnings": warnings, "stats": stats}
304
-
305
- if not screenshot_file.exists():
306
- violations.append("assets/screenshot.png does not exist")
307
-
308
- md_content = md_file.read_text(encoding="utf-8")
309
-
310
- # Required ## sections
311
- required_sections = [
312
- "Overview", "Testing Identifiers", "Localization Keys",
313
- "Accessibility", "Analytics Events", "Sub-Components",
314
- "Platform Implementations", "Changelog", "iOS Implementation",
315
- ]
316
- present, missing = check_required_md_sections(md_content, required_sections)
317
-
318
- # Allow placeholder text as alternative
319
- for section in list(missing):
320
- placeholders = {
321
- "Testing Identifiers": "No testing identifiers",
322
- "Localization Keys": "No localization keys",
323
- "Accessibility": "No dedicated accessibility keys",
324
- "Analytics Events": "No analytics events",
325
- "Sub-Components": "No nested View components",
326
- }
327
- if section in placeholders and placeholders[section] in md_content:
328
- missing.remove(section)
329
- present.append(f"{section} (placeholder)")
330
-
331
- if missing:
332
- violations.append(f"Missing sections: {missing}")
333
- stats["sections"] = len(present)
334
-
335
- # iOS subsections (under ## iOS Implementation)
336
- ios_start = md_content.find("## iOS Implementation")
337
- if ios_start >= 0:
338
- ios_content = md_content[ios_start:]
339
- ios_required = ["Initializer", "Usage"]
340
- ios_present, ios_missing = check_required_md_subsections(ios_content, ios_required)
341
- if ios_missing:
342
- violations.append(f"iOS missing subsections: {ios_missing}")
343
-
344
- has_snapshot_assets = any(
345
- f.startswith("ios_") and f.endswith(".png")
346
- for f in (os.listdir(assets_dir) if assets_dir.exists() else [])
347
- )
348
- has_snapshot_section = "## Snapshot Tests" in ios_content or "### Snapshot Tests" in md_content
349
- if has_snapshot_assets and not has_snapshot_section:
350
- violations.append("Missing Snapshot Tests section but snapshot assets exist")
351
- else:
352
- violations.append("Missing ## iOS Implementation split marker")
353
-
354
- # Template variables
355
- template_vars = find_template_variables(md_content)
356
- if template_vars:
357
- violations.append(f"Unreplaced template variables: {template_vars}")
358
-
359
- # HTML comments
360
- html_comments = find_html_comments(md_content)
361
- if html_comments:
362
- violations.append(f"Remaining template comments: {html_comments}")
363
-
364
- # Asset reference integrity
365
- md_refs = set(find_wiki_image_references(md_content))
366
- existing_assets = set()
367
- if assets_dir.exists():
368
- existing_assets = {f.name for f in assets_dir.iterdir() if f.is_file()}
369
-
370
- missing_assets = md_refs - existing_assets
371
- if missing_assets:
372
- violations.append(f"Referenced but missing from assets/: {sorted(missing_assets)}")
373
-
374
- orphan_assets = existing_assets - md_refs
375
- if orphan_assets:
376
- warnings.append(f"Assets not referenced in markdown: {sorted(orphan_assets)}")
377
-
378
- stats["assets_total"] = len(existing_assets)
379
- stats["assets_referenced"] = len(md_refs & existing_assets)
380
- stats["assets_orphaned"] = len(orphan_assets)
381
-
382
- # Snapshot coverage
383
- snapshot_result = validate_wiki_snapshot_coverage(assets_dir, md_content, component_name)
384
- stats["snapshot_variants"] = len(snapshot_result["variants_found"])
385
- stats["snapshot_rtl_variants"] = len(snapshot_result["rtl_variants_found"])
386
-
387
- if snapshot_result["missing_assets"]:
388
- violations.append(f"Snapshot variants missing asset files: {snapshot_result['missing_assets']}")
389
- if snapshot_result["missing_references"]:
390
- violations.append(f"Snapshot assets not referenced in markdown: {snapshot_result['missing_references']}")
391
- if snapshot_result["rtl_missing_assets"]:
392
- violations.append(f"RTL snapshot variants missing asset files: {snapshot_result['rtl_missing_assets']}")
393
- if snapshot_result["rtl_missing_references"]:
394
- violations.append(f"RTL snapshot assets not referenced in markdown: {snapshot_result['rtl_missing_references']}")
395
- if snapshot_result["orphan_assets"]:
396
- warnings.append(f"ios_ assets not referenced in markdown: {snapshot_result['orphan_assets']}")
397
-
398
- # Variant screenshots
399
- variant_assets = {a for a in existing_assets if not a.startswith("ios_") and a != "screenshot.png"}
400
- if variant_assets:
401
- variant_refs = {r for r in md_refs if not r.startswith("ios_") and r != "screenshot.png"}
402
- missing_variant_refs = variant_assets - variant_refs
403
- if missing_variant_refs:
404
- warnings.append(f"Variant assets not referenced in markdown: {sorted(missing_variant_refs)}")
405
- stats["variant_screenshots"] = len(variant_assets)
406
- else:
407
- stats["variant_screenshots"] = 0
408
-
409
- status = "PASS" if not violations else "FAIL"
410
- return {
411
- "status": status,
412
- "violations": violations,
413
- "warnings": warnings,
414
- "stats": stats,
415
- "snapshot_coverage": {
416
- "variants": snapshot_result["variants_found"],
417
- "rtl_variants": snapshot_result["rtl_variants_found"],
418
- "missing_assets": snapshot_result["missing_assets"],
419
- "missing_references": snapshot_result["missing_references"],
420
- },
421
- }
422
-
423
-
424
- def main():
425
- parser = argparse.ArgumentParser(description="Validate Phase 7A output (wiki or confluence)")
426
- parser.add_argument("--confluence-path", default=None, help="Path to confluence output directory")
427
- parser.add_argument("--wiki-path", default=None, help="Path to wiki component directory")
428
- parser.add_argument("--snapshot-dir", default=None, help="Path to __Snapshots__/ComponentSnapshotTests/ (optional)")
429
- parser.add_argument("--component-name", required=True, help="Component name (e.g., LabelBadge)")
430
- parser.add_argument("--mode", default="confluence", choices=["confluence", "wiki"], help="Validation mode")
431
- args = parser.parse_args()
432
-
433
- if args.mode == "wiki":
434
- if not args.wiki_path:
435
- print(json.dumps({"status": "FAIL", "violations": ["--wiki-path required for wiki mode"]}))
436
- sys.exit(1)
437
- output = validate_wiki(Path(args.wiki_path), args.component_name)
438
- print(json.dumps(output, indent=2))
439
- sys.exit(0 if output["status"] == "PASS" else 1)
440
-
441
- # Confluence mode (original behavior)
442
- if not args.confluence_path:
443
- print(json.dumps({"status": "FAIL", "violations": ["--confluence-path required for confluence mode"]}))
444
- sys.exit(1)
445
-
446
- confluence_path = Path(args.confluence_path)
447
- assets_dir = confluence_path / "assets"
448
-
449
- violations = []
450
- warnings = []
451
- stats = {}
452
-
453
- # --- 1. File existence ---
454
- main_file = confluence_path / "main.html"
455
- ios_file = confluence_path / "ios.html"
456
- screenshot_file = assets_dir / "screenshot.png"
457
-
458
- if not main_file.exists():
459
- violations.append("main.html does not exist")
460
- if not ios_file.exists():
461
- violations.append("ios.html does not exist")
462
- if not screenshot_file.exists():
463
- violations.append("assets/screenshot.png does not exist")
464
-
465
- if not main_file.exists() or not ios_file.exists():
466
- print(json.dumps({
467
- "status": "FAIL",
468
- "violations": violations,
469
- "warnings": warnings,
470
- }, indent=2))
471
- sys.exit(1)
472
-
473
- main_html = main_file.read_text(encoding="utf-8")
474
- ios_html = ios_file.read_text(encoding="utf-8")
475
-
476
- # --- 2. main.html required sections ---
477
- main_required = [
478
- "Variants", "Overview", "Testing Identifiers", "Localization Keys",
479
- "Accessibility", "Analytics Events", "Sub-Components",
480
- "Platform Implementations", "Changelog",
481
- ]
482
- main_present, main_missing = check_required_sections(main_html, main_required)
483
- # Sections can be replaced with placeholder text, check for that
484
- for section in list(main_missing):
485
- # Allow "No ..." placeholder as alternative to <h2> section
486
- placeholders = {
487
- "Testing Identifiers": "No testing identifiers",
488
- "Localization Keys": "No localization keys",
489
- "Accessibility": "No dedicated accessibility keys",
490
- "Analytics Events": "No analytics events",
491
- "Sub-Components": "No nested View components",
492
- }
493
- if section in placeholders and placeholders[section] in main_html:
494
- main_missing.remove(section)
495
- main_present.append(f"{section} (placeholder)")
496
-
497
- if main_missing:
498
- violations.append(f"main.html missing sections: {main_missing}")
499
- stats["main_sections"] = len(main_present)
500
-
501
- # --- 3. ios.html required sections ---
502
- ios_required = ["Initializer", "Usage", "Changelog"]
503
- ios_present, ios_missing = check_required_sections(ios_html, ios_required)
504
- if ios_missing:
505
- violations.append(f"ios.html missing sections: {ios_missing}")
506
-
507
- # Back-link check
508
- if "ri:content-title=" not in ios_html or "Back to" not in ios_html:
509
- violations.append("ios.html missing back-link to main page")
510
-
511
- # Snapshot Tests section (required if snapshot assets exist)
512
- has_snapshot_assets = any(
513
- f.startswith("ios_") and f.endswith(".png")
514
- for f in (os.listdir(assets_dir) if assets_dir.exists() else [])
515
- )
516
- has_snapshot_section = "<h2>Snapshot Tests</h2>" in ios_html
517
- if has_snapshot_assets and not has_snapshot_section:
518
- violations.append("ios.html missing <h2>Snapshot Tests</h2> section but snapshot assets exist")
519
- if has_snapshot_section:
520
- ios_present.append("Snapshot Tests")
521
- stats["ios_sections"] = len(ios_present)
522
-
523
- # Code Connect section (optional but tracked)
524
- if "<h2>Code Connect</h2>" in ios_html:
525
- ios_present.append("Code Connect")
526
-
527
- # --- 4. Template variables ---
528
- main_vars = find_template_variables(main_html)
529
- ios_vars = find_template_variables(ios_html)
530
- if main_vars:
531
- violations.append(f"main.html has unreplaced template variables: {main_vars}")
532
- if ios_vars:
533
- violations.append(f"ios.html has unreplaced template variables: {ios_vars}")
534
-
535
- # --- 5. HTML comments ---
536
- main_comments = find_html_comments(main_html)
537
- ios_comments = find_html_comments(ios_html)
538
- if main_comments:
539
- violations.append(f"main.html has remaining template comments: {main_comments}")
540
- if ios_comments:
541
- violations.append(f"ios.html has remaining template comments: {ios_comments}")
542
-
543
- # --- 6. Swift code leaks (main.html only) ---
544
- leaks = find_swift_code_leaks(main_html)
545
- if leaks:
546
- violations.append(f"main.html contains Swift code patterns: {leaks}")
547
-
548
- # --- 7. Unescaped ampersands ---
549
- main_amps = check_unescaped_ampersands(main_html)
550
- ios_amps = check_unescaped_ampersands(ios_html)
551
- if main_amps:
552
- violations.append(f"main.html has unescaped & in attributes: {main_amps}")
553
- if ios_amps:
554
- violations.append(f"ios.html has unescaped & in attributes: {ios_amps}")
555
-
556
- # --- 8. Asset reference integrity ---
557
- main_refs = set(find_image_references(main_html))
558
- ios_refs = set(find_image_references(ios_html))
559
- all_refs = main_refs | ios_refs
560
-
561
- existing_assets = set()
562
- if assets_dir.exists():
563
- existing_assets = {f.name for f in assets_dir.iterdir() if f.is_file()}
564
-
565
- # Referenced but missing
566
- missing_assets = all_refs - existing_assets
567
- if missing_assets:
568
- violations.append(f"Referenced in XHTML but missing from assets/: {sorted(missing_assets)}")
569
-
570
- # Existing but unreferenced (orphans)
571
- orphan_assets = existing_assets - all_refs
572
- if orphan_assets:
573
- warnings.append(f"Assets not referenced in any XHTML: {sorted(orphan_assets)}")
574
-
575
- stats["assets_total"] = len(existing_assets)
576
- stats["assets_referenced"] = len(all_refs & existing_assets)
577
- stats["assets_orphaned"] = len(orphan_assets)
578
-
579
- # --- 9. Snapshot coverage ---
580
- snapshot_result = validate_snapshot_coverage(
581
- assets_dir, args.snapshot_dir, ios_html, args.component_name
582
- )
583
- stats["snapshot_variants"] = len(snapshot_result["variants_found"])
584
- stats["snapshot_rtl_variants"] = len(snapshot_result["rtl_variants_found"])
585
-
586
- if snapshot_result["missing_assets"]:
587
- violations.append(f"Snapshot variants missing asset files: {snapshot_result['missing_assets']}")
588
- if snapshot_result["missing_references"]:
589
- violations.append(f"Snapshot assets not referenced in ios.html: {snapshot_result['missing_references']}")
590
- if snapshot_result["rtl_missing_assets"]:
591
- violations.append(f"RTL snapshot variants missing asset files: {snapshot_result['rtl_missing_assets']}")
592
- if snapshot_result["rtl_missing_references"]:
593
- violations.append(f"RTL snapshot assets not referenced in ios.html: {snapshot_result['rtl_missing_references']}")
594
- if snapshot_result["orphan_assets"]:
595
- warnings.append(f"ios_ assets not referenced in ios.html: {snapshot_result['orphan_assets']}")
596
-
597
- # --- 10. Variant section in main.html ---
598
- # If variant screenshots exist (non-ios_, non-screenshot.png), Variants section should have <ac:image>
599
- variant_assets = {a for a in existing_assets if not a.startswith("ios_") and a != "screenshot.png"}
600
- if variant_assets:
601
- variant_images_in_main = {r for r in main_refs if not r.startswith("ios_") and r != "screenshot.png"}
602
- missing_variant_refs = variant_assets - variant_images_in_main
603
- if missing_variant_refs:
604
- warnings.append(f"Variant assets not referenced in main.html: {sorted(missing_variant_refs)}")
605
- stats["variant_screenshots"] = len(variant_assets)
606
- else:
607
- stats["variant_screenshots"] = 0
608
-
609
- # --- Output ---
610
- status = "PASS" if not violations else "FAIL"
611
- output = {
612
- "status": status,
613
- "violations": violations,
614
- "warnings": warnings,
615
- "stats": stats,
616
- "snapshot_coverage": {
617
- "variants": snapshot_result["variants_found"],
618
- "rtl_variants": snapshot_result["rtl_variants_found"],
619
- "missing_assets": snapshot_result["missing_assets"],
620
- "missing_references": snapshot_result["missing_references"],
621
- },
622
- }
623
-
624
- print(json.dumps(output, indent=2))
625
- sys.exit(0 if status == "PASS" else 1)
626
-
627
-
628
- if __name__ == "__main__":
629
- main()