@mmerterden/multi-agent-pipeline 11.2.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 (331) hide show
  1. package/CHANGELOG.md +37 -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/_dev-only-files.mjs +0 -6
  7. package/install/claude.mjs +33 -15
  8. package/install/copilot.mjs +16 -14
  9. package/install/templates/copilot-instructions.md +3 -3
  10. package/package.json +1 -1
  11. package/pipeline/commands/{multi-agent.md → multi-agent/SKILL.md} +39 -39
  12. package/pipeline/commands/multi-agent/{analysis.md → analysis/SKILL.md} +18 -18
  13. package/pipeline/commands/multi-agent/{analysis-resolve.md → analysis-resolve/SKILL.md} +4 -4
  14. package/pipeline/commands/multi-agent/{autopilot.md → autopilot/SKILL.md} +4 -4
  15. package/pipeline/commands/multi-agent/{build-optimize.md → build-optimize/SKILL.md} +1 -1
  16. package/pipeline/commands/multi-agent/{channels.md → channels/SKILL.md} +12 -12
  17. package/pipeline/commands/multi-agent/{dev.md → dev/SKILL.md} +4 -4
  18. package/pipeline/commands/multi-agent/{dev-autopilot.md → dev-autopilot/SKILL.md} +4 -4
  19. package/pipeline/commands/multi-agent/{dev-local.md → dev-local/SKILL.md} +5 -5
  20. package/pipeline/commands/multi-agent/{dev-local-autopilot.md → dev-local-autopilot/SKILL.md} +4 -4
  21. package/pipeline/commands/multi-agent/{finish.md → finish/SKILL.md} +6 -6
  22. package/pipeline/commands/multi-agent/{generate.md → generate/SKILL.md} +3 -3
  23. package/pipeline/commands/multi-agent/{help.md → help/SKILL.md} +4 -4
  24. package/pipeline/commands/multi-agent/{local.md → local/SKILL.md} +5 -5
  25. package/pipeline/commands/multi-agent/{local-autopilot.md → local-autopilot/SKILL.md} +5 -5
  26. package/pipeline/commands/multi-agent/{manual-test.md → manual-test/SKILL.md} +1 -1
  27. package/pipeline/commands/multi-agent/refactor/SKILL.md +257 -0
  28. package/pipeline/commands/multi-agent/{resume.md → resume/SKILL.md} +1 -1
  29. package/pipeline/commands/multi-agent/{review.md → review/SKILL.md} +5 -5
  30. package/pipeline/commands/multi-agent/{setup.md → setup/SKILL.md} +1 -1
  31. package/pipeline/commands/multi-agent/{sync.md → sync/SKILL.md} +20 -58
  32. package/pipeline/{commands/multi-agent → multi-agent-refs}/_account-picker.md +2 -2
  33. package/pipeline/{commands/multi-agent → multi-agent-refs}/_dev-context.md +2 -2
  34. package/pipeline/{commands/multi-agent → multi-agent-refs}/_repo-picker.md +2 -2
  35. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/android-guide.md +1 -1
  36. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/jira.md +1 -1
  37. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/wiki.md +7 -7
  38. package/pipeline/multi-agent-refs/component-dispatch.md +92 -0
  39. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/cross-cli-contract.md +10 -77
  40. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/verify-by-test.md +1 -1
  41. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/generate-issue.md +2 -2
  42. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/issue-jira-triad.md +1 -1
  43. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/keychain.md +1 -1
  44. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/log-format.md +1 -1
  45. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/modes.md +2 -2
  46. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/operations.md +1 -1
  47. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-0-init.md +10 -10
  48. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-1-analysis.md +6 -6
  49. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-2-planning.md +3 -3
  50. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-3-dev.md +10 -10
  51. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-4-review.md +8 -8
  52. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-5-test.md +3 -3
  53. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-6-commit.md +4 -4
  54. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-7-report.md +6 -6
  55. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases.md +12 -12
  56. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/progress-contract.md +4 -4
  57. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/swiftui-guide.md +1 -1
  58. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/tracker-contract.md +3 -3
  59. package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/wiki-capture.md +4 -4
  60. package/pipeline/preferences-template.json +17 -1
  61. package/pipeline/rules/figma-pipeline.md +2 -2
  62. package/pipeline/schemas/prefs.schema.json +0 -34
  63. package/pipeline/scripts/README.md +1 -3
  64. package/pipeline/scripts/fixtures/install-layout.tsv +6 -5
  65. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
  66. package/pipeline/scripts/phase-banner.sh +2 -2
  67. package/pipeline/scripts/review-scope.mjs +94 -0
  68. package/pipeline/scripts/scan-agent-config.sh +2 -2
  69. package/pipeline/scripts/smoke-agent-log-cost.sh +1 -1
  70. package/pipeline/scripts/smoke-agent-model-routing.sh +4 -4
  71. package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +2 -2
  72. package/pipeline/scripts/smoke-channels-approval-gate.sh +2 -2
  73. package/pipeline/scripts/smoke-channels-flow.sh +5 -5
  74. package/pipeline/scripts/smoke-clarify.sh +1 -1
  75. package/pipeline/scripts/smoke-commands-skills-parity.sh +3 -3
  76. package/pipeline/scripts/smoke-community-gates.sh +1 -1
  77. package/pipeline/scripts/smoke-compliance-skills.sh +2 -2
  78. package/pipeline/scripts/smoke-cost-summary.sh +1 -1
  79. package/pipeline/scripts/smoke-cross-cli-behavior.sh +17 -43
  80. package/pipeline/scripts/smoke-cross-phase-cohesion.sh +1 -1
  81. package/pipeline/scripts/smoke-dev-critic.sh +1 -1
  82. package/pipeline/scripts/smoke-diff-explain.sh +1 -1
  83. package/pipeline/scripts/smoke-diff-risk.sh +1 -1
  84. package/pipeline/scripts/smoke-evidence-gate.sh +1 -1
  85. package/pipeline/scripts/smoke-figma-dispatch.sh +46 -57
  86. package/pipeline/scripts/smoke-gate-hooks.sh +1 -1
  87. package/pipeline/scripts/smoke-generate-issue.sh +8 -8
  88. package/pipeline/scripts/smoke-handoff-contract.sh +3 -3
  89. package/pipeline/scripts/smoke-identity-isolation.sh +2 -2
  90. package/pipeline/scripts/smoke-intent-guard.sh +1 -1
  91. package/pipeline/scripts/smoke-issue-comment-template.sh +2 -2
  92. package/pipeline/scripts/smoke-issue-jira-triad.sh +4 -4
  93. package/pipeline/scripts/smoke-language-axis.sh +6 -6
  94. package/pipeline/scripts/smoke-learnings-ledger.sh +3 -3
  95. package/pipeline/scripts/smoke-mode-dispatch-drift.sh +16 -16
  96. package/pipeline/scripts/smoke-model-fallback.sh +3 -3
  97. package/pipeline/scripts/smoke-multi-repo-integration.sh +2 -2
  98. package/pipeline/scripts/smoke-multi-repo-worktree.sh +1 -1
  99. package/pipeline/scripts/smoke-no-token-prompt.sh +5 -5
  100. package/pipeline/scripts/smoke-phase-0-multi-repo.sh +1 -1
  101. package/pipeline/scripts/smoke-phase-6-multi.sh +1 -1
  102. package/pipeline/scripts/smoke-phase4-gates.sh +45 -0
  103. package/pipeline/scripts/smoke-plan-approval-gate.sh +5 -5
  104. package/pipeline/scripts/smoke-plan-todos.sh +3 -3
  105. package/pipeline/scripts/smoke-pr-review-actions.sh +3 -3
  106. package/pipeline/scripts/smoke-prefs-language.sh +1 -1
  107. package/pipeline/scripts/smoke-progress-contract.sh +2 -2
  108. package/pipeline/scripts/smoke-push-retry.sh +1 -1
  109. package/pipeline/scripts/smoke-repo-map.sh +2 -2
  110. package/pipeline/scripts/smoke-shadow-git.sh +1 -1
  111. package/pipeline/scripts/smoke-skill-authoring.sh +4 -9
  112. package/pipeline/scripts/smoke-tasklist-ordering.sh +10 -10
  113. package/pipeline/scripts/smoke-test-gap.sh +1 -1
  114. package/pipeline/scripts/smoke-token-budget.sh +1 -1
  115. package/pipeline/scripts/smoke-token-preflight.sh +2 -2
  116. package/pipeline/scripts/smoke-tracker-contract.sh +13 -13
  117. package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +5 -5
  118. package/pipeline/scripts/smoke-triage-memory.sh +2 -2
  119. package/pipeline/scripts/smoke-update-check.sh +1 -1
  120. package/pipeline/scripts/smoke-url-enrichment.sh +2 -2
  121. package/pipeline/scripts/smoke-validator-gates.sh +1 -1
  122. package/pipeline/scripts/smoke-verify-by-test.sh +3 -3
  123. package/pipeline/scripts/smoke-wiki-integration.sh +9 -33
  124. package/pipeline/scripts/smoke-work-summary.sh +1 -1
  125. package/pipeline/scripts/smoke-worktree-path-convention.sh +4 -4
  126. package/pipeline/scripts/test-integrity-gate.mjs +83 -0
  127. package/pipeline/scripts/uninstall.mjs +2 -2
  128. package/pipeline/skills/.skill-manifest.json +40 -160
  129. package/pipeline/skills/.skills-index.json +3 -372
  130. package/pipeline/skills/shared/README.md +1 -1
  131. package/pipeline/skills/shared/core/multi-agent/SKILL.md +1 -1
  132. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +2 -2
  133. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +3 -3
  134. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
  135. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +1 -1
  136. package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
  137. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +1 -1
  138. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +116 -51
  139. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +8 -30
  140. package/pipeline/skills/shared/external/compose-components/SKILL.md +14 -14
  141. package/pipeline/skills/skills-index.md +2 -43
  142. package/pipeline/commands/multi-agent/refactor.md +0 -188
  143. package/pipeline/commands/multi-agent/refs/component-dispatch.md +0 -92
  144. package/pipeline/scripts/smoke-existing-discovery-gate.sh +0 -71
  145. package/pipeline/scripts/smoke-figma-android-parity.sh +0 -148
  146. package/pipeline/scripts/smoke-figma-credential-store.sh +0 -105
  147. package/pipeline/scripts/smoke-figma-cross-cli-inventory.sh +0 -177
  148. package/pipeline/scripts/smoke-figma-sync.sh +0 -149
  149. package/pipeline/scripts/smoke-sync-delegation.sh +0 -74
  150. package/pipeline/skills/figma-android/README.md +0 -38
  151. package/pipeline/skills/figma-android/figma-component-code-connect/SKILL.md +0 -62
  152. package/pipeline/skills/figma-android/figma-component-implement/SKILL.md +0 -158
  153. package/pipeline/skills/figma-android/figma-component-test/SKILL.md +0 -120
  154. package/pipeline/skills/figma-android/figma-component-wiki/SKILL.md +0 -35
  155. package/pipeline/skills/figma-android/figma-to-component/SKILL.md +0 -124
  156. package/pipeline/skills/figma-common/README.md +0 -64
  157. package/pipeline/skills/figma-common/figma-bottom-sheets/SKILL.md +0 -152
  158. package/pipeline/skills/figma-common/figma-cli-iterate/SKILL.md +0 -282
  159. package/pipeline/skills/figma-common/figma-cli-iterate-mend/SKILL.md +0 -503
  160. package/pipeline/skills/figma-common/figma-cli-lean-iterate/SKILL.md +0 -288
  161. package/pipeline/skills/figma-common/figma-cli-skip/SKILL.md +0 -362
  162. package/pipeline/skills/figma-common/figma-commit/COMMON_REBASE.md +0 -206
  163. package/pipeline/skills/figma-common/figma-commit/REVIEW.md +0 -337
  164. package/pipeline/skills/figma-common/figma-commit/SKILL.md +0 -216
  165. package/pipeline/skills/figma-common/figma-component-confluence-sync/SKILL.md +0 -223
  166. package/pipeline/skills/figma-common/figma-component-start/SKILL.md +0 -251
  167. package/pipeline/skills/figma-common/figma-component-status-update/SKILL.md +0 -78
  168. package/pipeline/skills/figma-common/figma-evolve-component/SKILL.md +0 -61
  169. package/pipeline/skills/figma-common/figma-fix/SKILL.md +0 -321
  170. package/pipeline/skills/figma-common/figma-form-integration/SKILL.md +0 -542
  171. package/pipeline/skills/figma-common/figma-issue/SKILL.md +0 -750
  172. package/pipeline/skills/figma-common/figma-iterate/SKILL.md +0 -208
  173. package/pipeline/skills/figma-common/figma-iteration-commit/SKILL.md +0 -1020
  174. package/pipeline/skills/figma-common/figma-mend/SKILL.md +0 -331
  175. package/pipeline/skills/figma-common/figma-navigation/SKILL.md +0 -156
  176. package/pipeline/skills/figma-common/figma-overlays/SKILL.md +0 -142
  177. package/pipeline/skills/figma-common/figma-price-integration/SKILL.md +0 -398
  178. package/pipeline/skills/figma-common/figma-remote-mcp-auth/SKILL.md +0 -104
  179. package/pipeline/skills/figma-common/figma-review/SKILL.md +0 -400
  180. package/pipeline/skills/figma-common/figma-setup/SKILL.md +0 -514
  181. package/pipeline/skills/figma-common/figma-setup/scripts/fetch-mcp-token.py +0 -592
  182. package/pipeline/skills/figma-common/figma-skip/SKILL.md +0 -129
  183. package/pipeline/skills/figma-common/figma-ui-patterns/SKILL.md +0 -105
  184. package/pipeline/skills/figma-common/figma-ui-patterns/patterns/animated-gradient-border.md +0 -116
  185. package/pipeline/skills/figma-common/figma-utility/SKILL.md +0 -274
  186. package/pipeline/skills/figma-common/figma-utility/scripts/figma-utility.py +0 -808
  187. package/pipeline/skills/figma-common/figma-validate/SKILL.md +0 -633
  188. package/pipeline/skills/figma-common/performance-iteration-commit-all/SKILL.md +0 -716
  189. package/pipeline/skills/figma-common/performance-review-next/SKILL.md +0 -238
  190. package/pipeline/skills/figma-common/performance-start/SKILL.md +0 -430
  191. package/pipeline/skills/figma-common/performance-swiftui/SKILL.md +0 -706
  192. package/pipeline/skills/figma-common/performance-tour/SKILL.md +0 -423
  193. package/pipeline/skills/figma-ios/REVIEW_CHECKLIST.md +0 -67
  194. package/pipeline/skills/figma-ios/figma-component-code-connect/SKILL.md +0 -178
  195. package/pipeline/skills/figma-ios/figma-component-implement/SKILL.md +0 -184
  196. package/pipeline/skills/figma-ios/figma-component-test/SKILL.md +0 -219
  197. package/pipeline/skills/figma-ios/figma-component-wiki/SKILL.md +0 -274
  198. package/pipeline/skills/figma-ios/figma-to-component/SKILL.md +0 -416
  199. package/pipeline/skills/figma-ios/figma-to-component/halt-return-protocol.md +0 -57
  200. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-0-init.md +0 -307
  201. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1-gathering.md +0 -119
  202. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1.5-existing-discovery.md +0 -174
  203. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2-orchestrator.md +0 -333
  204. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2a-testing-identifiers.md +0 -368
  205. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2b-localization.md +0 -393
  206. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2c-accessibility.md +0 -617
  207. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2d-analytics.md +0 -352
  208. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3-orchestrator.md +0 -337
  209. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3a-location.md +0 -206
  210. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3b-tokens.md +0 -235
  211. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3c-nested.md +0 -214
  212. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3d-patterns.md +0 -902
  213. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3e-assets.md +0 -156
  214. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3f-utilities.md +0 -175
  215. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3g-property-coverage.md +0 -176
  216. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3h-variant-config.md +0 -333
  217. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4-orchestrator.md +0 -412
  218. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4a-configuration.md +0 -336
  219. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4b-view.md +0 -705
  220. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4c-documentation.md +0 -332
  221. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4d-preview.md +0 -380
  222. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4e-modifiers.md +0 -262
  223. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5-orchestrator.md +0 -482
  224. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5a-viewinspector.md +0 -274
  225. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5b-snapshot.md +0 -636
  226. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5c-unit.md +0 -142
  227. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-6-code-connect.md +0 -547
  228. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7-wiki.md +0 -39
  229. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-confluence-generate.md +0 -659
  230. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-wiki-generate.md +0 -580
  231. package/pipeline/skills/figma-ios/figma-to-component/phases/phase-8-cleanup.md +0 -51
  232. package/pipeline/skills/figma-ios/figma-to-component/reference/accessibility.md +0 -183
  233. package/pipeline/skills/figma-ios/figma-to-component/reference/analytics-events.md +0 -64
  234. package/pipeline/skills/figma-ios/figma-to-component/reference/code-connect.md +0 -531
  235. package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-api.md +0 -89
  236. package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-xhtml.md +0 -155
  237. package/pipeline/skills/figma-ios/figma-to-component/reference/figma-to-swiftui-effects.md +0 -196
  238. package/pipeline/skills/figma-ios/figma-to-component/reference/halt-return-protocol.md +0 -57
  239. package/pipeline/skills/figma-ios/figma-to-component/reference/localization-naming.md +0 -89
  240. package/pipeline/skills/figma-ios/figma-to-component/reference/macros.md +0 -227
  241. package/pipeline/skills/figma-ios/figma-to-component/reference/missing-tokens.md +0 -157
  242. package/pipeline/skills/figma-ios/figma-to-component/reference/orchestrator-discipline.md +0 -90
  243. package/pipeline/skills/figma-ios/figma-to-component/reference/registry.md +0 -116
  244. package/pipeline/skills/figma-ios/figma-to-component/reference/remote-mcp-script.md +0 -153
  245. package/pipeline/skills/figma-ios/figma-to-component/reference/rest-api-script.md +0 -130
  246. package/pipeline/skills/figma-ios/figma-to-component/reference/scripts-inventory.md +0 -218
  247. package/pipeline/skills/figma-ios/figma-to-component/reference/snapshot-testing.md +0 -188
  248. package/pipeline/skills/figma-ios/figma-to-component/reference/subcomponent-graph.md +0 -93
  249. package/pipeline/skills/figma-ios/figma-to-component/reference/testing-identifiers-naming.md +0 -98
  250. package/pipeline/skills/figma-ios/figma-to-component/reference/tools.md +0 -261
  251. package/pipeline/skills/figma-ios/figma-to-component/reference/viewinspector.md +0 -147
  252. package/pipeline/skills/figma-ios/figma-to-component/reference/wiki-to-confluence-mapping.md +0 -182
  253. package/pipeline/skills/figma-ios/figma-to-component/scripts/apply-author-login-map.py +0 -185
  254. package/pipeline/skills/figma-ios/figma-to-component/scripts/backfill-status.py +0 -609
  255. package/pipeline/skills/figma-ios/figma-to-component/scripts/build-author-registry.py +0 -332
  256. package/pipeline/skills/figma-ios/figma-to-component/scripts/bulk-sync-issues.py +0 -261
  257. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-data-gather.py +0 -184
  258. package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-publish.sh +0 -188
  259. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status-upload.py +0 -768
  260. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status.py +0 -191
  261. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-data-gather.py +0 -420
  262. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-page-ids.example.json +0 -9
  263. package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-publish.py +0 -336
  264. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-subcomponent-graph.py +0 -391
  265. package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-update.py +0 -292
  266. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/__init__.py +0 -1
  267. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/issue_sync_propagate.py +0 -93
  268. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/registry_writer.py +0 -299
  269. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_backfill_status.py +0 -343
  270. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update.py +0 -206
  271. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update_http.py +0 -149
  272. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_phase_clis.py +0 -281
  273. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_registry_writer.py +0 -332
  274. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_issue.py +0 -176
  275. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_review.py +0 -98
  276. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue.py +0 -298
  277. package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue_gh.py +0 -195
  278. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase1-gather.py +0 -1298
  279. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase2-finalize.py +0 -228
  280. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase3-scripts.py +0 -1089
  281. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase4-finalize.py +0 -141
  282. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase5-finalize.py +0 -106
  283. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase6-finalize.py +0 -162
  284. package/pipeline/skills/figma-ios/figma-to-component/scripts/phase7-finalize.py +0 -105
  285. package/pipeline/skills/figma-ios/figma-to-component/scripts/register-icons-codeconnect.py +0 -179
  286. package/pipeline/skills/figma-ios/figma-to-component/scripts/remote-mcp-fetch.py +0 -260
  287. package/pipeline/skills/figma-ios/figma-to-component/scripts/resolve-author-logins.py +0 -260
  288. package/pipeline/skills/figma-ios/figma-to-component/scripts/run-uicomponents-tests.sh +0 -86
  289. package/pipeline/skills/figma-ios/figma-to-component/scripts/sidebar-generator.py +0 -321
  290. package/pipeline/skills/figma-ios/figma-to-component/scripts/update-issue-from-registry.py +0 -1470
  291. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase4.sh +0 -176
  292. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase6.sh +0 -147
  293. package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase7a.py +0 -629
  294. /package/pipeline/commands/multi-agent/{delete.md → delete/SKILL.md} +0 -0
  295. /package/pipeline/commands/multi-agent/{diff-explain.md → diff-explain/SKILL.md} +0 -0
  296. /package/pipeline/commands/multi-agent/{garbage-collect.md → garbage-collect/SKILL.md} +0 -0
  297. /package/pipeline/commands/multi-agent/{issue.md → issue/SKILL.md} +0 -0
  298. /package/pipeline/commands/multi-agent/{jira.md → jira/SKILL.md} +0 -0
  299. /package/pipeline/commands/multi-agent/{kill.md → kill/SKILL.md} +0 -0
  300. /package/pipeline/commands/multi-agent/{language.md → language/SKILL.md} +0 -0
  301. /package/pipeline/commands/multi-agent/{log.md → log/SKILL.md} +0 -0
  302. /package/pipeline/commands/multi-agent/{prune-logs.md → prune-logs/SKILL.md} +0 -0
  303. /package/pipeline/commands/multi-agent/{purge.md → purge/SKILL.md} +0 -0
  304. /package/pipeline/commands/multi-agent/{scan.md → scan/SKILL.md} +0 -0
  305. /package/pipeline/commands/multi-agent/{search.md → search/SKILL.md} +0 -0
  306. /package/pipeline/commands/multi-agent/{stack.md → stack/SKILL.md} +0 -0
  307. /package/pipeline/commands/multi-agent/{status.md → status/SKILL.md} +0 -0
  308. /package/pipeline/commands/multi-agent/{test.md → test/SKILL.md} +0 -0
  309. /package/pipeline/commands/multi-agent/{update.md → update/SKILL.md} +0 -0
  310. /package/pipeline/{commands/multi-agent → multi-agent-refs}/_input-parser.md +0 -0
  311. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/analysis-template.md +0 -0
  312. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/audit-guide.md +0 -0
  313. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/backend-guide.md +0 -0
  314. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/confluence.md +0 -0
  315. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/issue-comment.md +0 -0
  316. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr-review-actions.md +0 -0
  317. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr.md +0 -0
  318. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/conventions-defaults.md +0 -0
  319. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/autopilot-circuit-breaker.md +0 -0
  320. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/dev-critic.md +0 -0
  321. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/external-context-injection.md +0 -0
  322. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/model-fallback.md +0 -0
  323. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/plan-todos.md +0 -0
  324. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/prior-fix-detection.md +0 -0
  325. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/repo-map.md +0 -0
  326. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/shadow-git.md +0 -0
  327. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/frontend-guide.md +0 -0
  328. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/knowledge.md +0 -0
  329. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/multi-repo-integration-build.md +0 -0
  330. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/picker-contract.md +0 -0
  331. /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/rules.md +0 -0
@@ -1,332 +0,0 @@
1
- """Unit tests for registry_writer.py.
2
-
3
- Run: python3 -m unittest test_registry_writer.py
4
- Or: python3 test_registry_writer.py
5
-
6
- Uses tempfile for isolation - no network, no repo writes, no dependencies
7
- beyond the Python standard library.
8
- """
9
-
10
- import json
11
- import sys
12
- import tempfile
13
- import time
14
- import unittest
15
- from pathlib import Path
16
-
17
- sys.path.insert(0, str(Path(__file__).parent))
18
-
19
- from registry_writer import ( # noqa: E402
20
- FLAGS,
21
- PLATFORMS,
22
- _blank_platform_status,
23
- get_flag_state,
24
- mark_stale,
25
- set_flag,
26
- set_implemented,
27
- )
28
-
29
-
30
- class RegistryWriterTests(unittest.TestCase):
31
- def setUp(self):
32
- self.tmp = tempfile.TemporaryDirectory()
33
- self.registry_dir = Path(self.tmp.name)
34
- self.node_id = "10447:6925"
35
- self.path = self.registry_dir / "10447-6925.json"
36
-
37
- def tearDown(self):
38
- self.tmp.cleanup()
39
-
40
- def _load(self):
41
- return json.loads(self.path.read_text())
42
-
43
- def _write_seed(self, data):
44
- self.path.write_text(json.dumps(data, indent=2) + "\n")
45
-
46
- # ------------------------------------------------------------------
47
- # set_implemented
48
- # ------------------------------------------------------------------
49
-
50
- def test_set_implemented_creates_new_file(self):
51
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
52
- data = self._load()
53
- self.assertEqual(data["nodeId"], self.node_id)
54
- impl = data["status"]["ios"]["implemented"]
55
- self.assertTrue(impl["value"])
56
- self.assertEqual(impl["version"], 1)
57
- self.assertIsNotNone(impl["at"])
58
- self.assertEqual(data["updatedBy"], "phase-4-view")
59
-
60
- def test_set_implemented_creates_both_platform_blocks(self):
61
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
62
- data = self._load()
63
- # ios written, android exists but untouched
64
- self.assertTrue(data["status"]["ios"]["implemented"]["value"])
65
- self.assertFalse(data["status"]["android"]["implemented"]["value"])
66
- self.assertEqual(data["status"]["android"]["implemented"]["version"], 0)
67
-
68
- def test_set_implemented_preserves_existing_top_level_fields(self):
69
- seed = {
70
- "nodeId": self.node_id,
71
- "componentName": {"ios": "Button", "android": "Button"},
72
- "fileKey": "abc123",
73
- "skip": False,
74
- "codeConnect": {"ios": False, "android": True},
75
- "confluence": {"page": "https://x", "ios": None, "android": None},
76
- "lastUpdated": "2025-01-01",
77
- "updatedBy": "manual",
78
- "testingIdentifiers": [{"key": "foo"}],
79
- "localizationKeys": [],
80
- "accessibilityKeys": [],
81
- "analyticsEvents": [],
82
- }
83
- self._write_seed(seed)
84
-
85
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
86
- data = self._load()
87
-
88
- self.assertEqual(data["componentName"], {"ios": "Button", "android": "Button"})
89
- self.assertEqual(data["fileKey"], "abc123")
90
- self.assertEqual(data["skip"], False)
91
- self.assertEqual(data["confluence"]["page"], "https://x")
92
- self.assertEqual(data["testingIdentifiers"], [{"key": "foo"}])
93
- # Legacy codeConnect UNTOUCHED by set_implemented
94
- self.assertEqual(data["codeConnect"], {"ios": False, "android": True})
95
- # New block present
96
- self.assertTrue(data["status"]["ios"]["implemented"]["value"])
97
-
98
- def test_set_implemented_second_call_without_source_bumps(self):
99
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
100
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
101
- data = self._load()
102
- self.assertEqual(data["status"]["ios"]["implemented"]["version"], 2)
103
-
104
- def test_set_implemented_no_bump_on_byte_identical_source(self):
105
- src = self.registry_dir / "Button.swift"
106
- src.write_text("struct Button {}\n")
107
-
108
- set_implemented(self.registry_dir, self.node_id, "ios", source_file=src, updater="phase-4-view")
109
- first = self._load()["status"]["ios"]["implemented"]
110
- self.assertEqual(first["version"], 1)
111
- self.assertIsNotNone(first["hash"])
112
-
113
- # Identical re-run
114
- time.sleep(0.01)
115
- set_implemented(self.registry_dir, self.node_id, "ios", source_file=src, updater="phase-4-view")
116
- second = self._load()["status"]["ios"]["implemented"]
117
-
118
- self.assertEqual(second["version"], 1) # no bump
119
- self.assertEqual(second["hash"], first["hash"])
120
- self.assertEqual(second["at"], first["at"]) # at unchanged on no-op
121
-
122
- def test_set_implemented_bumps_on_content_change(self):
123
- src = self.registry_dir / "Button.swift"
124
- src.write_text("struct Button {}\n")
125
- set_implemented(self.registry_dir, self.node_id, "ios", source_file=src, updater="phase-4-view")
126
- v1 = self._load()["status"]["ios"]["implemented"]["version"]
127
-
128
- src.write_text("struct Button { let label: String }\n")
129
- set_implemented(self.registry_dir, self.node_id, "ios", source_file=src, updater="phase-4-view")
130
- v2 = self._load()["status"]["ios"]["implemented"]["version"]
131
-
132
- self.assertEqual(v1, 1)
133
- self.assertEqual(v2, 2)
134
-
135
- def test_set_implemented_clears_stale_on_same_platform_only(self):
136
- seed = {
137
- "nodeId": self.node_id,
138
- "status": {
139
- "ios": {
140
- "stale": True,
141
- "implemented": {"value": True, "version": 1, "hash": None, "at": "2026-04-01T00:00:00Z"},
142
- "tested": {"value": False, "against": 0, "at": None},
143
- "codeConnect": {"value": False, "against": 0, "at": None},
144
- "wiki": {"value": False, "against": 0, "at": None},
145
- },
146
- "android": {
147
- "stale": True,
148
- "implemented": {"value": True, "version": 1, "hash": None, "at": "2026-04-01T00:00:00Z"},
149
- "tested": {"value": False, "against": 0, "at": None},
150
- "codeConnect": {"value": False, "against": 0, "at": None},
151
- "wiki": {"value": False, "against": 0, "at": None},
152
- },
153
- },
154
- }
155
- self._write_seed(seed)
156
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
157
- data = self._load()
158
- self.assertFalse(data["status"]["ios"]["stale"])
159
- self.assertTrue(data["status"]["android"]["stale"]) # untouched
160
-
161
- def test_set_implemented_rejects_unknown_platform(self):
162
- with self.assertRaises(ValueError):
163
- set_implemented(self.registry_dir, self.node_id, "windows", updater="phase-4-view")
164
-
165
- # ------------------------------------------------------------------
166
- # set_flag
167
- # ------------------------------------------------------------------
168
-
169
- def test_set_flag_records_against_current_impl_version(self):
170
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
171
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
172
- # impl is now version 2
173
- set_flag(self.registry_dir, self.node_id, "ios", "tested", updater="phase-5-test")
174
- data = self._load()
175
- self.assertTrue(data["status"]["ios"]["tested"]["value"])
176
- self.assertEqual(data["status"]["ios"]["tested"]["against"], 2)
177
-
178
- def test_set_flag_rejects_unknown_flag(self):
179
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
180
- with self.assertRaises(ValueError):
181
- set_flag(self.registry_dir, self.node_id, "ios", "bogus", updater="x")
182
-
183
- def test_set_flag_rejects_implemented_as_flag(self):
184
- # 'implemented' is not in FLAGS - use set_implemented instead
185
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
186
- with self.assertRaises(ValueError):
187
- set_flag(self.registry_dir, self.node_id, "ios", "implemented", updater="x")
188
-
189
- def test_set_flag_codeconnect_mirrors_legacy_field(self):
190
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
191
- set_flag(self.registry_dir, self.node_id, "ios", "codeConnect", updater="phase-6")
192
- data = self._load()
193
- self.assertTrue(data["codeConnect"]["ios"])
194
- self.assertFalse(data["codeConnect"]["android"])
195
-
196
- def test_set_flag_tested_does_not_touch_legacy_codeconnect(self):
197
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
198
- # Pre-seed a legacy codeConnect=True
199
- data = self._load()
200
- data["codeConnect"] = {"ios": True, "android": False}
201
- self.path.write_text(json.dumps(data, indent=2) + "\n")
202
-
203
- set_flag(self.registry_dir, self.node_id, "ios", "tested", updater="phase-5")
204
- data = self._load()
205
- # Legacy unchanged
206
- self.assertTrue(data["codeConnect"]["ios"])
207
-
208
- def test_set_flag_all_three_flags_work(self):
209
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
210
- for flag in FLAGS:
211
- set_flag(self.registry_dir, self.node_id, "ios", flag, updater=f"phase-{flag}")
212
- data = self._load()
213
- for flag in FLAGS:
214
- self.assertTrue(data["status"]["ios"][flag]["value"], f"{flag} should be true")
215
- self.assertEqual(data["status"]["ios"][flag]["against"], 1)
216
-
217
- # ------------------------------------------------------------------
218
- # mark_stale
219
- # ------------------------------------------------------------------
220
-
221
- def test_mark_stale_updates_when_figma_is_newer(self):
222
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
223
- updated = mark_stale(self.registry_dir, self.node_id, "2026-04-15T10:00:00Z")
224
- self.assertTrue(updated)
225
- data = self._load()
226
- self.assertEqual(data["figmaUpdatedAt"], "2026-04-15T10:00:00Z")
227
- self.assertTrue(data["status"]["ios"]["stale"])
228
-
229
- def test_mark_stale_noop_when_figma_is_older(self):
230
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
231
- mark_stale(self.registry_dir, self.node_id, "2026-04-15T10:00:00Z")
232
-
233
- updated = mark_stale(self.registry_dir, self.node_id, "2026-04-10T00:00:00Z")
234
- self.assertFalse(updated)
235
- data = self._load()
236
- self.assertEqual(data["figmaUpdatedAt"], "2026-04-15T10:00:00Z")
237
-
238
- def test_mark_stale_only_marks_implemented_platforms(self):
239
- # Seed: ios implemented, android not
240
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
241
-
242
- mark_stale(self.registry_dir, self.node_id, "2026-04-15T10:00:00Z")
243
- data = self._load()
244
- self.assertTrue(data["status"]["ios"]["stale"])
245
- self.assertFalse(data["status"]["android"]["stale"]) # nothing to make stale
246
-
247
- def test_mark_stale_returns_false_for_missing_registry(self):
248
- updated = mark_stale(self.registry_dir, "9999:9999", "2026-04-15T10:00:00Z")
249
- self.assertFalse(updated)
250
- self.assertFalse((self.registry_dir / "9999-9999.json").exists())
251
-
252
- # ------------------------------------------------------------------
253
- # get_flag_state (yellow rule)
254
- # ------------------------------------------------------------------
255
-
256
- def test_get_flag_state_gray_for_missing_file(self):
257
- state = get_flag_state(self.registry_dir, self.node_id, "ios", "implemented")
258
- self.assertEqual(state, "gray")
259
-
260
- def test_get_flag_state_green_after_impl(self):
261
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
262
- self.assertEqual(get_flag_state(self.registry_dir, self.node_id, "ios", "implemented"), "green")
263
-
264
- def test_get_flag_state_gray_for_unset_tested(self):
265
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
266
- self.assertEqual(get_flag_state(self.registry_dir, self.node_id, "ios", "tested"), "gray")
267
-
268
- def test_get_flag_state_green_after_set_flag(self):
269
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
270
- set_flag(self.registry_dir, self.node_id, "ios", "tested", updater="phase-5")
271
- self.assertEqual(get_flag_state(self.registry_dir, self.node_id, "ios", "tested"), "green")
272
-
273
- def test_get_flag_state_yellow_when_impl_ahead(self):
274
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
275
- set_flag(self.registry_dir, self.node_id, "ios", "tested", updater="phase-5")
276
- set_flag(self.registry_dir, self.node_id, "ios", "codeConnect", updater="phase-6")
277
- set_flag(self.registry_dir, self.node_id, "ios", "wiki", updater="phase-7")
278
- # All green against version 1
279
- for flag in FLAGS:
280
- self.assertEqual(get_flag_state(self.registry_dir, self.node_id, "ios", flag), "green")
281
-
282
- # Re-implement - version bumps to 2
283
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
284
-
285
- # Everything downstream is now yellow
286
- for flag in FLAGS:
287
- self.assertEqual(
288
- get_flag_state(self.registry_dir, self.node_id, "ios", flag),
289
- "yellow",
290
- f"{flag} should be yellow after impl bump",
291
- )
292
- # impl itself stays green
293
- self.assertEqual(get_flag_state(self.registry_dir, self.node_id, "ios", "implemented"), "green")
294
-
295
- def test_yellow_clears_when_flag_re_set(self):
296
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
297
- set_flag(self.registry_dir, self.node_id, "ios", "tested", updater="phase-5")
298
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
299
- self.assertEqual(get_flag_state(self.registry_dir, self.node_id, "ios", "tested"), "yellow")
300
-
301
- set_flag(self.registry_dir, self.node_id, "ios", "tested", updater="phase-5")
302
- self.assertEqual(get_flag_state(self.registry_dir, self.node_id, "ios", "tested"), "green")
303
-
304
- # ------------------------------------------------------------------
305
- # Platform isolation + invariants
306
- # ------------------------------------------------------------------
307
-
308
- def test_ios_and_android_independent(self):
309
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
310
- set_implemented(self.registry_dir, self.node_id, "ios", updater="phase-4-view")
311
-
312
- data = self._load()
313
- self.assertEqual(data["status"]["ios"]["implemented"]["version"], 2)
314
- self.assertEqual(data["status"]["android"]["implemented"]["version"], 0)
315
- self.assertFalse(data["status"]["android"]["implemented"]["value"])
316
-
317
- def test_blank_platform_shape_matches_flags_constant(self):
318
- blank = _blank_platform_status()
319
- self.assertIn("stale", blank)
320
- self.assertIn("implemented", blank)
321
- for flag in FLAGS:
322
- self.assertIn(flag, blank)
323
- self.assertFalse(blank[flag]["value"])
324
- self.assertEqual(blank[flag]["against"], 0)
325
- self.assertIsNone(blank[flag]["at"])
326
-
327
- def test_platforms_constant_is_complete(self):
328
- self.assertEqual(set(PLATFORMS), {"ios", "android"})
329
-
330
-
331
- if __name__ == "__main__":
332
- unittest.main(verbosity=2)
@@ -1,176 +0,0 @@
1
- """Execute the embedded Python block from figma-issue/SKILL.md STEP 1.5a.
2
-
3
- The readiness check is a Python one-liner embedded inside a bash heredoc.
4
- This test extracts it, substitutes ${FIGMA_DIR} and <NODE_ID>, runs it
5
- against a fixture registry, and asserts the output JSON matches the
6
- expected per-component status.
7
-
8
- This is the *only* automated test that proves Step 6's blocker-logic
9
- edit actually works. If my edit has a syntax error or wrong field
10
- access, this fails.
11
-
12
- Run: python3 -m unittest test_skill_figma_issue.py
13
- """
14
-
15
- import json
16
- import re
17
- import subprocess
18
- import sys
19
- import tempfile
20
- import unittest
21
- from pathlib import Path
22
-
23
- REPO_ROOT = Path(__file__).resolve().parents[5]
24
- SKILL_MD = REPO_ROOT / ".instructions" / "figma" / "figma-issue" / "SKILL.md"
25
-
26
-
27
- def extract_readiness_python(skill_md: Path) -> str:
28
- """Pull the Python block from STEP 1.5a out of the SKILL.md.
29
-
30
- The block is inside a bash heredoc:
31
- python3 -c "
32
- import json, os, glob
33
- ...
34
- "
35
- We find the opening `python3 -c "` and read until the closing `"` on
36
- its own line before the code fence.
37
- """
38
- text = skill_md.read_text(encoding="utf-8")
39
- m = re.search(
40
- r'python3 -c "\n(.*?)\n"\n```',
41
- text,
42
- re.DOTALL,
43
- )
44
- if not m:
45
- raise RuntimeError("Could not locate readiness Python block in SKILL.md")
46
- return m.group(1)
47
-
48
-
49
- class SkillFigmaIssueReadinessTests(unittest.TestCase):
50
- @classmethod
51
- def setUpClass(cls):
52
- cls.code = extract_readiness_python(SKILL_MD)
53
-
54
- def setUp(self):
55
- self.tmp = tempfile.TemporaryDirectory()
56
- self.root = Path(self.tmp.name)
57
- self.figma_dir = self.root / "Figma"
58
- self.components_dir = self.figma_dir / "Components"
59
- self.components_dir.mkdir(parents=True)
60
-
61
- # Graph with one parent that depends on several sub-components
62
- graph = {
63
- "graph": {
64
- "1:1": {
65
- "subComponents": [
66
- "NewStyleButton", # new status block, implemented
67
- "LegacyButton", # legacy codeConnect=true
68
- "SkipButton", # skip=true
69
- "UnimplementedButton", # has entry but no impl
70
- "UnknownButton", # not in registry
71
- ],
72
- },
73
- },
74
- }
75
- (self.figma_dir / "sub-component-graph.json").write_text(json.dumps(graph))
76
-
77
- self._write_component("1-101.json", {
78
- "nodeId": "1:101",
79
- "componentName": {"ios": "NewStyleButton", "android": "NewStyleButton"},
80
- "skip": False,
81
- "codeConnect": {"ios": False, "android": False},
82
- "status": {
83
- "ios": {
84
- "stale": False,
85
- "implemented": {"value": True, "version": 1, "hash": None, "at": "..."},
86
- "tested": {"value": False, "against": 0, "at": None},
87
- "codeConnect": {"value": False, "against": 0, "at": None},
88
- "wiki": {"value": False, "against": 0, "at": None},
89
- },
90
- "android": {
91
- "stale": False,
92
- "implemented": {"value": False, "version": 0, "hash": None, "at": None},
93
- "tested": {"value": False, "against": 0, "at": None},
94
- "codeConnect": {"value": False, "against": 0, "at": None},
95
- "wiki": {"value": False, "against": 0, "at": None},
96
- },
97
- },
98
- })
99
-
100
- self._write_component("1-102.json", {
101
- "nodeId": "1:102",
102
- "componentName": {"ios": "LegacyButton", "android": "LegacyButton"},
103
- "skip": False,
104
- "codeConnect": {"ios": True, "android": False},
105
- # No status block at all - pure legacy shape
106
- })
107
-
108
- self._write_component("1-103.json", {
109
- "nodeId": "1:103",
110
- "componentName": {"ios": "SkipButton", "android": "SkipButton"},
111
- "skip": True,
112
- "codeConnect": {"ios": False, "android": False},
113
- })
114
-
115
- self._write_component("1-104.json", {
116
- "nodeId": "1:104",
117
- "componentName": {"ios": "UnimplementedButton", "android": "UnimplementedButton"},
118
- "skip": False,
119
- "codeConnect": {"ios": False, "android": False},
120
- })
121
-
122
- def tearDown(self):
123
- self.tmp.cleanup()
124
-
125
- def _write_component(self, filename: str, data: dict):
126
- (self.components_dir / filename).write_text(json.dumps(data))
127
-
128
- def _run_readiness(self, node_id: str = "1:1") -> dict:
129
- """Substitute placeholders and run the embedded block."""
130
- code = self.code.replace("${FIGMA_DIR}", str(self.figma_dir)).replace("<NODE_ID>", node_id)
131
- r = subprocess.run(
132
- ["python3", "-c", code],
133
- capture_output=True,
134
- text=True,
135
- check=False,
136
- )
137
- if r.returncode != 0:
138
- raise AssertionError(f"Readiness block crashed:\nSTDERR:\n{r.stderr}\nSTDOUT:\n{r.stdout}")
139
- return json.loads(r.stdout)
140
-
141
- def test_block_can_be_extracted(self):
142
- self.assertIn("status", self.code)
143
- self.assertIn("codeConnect", self.code)
144
-
145
- def test_new_status_implemented_is_implemented(self):
146
- out = self._run_readiness("1:1")
147
- subs = {s["name"]: s["status"] for s in out["subComponents"]}
148
- self.assertEqual(subs["NewStyleButton"], "implemented")
149
-
150
- def test_legacy_codeconnect_true_is_implemented(self):
151
- out = self._run_readiness("1:1")
152
- subs = {s["name"]: s["status"] for s in out["subComponents"]}
153
- self.assertEqual(subs["LegacyButton"], "implemented")
154
-
155
- def test_skip_true_is_skipped(self):
156
- out = self._run_readiness("1:1")
157
- subs = {s["name"]: s["status"] for s in out["subComponents"]}
158
- self.assertEqual(subs["SkipButton"], "skipped")
159
-
160
- def test_no_impl_is_not_implemented(self):
161
- out = self._run_readiness("1:1")
162
- subs = {s["name"]: s["status"] for s in out["subComponents"]}
163
- self.assertEqual(subs["UnimplementedButton"], "not_implemented")
164
-
165
- def test_unknown_component_is_unresolved(self):
166
- out = self._run_readiness("1:1")
167
- subs = {s["name"]: s["status"] for s in out["subComponents"]}
168
- self.assertEqual(subs["UnknownButton"], "unresolved")
169
-
170
- def test_no_deps_case(self):
171
- out = self._run_readiness("9:99") # not in graph
172
- self.assertEqual(out["status"], "no_deps")
173
-
174
-
175
- if __name__ == "__main__":
176
- unittest.main(verbosity=2)
@@ -1,98 +0,0 @@
1
- """Execute the embedded Python block from figma-review/SKILL.md STEP 0.
2
-
3
- Step 8 added a registry lookup block to figma-review/SKILL.md that
4
- resolves a ComponentName to a Figma nodeId so the issue can be found
5
- by `"{nodeId}" in:body` search. This test extracts that block,
6
- substitutes placeholders, and runs it against a fixture registry.
7
-
8
- Run: python3 -m unittest test_skill_figma_review.py
9
- """
10
-
11
- import json
12
- import re
13
- import subprocess
14
- import sys
15
- import tempfile
16
- import unittest
17
- from pathlib import Path
18
-
19
- REPO_ROOT = Path(__file__).resolve().parents[5]
20
- SKILL_MD = REPO_ROOT / ".instructions" / "figma" / "figma-review" / "SKILL.md"
21
-
22
-
23
- def extract_nodeid_lookup_python(skill_md: Path) -> str:
24
- """Pull the Python block that resolves ComponentName → nodeId."""
25
- text = skill_md.read_text(encoding="utf-8")
26
- m = re.search(
27
- r'NODE_ID=\$\(python3 -c "\n(.*?)\n"\)',
28
- text,
29
- re.DOTALL,
30
- )
31
- if not m:
32
- raise RuntimeError("Could not locate node-id lookup block in figma-review SKILL.md")
33
- return m.group(1)
34
-
35
-
36
- class SkillFigmaReviewLookupTests(unittest.TestCase):
37
- @classmethod
38
- def setUpClass(cls):
39
- cls.code = extract_nodeid_lookup_python(SKILL_MD)
40
-
41
- def setUp(self):
42
- self.tmp = tempfile.TemporaryDirectory()
43
- self.root = Path(self.tmp.name)
44
- self.figma_dir = self.root / "Figma"
45
- self.components_dir = self.figma_dir / "Components"
46
- self.components_dir.mkdir(parents=True)
47
-
48
- # Fixture: three components with different shapes
49
- (self.components_dir / "5-17752.json").write_text(json.dumps({
50
- "nodeId": "5:17752",
51
- "componentName": {"ios": "TurkishButton", "android": "TurkishButton"},
52
- }))
53
- (self.components_dir / "1-100.json").write_text(json.dumps({
54
- "nodeId": "1:100",
55
- "componentName": {"ios": "FlightCard", "android": "FlightCard"},
56
- }))
57
- # Legacy bare-string componentName
58
- (self.components_dir / "7-200.json").write_text(json.dumps({
59
- "nodeId": "7:200",
60
- "componentName": "InputArea",
61
- }))
62
-
63
- def tearDown(self):
64
- self.tmp.cleanup()
65
-
66
- def _run_lookup(self, component_name: str) -> str:
67
- code = self.code.replace("${FIGMA_DIR}", str(self.figma_dir)).replace("{ComponentName}", component_name)
68
- r = subprocess.run(
69
- ["python3", "-c", code],
70
- capture_output=True,
71
- text=True,
72
- check=False,
73
- )
74
- if r.returncode != 0:
75
- raise AssertionError(f"Lookup crashed:\nSTDERR:\n{r.stderr}\nSTDOUT:\n{r.stdout}")
76
- return r.stdout.strip()
77
-
78
- def test_block_can_be_extracted(self):
79
- self.assertIn("componentName", self.code)
80
- self.assertIn("nodeId", self.code)
81
-
82
- def test_dict_component_name_resolves(self):
83
- self.assertEqual(self._run_lookup("TurkishButton"), "5:17752")
84
-
85
- def test_different_component_resolves(self):
86
- self.assertEqual(self._run_lookup("FlightCard"), "1:100")
87
-
88
- def test_unknown_component_returns_empty(self):
89
- self.assertEqual(self._run_lookup("NonExistent"), "")
90
-
91
- def test_bare_string_component_name_resolves(self):
92
- # Real registry data has entries where componentName is "InputArea"
93
- # instead of {"ios": "InputArea", "android": "InputArea"}
94
- self.assertEqual(self._run_lookup("InputArea"), "7:200")
95
-
96
-
97
- if __name__ == "__main__":
98
- unittest.main(verbosity=2)