@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,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)