@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.
- package/CHANGELOG.md +37 -0
- package/README.md +2 -2
- package/docs/FIGMA_PIPELINE.md +12 -25
- package/docs/architecture.md +3 -5
- package/docs/features.md +8 -8
- package/install/_dev-only-files.mjs +0 -6
- package/install/claude.mjs +33 -15
- package/install/copilot.mjs +16 -14
- package/install/templates/copilot-instructions.md +3 -3
- package/package.json +1 -1
- package/pipeline/commands/{multi-agent.md → multi-agent/SKILL.md} +39 -39
- package/pipeline/commands/multi-agent/{analysis.md → analysis/SKILL.md} +18 -18
- package/pipeline/commands/multi-agent/{analysis-resolve.md → analysis-resolve/SKILL.md} +4 -4
- package/pipeline/commands/multi-agent/{autopilot.md → autopilot/SKILL.md} +4 -4
- package/pipeline/commands/multi-agent/{build-optimize.md → build-optimize/SKILL.md} +1 -1
- package/pipeline/commands/multi-agent/{channels.md → channels/SKILL.md} +12 -12
- package/pipeline/commands/multi-agent/{dev.md → dev/SKILL.md} +4 -4
- package/pipeline/commands/multi-agent/{dev-autopilot.md → dev-autopilot/SKILL.md} +4 -4
- package/pipeline/commands/multi-agent/{dev-local.md → dev-local/SKILL.md} +5 -5
- package/pipeline/commands/multi-agent/{dev-local-autopilot.md → dev-local-autopilot/SKILL.md} +4 -4
- package/pipeline/commands/multi-agent/{finish.md → finish/SKILL.md} +6 -6
- package/pipeline/commands/multi-agent/{generate.md → generate/SKILL.md} +3 -3
- package/pipeline/commands/multi-agent/{help.md → help/SKILL.md} +4 -4
- package/pipeline/commands/multi-agent/{local.md → local/SKILL.md} +5 -5
- package/pipeline/commands/multi-agent/{local-autopilot.md → local-autopilot/SKILL.md} +5 -5
- package/pipeline/commands/multi-agent/{manual-test.md → manual-test/SKILL.md} +1 -1
- package/pipeline/commands/multi-agent/refactor/SKILL.md +257 -0
- package/pipeline/commands/multi-agent/{resume.md → resume/SKILL.md} +1 -1
- package/pipeline/commands/multi-agent/{review.md → review/SKILL.md} +5 -5
- package/pipeline/commands/multi-agent/{setup.md → setup/SKILL.md} +1 -1
- package/pipeline/commands/multi-agent/{sync.md → sync/SKILL.md} +20 -58
- package/pipeline/{commands/multi-agent → multi-agent-refs}/_account-picker.md +2 -2
- package/pipeline/{commands/multi-agent → multi-agent-refs}/_dev-context.md +2 -2
- package/pipeline/{commands/multi-agent → multi-agent-refs}/_repo-picker.md +2 -2
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/android-guide.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/jira.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/wiki.md +7 -7
- package/pipeline/multi-agent-refs/component-dispatch.md +92 -0
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/cross-cli-contract.md +10 -77
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/verify-by-test.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/generate-issue.md +2 -2
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/issue-jira-triad.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/keychain.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/log-format.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/modes.md +2 -2
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/operations.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-0-init.md +10 -10
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-1-analysis.md +6 -6
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-2-planning.md +3 -3
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-3-dev.md +10 -10
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-4-review.md +8 -8
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-5-test.md +3 -3
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-6-commit.md +4 -4
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases/phase-7-report.md +6 -6
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/phases.md +12 -12
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/progress-contract.md +4 -4
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/swiftui-guide.md +1 -1
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/tracker-contract.md +3 -3
- package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/wiki-capture.md +4 -4
- package/pipeline/preferences-template.json +17 -1
- package/pipeline/rules/figma-pipeline.md +2 -2
- package/pipeline/schemas/prefs.schema.json +0 -34
- package/pipeline/scripts/README.md +1 -3
- package/pipeline/scripts/fixtures/install-layout.tsv +6 -5
- package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
- package/pipeline/scripts/phase-banner.sh +2 -2
- package/pipeline/scripts/review-scope.mjs +94 -0
- package/pipeline/scripts/scan-agent-config.sh +2 -2
- package/pipeline/scripts/smoke-agent-log-cost.sh +1 -1
- package/pipeline/scripts/smoke-agent-model-routing.sh +4 -4
- package/pipeline/scripts/smoke-autopilot-circuit-breaker.sh +2 -2
- package/pipeline/scripts/smoke-channels-approval-gate.sh +2 -2
- package/pipeline/scripts/smoke-channels-flow.sh +5 -5
- package/pipeline/scripts/smoke-clarify.sh +1 -1
- package/pipeline/scripts/smoke-commands-skills-parity.sh +3 -3
- package/pipeline/scripts/smoke-community-gates.sh +1 -1
- package/pipeline/scripts/smoke-compliance-skills.sh +2 -2
- package/pipeline/scripts/smoke-cost-summary.sh +1 -1
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +17 -43
- package/pipeline/scripts/smoke-cross-phase-cohesion.sh +1 -1
- package/pipeline/scripts/smoke-dev-critic.sh +1 -1
- package/pipeline/scripts/smoke-diff-explain.sh +1 -1
- package/pipeline/scripts/smoke-diff-risk.sh +1 -1
- package/pipeline/scripts/smoke-evidence-gate.sh +1 -1
- package/pipeline/scripts/smoke-figma-dispatch.sh +46 -57
- package/pipeline/scripts/smoke-gate-hooks.sh +1 -1
- package/pipeline/scripts/smoke-generate-issue.sh +8 -8
- package/pipeline/scripts/smoke-handoff-contract.sh +3 -3
- package/pipeline/scripts/smoke-identity-isolation.sh +2 -2
- package/pipeline/scripts/smoke-intent-guard.sh +1 -1
- package/pipeline/scripts/smoke-issue-comment-template.sh +2 -2
- package/pipeline/scripts/smoke-issue-jira-triad.sh +4 -4
- package/pipeline/scripts/smoke-language-axis.sh +6 -6
- package/pipeline/scripts/smoke-learnings-ledger.sh +3 -3
- package/pipeline/scripts/smoke-mode-dispatch-drift.sh +16 -16
- package/pipeline/scripts/smoke-model-fallback.sh +3 -3
- package/pipeline/scripts/smoke-multi-repo-integration.sh +2 -2
- package/pipeline/scripts/smoke-multi-repo-worktree.sh +1 -1
- package/pipeline/scripts/smoke-no-token-prompt.sh +5 -5
- package/pipeline/scripts/smoke-phase-0-multi-repo.sh +1 -1
- package/pipeline/scripts/smoke-phase-6-multi.sh +1 -1
- package/pipeline/scripts/smoke-phase4-gates.sh +45 -0
- package/pipeline/scripts/smoke-plan-approval-gate.sh +5 -5
- package/pipeline/scripts/smoke-plan-todos.sh +3 -3
- package/pipeline/scripts/smoke-pr-review-actions.sh +3 -3
- package/pipeline/scripts/smoke-prefs-language.sh +1 -1
- package/pipeline/scripts/smoke-progress-contract.sh +2 -2
- package/pipeline/scripts/smoke-push-retry.sh +1 -1
- package/pipeline/scripts/smoke-repo-map.sh +2 -2
- package/pipeline/scripts/smoke-shadow-git.sh +1 -1
- package/pipeline/scripts/smoke-skill-authoring.sh +4 -9
- package/pipeline/scripts/smoke-tasklist-ordering.sh +10 -10
- package/pipeline/scripts/smoke-test-gap.sh +1 -1
- package/pipeline/scripts/smoke-token-budget.sh +1 -1
- package/pipeline/scripts/smoke-token-preflight.sh +2 -2
- package/pipeline/scripts/smoke-tracker-contract.sh +13 -13
- package/pipeline/scripts/smoke-tracker-tokens-invocation.sh +5 -5
- package/pipeline/scripts/smoke-triage-memory.sh +2 -2
- package/pipeline/scripts/smoke-update-check.sh +1 -1
- package/pipeline/scripts/smoke-url-enrichment.sh +2 -2
- package/pipeline/scripts/smoke-validator-gates.sh +1 -1
- package/pipeline/scripts/smoke-verify-by-test.sh +3 -3
- package/pipeline/scripts/smoke-wiki-integration.sh +9 -33
- package/pipeline/scripts/smoke-work-summary.sh +1 -1
- package/pipeline/scripts/smoke-worktree-path-convention.sh +4 -4
- package/pipeline/scripts/test-integrity-gate.mjs +83 -0
- package/pipeline/scripts/uninstall.mjs +2 -2
- package/pipeline/skills/.skill-manifest.json +40 -160
- package/pipeline/skills/.skills-index.json +3 -372
- package/pipeline/skills/shared/README.md +1 -1
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +3 -3
- package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +116 -51
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +8 -30
- package/pipeline/skills/shared/external/compose-components/SKILL.md +14 -14
- package/pipeline/skills/skills-index.md +2 -43
- package/pipeline/commands/multi-agent/refactor.md +0 -188
- package/pipeline/commands/multi-agent/refs/component-dispatch.md +0 -92
- package/pipeline/scripts/smoke-existing-discovery-gate.sh +0 -71
- package/pipeline/scripts/smoke-figma-android-parity.sh +0 -148
- package/pipeline/scripts/smoke-figma-credential-store.sh +0 -105
- package/pipeline/scripts/smoke-figma-cross-cli-inventory.sh +0 -177
- package/pipeline/scripts/smoke-figma-sync.sh +0 -149
- package/pipeline/scripts/smoke-sync-delegation.sh +0 -74
- package/pipeline/skills/figma-android/README.md +0 -38
- package/pipeline/skills/figma-android/figma-component-code-connect/SKILL.md +0 -62
- package/pipeline/skills/figma-android/figma-component-implement/SKILL.md +0 -158
- package/pipeline/skills/figma-android/figma-component-test/SKILL.md +0 -120
- package/pipeline/skills/figma-android/figma-component-wiki/SKILL.md +0 -35
- package/pipeline/skills/figma-android/figma-to-component/SKILL.md +0 -124
- package/pipeline/skills/figma-common/README.md +0 -64
- package/pipeline/skills/figma-common/figma-bottom-sheets/SKILL.md +0 -152
- package/pipeline/skills/figma-common/figma-cli-iterate/SKILL.md +0 -282
- package/pipeline/skills/figma-common/figma-cli-iterate-mend/SKILL.md +0 -503
- package/pipeline/skills/figma-common/figma-cli-lean-iterate/SKILL.md +0 -288
- package/pipeline/skills/figma-common/figma-cli-skip/SKILL.md +0 -362
- package/pipeline/skills/figma-common/figma-commit/COMMON_REBASE.md +0 -206
- package/pipeline/skills/figma-common/figma-commit/REVIEW.md +0 -337
- package/pipeline/skills/figma-common/figma-commit/SKILL.md +0 -216
- package/pipeline/skills/figma-common/figma-component-confluence-sync/SKILL.md +0 -223
- package/pipeline/skills/figma-common/figma-component-start/SKILL.md +0 -251
- package/pipeline/skills/figma-common/figma-component-status-update/SKILL.md +0 -78
- package/pipeline/skills/figma-common/figma-evolve-component/SKILL.md +0 -61
- package/pipeline/skills/figma-common/figma-fix/SKILL.md +0 -321
- package/pipeline/skills/figma-common/figma-form-integration/SKILL.md +0 -542
- package/pipeline/skills/figma-common/figma-issue/SKILL.md +0 -750
- package/pipeline/skills/figma-common/figma-iterate/SKILL.md +0 -208
- package/pipeline/skills/figma-common/figma-iteration-commit/SKILL.md +0 -1020
- package/pipeline/skills/figma-common/figma-mend/SKILL.md +0 -331
- package/pipeline/skills/figma-common/figma-navigation/SKILL.md +0 -156
- package/pipeline/skills/figma-common/figma-overlays/SKILL.md +0 -142
- package/pipeline/skills/figma-common/figma-price-integration/SKILL.md +0 -398
- package/pipeline/skills/figma-common/figma-remote-mcp-auth/SKILL.md +0 -104
- package/pipeline/skills/figma-common/figma-review/SKILL.md +0 -400
- package/pipeline/skills/figma-common/figma-setup/SKILL.md +0 -514
- package/pipeline/skills/figma-common/figma-setup/scripts/fetch-mcp-token.py +0 -592
- package/pipeline/skills/figma-common/figma-skip/SKILL.md +0 -129
- package/pipeline/skills/figma-common/figma-ui-patterns/SKILL.md +0 -105
- package/pipeline/skills/figma-common/figma-ui-patterns/patterns/animated-gradient-border.md +0 -116
- package/pipeline/skills/figma-common/figma-utility/SKILL.md +0 -274
- package/pipeline/skills/figma-common/figma-utility/scripts/figma-utility.py +0 -808
- package/pipeline/skills/figma-common/figma-validate/SKILL.md +0 -633
- package/pipeline/skills/figma-common/performance-iteration-commit-all/SKILL.md +0 -716
- package/pipeline/skills/figma-common/performance-review-next/SKILL.md +0 -238
- package/pipeline/skills/figma-common/performance-start/SKILL.md +0 -430
- package/pipeline/skills/figma-common/performance-swiftui/SKILL.md +0 -706
- package/pipeline/skills/figma-common/performance-tour/SKILL.md +0 -423
- package/pipeline/skills/figma-ios/REVIEW_CHECKLIST.md +0 -67
- package/pipeline/skills/figma-ios/figma-component-code-connect/SKILL.md +0 -178
- package/pipeline/skills/figma-ios/figma-component-implement/SKILL.md +0 -184
- package/pipeline/skills/figma-ios/figma-component-test/SKILL.md +0 -219
- package/pipeline/skills/figma-ios/figma-component-wiki/SKILL.md +0 -274
- package/pipeline/skills/figma-ios/figma-to-component/SKILL.md +0 -416
- package/pipeline/skills/figma-ios/figma-to-component/halt-return-protocol.md +0 -57
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-0-init.md +0 -307
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1-gathering.md +0 -119
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-1.5-existing-discovery.md +0 -174
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2-orchestrator.md +0 -333
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2a-testing-identifiers.md +0 -368
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2b-localization.md +0 -393
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2c-accessibility.md +0 -617
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-2d-analytics.md +0 -352
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3-orchestrator.md +0 -337
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3a-location.md +0 -206
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3b-tokens.md +0 -235
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3c-nested.md +0 -214
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3d-patterns.md +0 -902
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3e-assets.md +0 -156
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3f-utilities.md +0 -175
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3g-property-coverage.md +0 -176
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-3h-variant-config.md +0 -333
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4-orchestrator.md +0 -412
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4a-configuration.md +0 -336
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4b-view.md +0 -705
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4c-documentation.md +0 -332
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4d-preview.md +0 -380
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-4e-modifiers.md +0 -262
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5-orchestrator.md +0 -482
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5a-viewinspector.md +0 -274
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5b-snapshot.md +0 -636
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-5c-unit.md +0 -142
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-6-code-connect.md +0 -547
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7-wiki.md +0 -39
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-confluence-generate.md +0 -659
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-7a-wiki-generate.md +0 -580
- package/pipeline/skills/figma-ios/figma-to-component/phases/phase-8-cleanup.md +0 -51
- package/pipeline/skills/figma-ios/figma-to-component/reference/accessibility.md +0 -183
- package/pipeline/skills/figma-ios/figma-to-component/reference/analytics-events.md +0 -64
- package/pipeline/skills/figma-ios/figma-to-component/reference/code-connect.md +0 -531
- package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-api.md +0 -89
- package/pipeline/skills/figma-ios/figma-to-component/reference/confluence-xhtml.md +0 -155
- package/pipeline/skills/figma-ios/figma-to-component/reference/figma-to-swiftui-effects.md +0 -196
- package/pipeline/skills/figma-ios/figma-to-component/reference/halt-return-protocol.md +0 -57
- package/pipeline/skills/figma-ios/figma-to-component/reference/localization-naming.md +0 -89
- package/pipeline/skills/figma-ios/figma-to-component/reference/macros.md +0 -227
- package/pipeline/skills/figma-ios/figma-to-component/reference/missing-tokens.md +0 -157
- package/pipeline/skills/figma-ios/figma-to-component/reference/orchestrator-discipline.md +0 -90
- package/pipeline/skills/figma-ios/figma-to-component/reference/registry.md +0 -116
- package/pipeline/skills/figma-ios/figma-to-component/reference/remote-mcp-script.md +0 -153
- package/pipeline/skills/figma-ios/figma-to-component/reference/rest-api-script.md +0 -130
- package/pipeline/skills/figma-ios/figma-to-component/reference/scripts-inventory.md +0 -218
- package/pipeline/skills/figma-ios/figma-to-component/reference/snapshot-testing.md +0 -188
- package/pipeline/skills/figma-ios/figma-to-component/reference/subcomponent-graph.md +0 -93
- package/pipeline/skills/figma-ios/figma-to-component/reference/testing-identifiers-naming.md +0 -98
- package/pipeline/skills/figma-ios/figma-to-component/reference/tools.md +0 -261
- package/pipeline/skills/figma-ios/figma-to-component/reference/viewinspector.md +0 -147
- package/pipeline/skills/figma-ios/figma-to-component/reference/wiki-to-confluence-mapping.md +0 -182
- package/pipeline/skills/figma-ios/figma-to-component/scripts/apply-author-login-map.py +0 -185
- package/pipeline/skills/figma-ios/figma-to-component/scripts/backfill-status.py +0 -609
- package/pipeline/skills/figma-ios/figma-to-component/scripts/build-author-registry.py +0 -332
- package/pipeline/skills/figma-ios/figma-to-component/scripts/bulk-sync-issues.py +0 -261
- package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-data-gather.py +0 -184
- package/pipeline/skills/figma-ios/figma-to-component/scripts/code-connect-publish.sh +0 -188
- package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status-upload.py +0 -768
- package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-component-status.py +0 -191
- package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-data-gather.py +0 -420
- package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-page-ids.example.json +0 -9
- package/pipeline/skills/figma-ios/figma-to-component/scripts/confluence-publish.py +0 -336
- package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-subcomponent-graph.py +0 -391
- package/pipeline/skills/figma-ios/figma-to-component/scripts/figma-update.py +0 -292
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/__init__.py +0 -1
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/issue_sync_propagate.py +0 -93
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/registry_writer.py +0 -299
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_backfill_status.py +0 -343
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update.py +0 -206
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_figma_update_http.py +0 -149
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_phase_clis.py +0 -281
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_registry_writer.py +0 -332
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_issue.py +0 -176
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_skill_figma_review.py +0 -98
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue.py +0 -298
- package/pipeline/skills/figma-ios/figma-to-component/scripts/lib/test_update_issue_gh.py +0 -195
- package/pipeline/skills/figma-ios/figma-to-component/scripts/phase1-gather.py +0 -1298
- package/pipeline/skills/figma-ios/figma-to-component/scripts/phase2-finalize.py +0 -228
- package/pipeline/skills/figma-ios/figma-to-component/scripts/phase3-scripts.py +0 -1089
- package/pipeline/skills/figma-ios/figma-to-component/scripts/phase4-finalize.py +0 -141
- package/pipeline/skills/figma-ios/figma-to-component/scripts/phase5-finalize.py +0 -106
- package/pipeline/skills/figma-ios/figma-to-component/scripts/phase6-finalize.py +0 -162
- package/pipeline/skills/figma-ios/figma-to-component/scripts/phase7-finalize.py +0 -105
- package/pipeline/skills/figma-ios/figma-to-component/scripts/register-icons-codeconnect.py +0 -179
- package/pipeline/skills/figma-ios/figma-to-component/scripts/remote-mcp-fetch.py +0 -260
- package/pipeline/skills/figma-ios/figma-to-component/scripts/resolve-author-logins.py +0 -260
- package/pipeline/skills/figma-ios/figma-to-component/scripts/run-uicomponents-tests.sh +0 -86
- package/pipeline/skills/figma-ios/figma-to-component/scripts/sidebar-generator.py +0 -321
- package/pipeline/skills/figma-ios/figma-to-component/scripts/update-issue-from-registry.py +0 -1470
- package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase4.sh +0 -176
- package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase6.sh +0 -147
- package/pipeline/skills/figma-ios/figma-to-component/scripts/validate-phase7a.py +0 -629
- /package/pipeline/commands/multi-agent/{delete.md → delete/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{diff-explain.md → diff-explain/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{garbage-collect.md → garbage-collect/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{issue.md → issue/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{jira.md → jira/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{kill.md → kill/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{language.md → language/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{log.md → log/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{prune-logs.md → prune-logs/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{purge.md → purge/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{scan.md → scan/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{search.md → search/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{stack.md → stack/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{status.md → status/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{test.md → test/SKILL.md} +0 -0
- /package/pipeline/commands/multi-agent/{update.md → update/SKILL.md} +0 -0
- /package/pipeline/{commands/multi-agent → multi-agent-refs}/_input-parser.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/analysis-template.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/audit-guide.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/backend-guide.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/confluence.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/issue-comment.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr-review-actions.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/channels/pr.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/conventions-defaults.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/autopilot-circuit-breaker.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/dev-critic.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/external-context-injection.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/model-fallback.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/plan-todos.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/prior-fix-detection.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/repo-map.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/features/shadow-git.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/frontend-guide.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/knowledge.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/multi-repo-integration-build.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/picker-contract.md +0 -0
- /package/pipeline/{commands/multi-agent/refs → multi-agent-refs}/rules.md +0 -0
|
@@ -1,609 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""backfill-status.py - populate status blocks in existing registry files.
|
|
3
|
-
|
|
4
|
-
Walks every JSON in the registry directory and, for each component,
|
|
5
|
-
infers the initial `status.ios.*` block from filesystem signals:
|
|
6
|
-
|
|
7
|
-
- status.ios.implemented:
|
|
8
|
-
True if a Swift source file with the component's iOS name exists
|
|
9
|
-
anywhere under the uicomponents Sources tree. When set, version
|
|
10
|
-
starts at 1.
|
|
11
|
-
|
|
12
|
-
- status.ios.codeConnect:
|
|
13
|
-
Mirrors the legacy top-level `codeConnect.ios` field. Only set if
|
|
14
|
-
the legacy value was True. Recorded against the current
|
|
15
|
-
impl.version - so if impl was just set to 1 in this same run,
|
|
16
|
-
codeConnect lands green (against=1), not yellow.
|
|
17
|
-
|
|
18
|
-
- status.ios.tested and status.ios.wiki:
|
|
19
|
-
NOT backfilled in this pass. These signals live in separate repos
|
|
20
|
-
and trees, and the heuristics are fragile. They'll naturally
|
|
21
|
-
populate on the next pipeline run of each component.
|
|
22
|
-
|
|
23
|
-
- status.android.*:
|
|
24
|
-
NOT backfilled. Android source tree and component index are
|
|
25
|
-
out-of-scope for tonight. Future enhancement.
|
|
26
|
-
|
|
27
|
-
The legacy top-level `codeConnect.{ios,android}` field is left intact.
|
|
28
|
-
set_flag's built-in mirror keeps the two representations in sync going
|
|
29
|
-
forward, and the backfill never explicitly downgrades anything.
|
|
30
|
-
|
|
31
|
-
Usage:
|
|
32
|
-
# See what would change - no writes
|
|
33
|
-
python3 backfill-status.py \\
|
|
34
|
-
--registry-dir /path/to/Shared/Figma/Components \\
|
|
35
|
-
--sources-dir /path/to/uicomponents/Sources \\
|
|
36
|
-
--dry-run
|
|
37
|
-
|
|
38
|
-
# Smoke test on 5 entries
|
|
39
|
-
python3 backfill-status.py \\
|
|
40
|
-
--registry-dir ... --sources-dir ... \\
|
|
41
|
-
--dry-run --limit 5
|
|
42
|
-
|
|
43
|
-
# Real backfill (only run after you've reviewed a --dry-run)
|
|
44
|
-
python3 backfill-status.py \\
|
|
45
|
-
--registry-dir ... --sources-dir ...
|
|
46
|
-
|
|
47
|
-
Exit codes:
|
|
48
|
-
0 - Success (full walk completed)
|
|
49
|
-
1 - Error (bad paths, read/write failure)
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
import argparse
|
|
53
|
-
import json
|
|
54
|
-
import subprocess
|
|
55
|
-
import sys
|
|
56
|
-
from collections import Counter
|
|
57
|
-
from pathlib import Path
|
|
58
|
-
from typing import Dict, List, Optional, Set
|
|
59
|
-
|
|
60
|
-
sys.path.insert(0, str(Path(__file__).parent))
|
|
61
|
-
from lib.registry_writer import set_flag, set_implemented # noqa: E402
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def find_repo_root() -> Path:
|
|
65
|
-
p = Path.cwd()
|
|
66
|
-
while p != p.parent:
|
|
67
|
-
if (p / ".git").exists():
|
|
68
|
-
return p
|
|
69
|
-
p = p.parent
|
|
70
|
-
return Path.cwd()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def default_registry_dir() -> Path:
|
|
74
|
-
return (
|
|
75
|
-
find_repo_root()
|
|
76
|
-
/ "{repos.packagesContainer}"
|
|
77
|
-
/ "Packages"
|
|
78
|
-
/ "{project.slug}-common"
|
|
79
|
-
/ "Shared"
|
|
80
|
-
/ "Figma"
|
|
81
|
-
/ "Components"
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def default_sources_dir() -> Path:
|
|
86
|
-
return (
|
|
87
|
-
find_repo_root()
|
|
88
|
-
/ "{repos.packagesContainer}"
|
|
89
|
-
/ "Packages"
|
|
90
|
-
/ "{project.slug}-components"
|
|
91
|
-
/ "Sources"
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def default_tests_dir() -> Path:
|
|
96
|
-
return (
|
|
97
|
-
find_repo_root()
|
|
98
|
-
/ "{repos.packagesContainer}"
|
|
99
|
-
/ "Packages"
|
|
100
|
-
/ "{project.slug}-components"
|
|
101
|
-
/ "Tests"
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def default_wiki_dir() -> Path:
|
|
106
|
-
return (
|
|
107
|
-
find_repo_root()
|
|
108
|
-
/ "{repos.packagesContainer}"
|
|
109
|
-
/ "Packages"
|
|
110
|
-
/ "{project.slug}-wiki"
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def default_uicomponents_repo_dir() -> Path:
|
|
115
|
-
return (
|
|
116
|
-
find_repo_root()
|
|
117
|
-
/ "{repos.packagesContainer}"
|
|
118
|
-
/ "Packages"
|
|
119
|
-
/ "{project.slug}-components"
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
# --------------------------------------------------------------------
|
|
124
|
-
# Source-tree indexing (separate from backfill for testability)
|
|
125
|
-
# --------------------------------------------------------------------
|
|
126
|
-
|
|
127
|
-
def build_swift_file_index(sources_dir: Path) -> Dict[str, Path]:
|
|
128
|
-
"""Walk the Sources tree and return { base_name: first_matching_path }.
|
|
129
|
-
|
|
130
|
-
Base name is the filename without the .swift extension.
|
|
131
|
-
Only the first match is kept if the same name appears twice
|
|
132
|
-
(unlikely in a well-organized source tree).
|
|
133
|
-
"""
|
|
134
|
-
index: Dict[str, Path] = {}
|
|
135
|
-
if not sources_dir.exists():
|
|
136
|
-
return index
|
|
137
|
-
|
|
138
|
-
for swift in sources_dir.rglob("*.swift"):
|
|
139
|
-
base = swift.stem
|
|
140
|
-
if base not in index:
|
|
141
|
-
index[base] = swift
|
|
142
|
-
return index
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
# Test-file name suffixes we recognize as "this component has tests".
|
|
146
|
-
TEST_SUFFIXES = (
|
|
147
|
-
"SnapshotTests",
|
|
148
|
-
"Tests",
|
|
149
|
-
"XCTests",
|
|
150
|
-
"ViewInspectorTests",
|
|
151
|
-
"UnitTests",
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def build_test_file_index(tests_dir: Path) -> Dict[str, List[Path]]:
|
|
156
|
-
"""Walk the Tests tree and return { ComponentName: [test_path, ...] }.
|
|
157
|
-
|
|
158
|
-
For each `{ComponentName}{suffix}.swift` we find, strip the suffix
|
|
159
|
-
and index under the stripped component name. A component is
|
|
160
|
-
considered tested if at least one test file maps to it.
|
|
161
|
-
"""
|
|
162
|
-
index: Dict[str, List[Path]] = {}
|
|
163
|
-
if not tests_dir.exists():
|
|
164
|
-
return index
|
|
165
|
-
|
|
166
|
-
for swift in tests_dir.rglob("*.swift"):
|
|
167
|
-
stem = swift.stem
|
|
168
|
-
for suffix in TEST_SUFFIXES:
|
|
169
|
-
if stem.endswith(suffix) and len(stem) > len(suffix):
|
|
170
|
-
comp = stem[: -len(suffix)]
|
|
171
|
-
index.setdefault(comp, []).append(swift)
|
|
172
|
-
break
|
|
173
|
-
return index
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def build_wiki_index(wiki_dir: Path) -> Dict[str, Path]:
|
|
177
|
-
"""Walk the wiki tree and return { ComponentName: path_to_md_file }.
|
|
178
|
-
|
|
179
|
-
Matches `**/{ComponentName}/{ComponentName}.md` (the canonical
|
|
180
|
-
per-component layout used in the uicomponents-wiki submodule).
|
|
181
|
-
Also accepts `**/{ComponentName}.md` as a fallback for flat
|
|
182
|
-
structures.
|
|
183
|
-
"""
|
|
184
|
-
index: Dict[str, Path] = {}
|
|
185
|
-
if not wiki_dir.exists():
|
|
186
|
-
return index
|
|
187
|
-
|
|
188
|
-
# Prefer per-component directories first
|
|
189
|
-
for md in wiki_dir.rglob("*.md"):
|
|
190
|
-
stem = md.stem
|
|
191
|
-
parent_name = md.parent.name
|
|
192
|
-
if parent_name == stem:
|
|
193
|
-
# {Component}/{Component}.md - canonical
|
|
194
|
-
index.setdefault(stem, md)
|
|
195
|
-
elif stem not in index:
|
|
196
|
-
# {Component}.md at any depth - fallback
|
|
197
|
-
index[stem] = md
|
|
198
|
-
return index
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def detect_primary_author(
|
|
202
|
-
source_file: Path,
|
|
203
|
-
repo_root: Path,
|
|
204
|
-
) -> Optional[str]:
|
|
205
|
-
"""Return the git author (most commits on `source_file`) inside `repo_root`.
|
|
206
|
-
|
|
207
|
-
Runs `git -C repo_root log --format=%an -- <rel_path>`, counts
|
|
208
|
-
unique authors, picks the one with the most commits.
|
|
209
|
-
|
|
210
|
-
Returns None if:
|
|
211
|
-
- source file doesn't exist
|
|
212
|
-
- git command fails
|
|
213
|
-
- no commits touch the file
|
|
214
|
-
- author name is empty
|
|
215
|
-
"""
|
|
216
|
-
if not source_file.exists():
|
|
217
|
-
return None
|
|
218
|
-
try:
|
|
219
|
-
rel = source_file.relative_to(repo_root)
|
|
220
|
-
except ValueError:
|
|
221
|
-
rel = source_file
|
|
222
|
-
try:
|
|
223
|
-
r = subprocess.run(
|
|
224
|
-
["git", "-C", str(repo_root), "log", "--format=%an", "--", str(rel)],
|
|
225
|
-
capture_output=True,
|
|
226
|
-
text=True,
|
|
227
|
-
check=False,
|
|
228
|
-
timeout=10,
|
|
229
|
-
)
|
|
230
|
-
except (subprocess.SubprocessError, FileNotFoundError):
|
|
231
|
-
return None
|
|
232
|
-
if r.returncode != 0:
|
|
233
|
-
return None
|
|
234
|
-
lines = [line.strip() for line in r.stdout.splitlines() if line.strip()]
|
|
235
|
-
if not lines:
|
|
236
|
-
return None
|
|
237
|
-
counter = Counter(lines)
|
|
238
|
-
author, _ = counter.most_common(1)[0]
|
|
239
|
-
return author or None
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# --------------------------------------------------------------------
|
|
243
|
-
# Per-entry decision logic (pure, testable)
|
|
244
|
-
# --------------------------------------------------------------------
|
|
245
|
-
|
|
246
|
-
def _safe_dict(value) -> dict:
|
|
247
|
-
"""Return value if it's a dict, otherwise an empty dict.
|
|
248
|
-
|
|
249
|
-
Real registry data in the wild contains a small number of legacy
|
|
250
|
-
entries where fields like `status` are strings (e.g. "implemented")
|
|
251
|
-
or `componentName` is a bare string. This helper lets the decision
|
|
252
|
-
logic treat those the same as missing/empty without raising.
|
|
253
|
-
"""
|
|
254
|
-
return value if isinstance(value, dict) else {}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
def _component_name_ios(raw) -> Optional[str]:
|
|
258
|
-
"""Handle both shapes: {"ios": "X", "android": "X"} and bare "X"."""
|
|
259
|
-
if isinstance(raw, dict):
|
|
260
|
-
return raw.get("ios")
|
|
261
|
-
if isinstance(raw, str) and raw:
|
|
262
|
-
return raw
|
|
263
|
-
return None
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
def decide_backfill(
|
|
267
|
-
entry: dict,
|
|
268
|
-
swift_index: Dict[str, Path],
|
|
269
|
-
test_index: Optional[Dict[str, List[Path]]] = None,
|
|
270
|
-
wiki_index: Optional[Dict[str, Path]] = None,
|
|
271
|
-
) -> dict:
|
|
272
|
-
"""Decide what the backfill should do for one registry entry.
|
|
273
|
-
|
|
274
|
-
Pure function - no I/O. Returns a dict describing the intended
|
|
275
|
-
action per flag, used by both dry-run and real-write paths.
|
|
276
|
-
|
|
277
|
-
test_index and wiki_index are optional for backward compat - when
|
|
278
|
-
None, tested/wiki detection is skipped and only implemented/cc are
|
|
279
|
-
considered (original Step 5 behavior).
|
|
280
|
-
|
|
281
|
-
Returned shape (added fields are marked NEW):
|
|
282
|
-
{
|
|
283
|
-
"node_id": str,
|
|
284
|
-
"component_name_ios": Optional[str],
|
|
285
|
-
"has_status_block": bool,
|
|
286
|
-
"impl_action": ...,
|
|
287
|
-
"codeconnect_action": ...,
|
|
288
|
-
"tested_action": ..., # NEW - "set" | "skip_*"
|
|
289
|
-
"wiki_action": ..., # NEW - "set" | "skip_*"
|
|
290
|
-
"swift_path": Optional[str],
|
|
291
|
-
"test_paths": List[str], # NEW - 0+ paths that match the component
|
|
292
|
-
"wiki_path": Optional[str], # NEW - the detected wiki .md file
|
|
293
|
-
}
|
|
294
|
-
"""
|
|
295
|
-
node_id = entry.get("nodeId")
|
|
296
|
-
component_name = _component_name_ios(entry.get("componentName"))
|
|
297
|
-
|
|
298
|
-
# Legacy shape: `status` was a bare string like "implemented". Leave
|
|
299
|
-
# these for manual migration - do not overwrite with the new block.
|
|
300
|
-
raw_status = entry.get("status")
|
|
301
|
-
if isinstance(raw_status, str):
|
|
302
|
-
return {
|
|
303
|
-
"node_id": node_id,
|
|
304
|
-
"component_name_ios": component_name,
|
|
305
|
-
"has_status_block": True,
|
|
306
|
-
"impl_action": "skip_legacy_status_string",
|
|
307
|
-
"codeconnect_action": "skip_legacy_status_string",
|
|
308
|
-
"tested_action": "skip_legacy_status_string",
|
|
309
|
-
"wiki_action": "skip_legacy_status_string",
|
|
310
|
-
"swift_path": None,
|
|
311
|
-
"test_paths": [],
|
|
312
|
-
"wiki_path": None,
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
status_block = _safe_dict(raw_status)
|
|
316
|
-
ios_status = _safe_dict(status_block.get("ios"))
|
|
317
|
-
implemented_block = _safe_dict(ios_status.get("implemented"))
|
|
318
|
-
has_status = bool(implemented_block.get("value"))
|
|
319
|
-
|
|
320
|
-
legacy_cc_ios = bool(_safe_dict(entry.get("codeConnect")).get("ios"))
|
|
321
|
-
skip = bool(entry.get("skip"))
|
|
322
|
-
|
|
323
|
-
result: dict = {
|
|
324
|
-
"node_id": node_id,
|
|
325
|
-
"component_name_ios": component_name,
|
|
326
|
-
"has_status_block": has_status,
|
|
327
|
-
"impl_action": None,
|
|
328
|
-
"codeconnect_action": None,
|
|
329
|
-
"tested_action": None,
|
|
330
|
-
"wiki_action": None,
|
|
331
|
-
"swift_path": None,
|
|
332
|
-
"test_paths": [],
|
|
333
|
-
"wiki_path": None,
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
# Skip entries marked skip=true
|
|
337
|
-
if skip:
|
|
338
|
-
for k in ("impl_action", "codeconnect_action", "tested_action", "wiki_action"):
|
|
339
|
-
result[k] = "skip_marked_skip"
|
|
340
|
-
return result
|
|
341
|
-
|
|
342
|
-
if not component_name:
|
|
343
|
-
for k in ("impl_action", "codeconnect_action", "tested_action", "wiki_action"):
|
|
344
|
-
result[k] = "skip_no_name" if k == "impl_action" else "skip_no_impl"
|
|
345
|
-
return result
|
|
346
|
-
|
|
347
|
-
# tested / wiki can be set independently of impl (they're orthogonal
|
|
348
|
-
# signals) but we compute them regardless so the decision dict is
|
|
349
|
-
# fully populated for the report.
|
|
350
|
-
if test_index is not None:
|
|
351
|
-
test_paths = test_index.get(component_name, [])
|
|
352
|
-
if test_paths:
|
|
353
|
-
result["test_paths"] = [str(p) for p in test_paths]
|
|
354
|
-
if wiki_index is not None:
|
|
355
|
-
wiki_path = wiki_index.get(component_name)
|
|
356
|
-
if wiki_path:
|
|
357
|
-
result["wiki_path"] = str(wiki_path)
|
|
358
|
-
|
|
359
|
-
# If the new status block already has implemented.value=true, don't
|
|
360
|
-
# overwrite the impl/cc flags. tested/wiki can still be added if
|
|
361
|
-
# they haven't been populated yet (backfill is additive for those).
|
|
362
|
-
if has_status:
|
|
363
|
-
result["impl_action"] = "skip_existing_status"
|
|
364
|
-
result["codeconnect_action"] = "skip_existing_status"
|
|
365
|
-
# Populate swift_path even when skipping impl - author detection
|
|
366
|
-
# needs it, and we want to be able to fill in implementedBy for
|
|
367
|
-
# components that were backfilled before author detection existed.
|
|
368
|
-
swift_path = swift_index.get(component_name) if component_name else None
|
|
369
|
-
if swift_path:
|
|
370
|
-
result["swift_path"] = str(swift_path)
|
|
371
|
-
# tested/wiki: still set them if not already set
|
|
372
|
-
tested_set = bool(_safe_dict(ios_status.get("tested")).get("value"))
|
|
373
|
-
wiki_set = bool(_safe_dict(ios_status.get("wiki")).get("value"))
|
|
374
|
-
if result["test_paths"] and not tested_set:
|
|
375
|
-
result["tested_action"] = "set"
|
|
376
|
-
else:
|
|
377
|
-
result["tested_action"] = "skip_existing_status" if tested_set else "skip_no_tests"
|
|
378
|
-
if result["wiki_path"] and not wiki_set:
|
|
379
|
-
result["wiki_action"] = "set"
|
|
380
|
-
else:
|
|
381
|
-
result["wiki_action"] = "skip_existing_status" if wiki_set else "skip_no_wiki"
|
|
382
|
-
return result
|
|
383
|
-
|
|
384
|
-
# Fresh entry - check swift file for implementation
|
|
385
|
-
swift_path = swift_index.get(component_name)
|
|
386
|
-
if not swift_path:
|
|
387
|
-
result["impl_action"] = "skip_no_swift"
|
|
388
|
-
result["codeconnect_action"] = "skip_no_impl"
|
|
389
|
-
result["tested_action"] = "skip_no_impl"
|
|
390
|
-
result["wiki_action"] = "skip_no_impl"
|
|
391
|
-
return result
|
|
392
|
-
|
|
393
|
-
result["impl_action"] = "set"
|
|
394
|
-
result["swift_path"] = str(swift_path)
|
|
395
|
-
result["codeconnect_action"] = "set" if legacy_cc_ios else "skip_legacy_false"
|
|
396
|
-
result["tested_action"] = "set" if result["test_paths"] else "skip_no_tests"
|
|
397
|
-
result["wiki_action"] = "set" if result["wiki_path"] else "skip_no_wiki"
|
|
398
|
-
|
|
399
|
-
return result
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
# --------------------------------------------------------------------
|
|
403
|
-
# Backfill execution
|
|
404
|
-
# --------------------------------------------------------------------
|
|
405
|
-
|
|
406
|
-
def apply_decision(
|
|
407
|
-
registry_dir: Path,
|
|
408
|
-
decision: dict,
|
|
409
|
-
uicomponents_repo: Optional[Path] = None,
|
|
410
|
-
) -> None:
|
|
411
|
-
"""Execute the decision (skip if action is 'skip_*').
|
|
412
|
-
|
|
413
|
-
Writes are atomic per flag - a crash between writes leaves a
|
|
414
|
-
partially-backfilled entry, recoverable on re-run. Order:
|
|
415
|
-
1. set_implemented (establishes version=1)
|
|
416
|
-
2. set_implemented_by (author)
|
|
417
|
-
3. set_flag codeConnect (if legacy was true)
|
|
418
|
-
4. set_flag tested (if tests detected)
|
|
419
|
-
5. set_flag wiki (if wiki detected)
|
|
420
|
-
"""
|
|
421
|
-
from lib.registry_writer import set_implemented_by # local to avoid circular
|
|
422
|
-
|
|
423
|
-
node_id = decision["node_id"]
|
|
424
|
-
|
|
425
|
-
if decision.get("impl_action") == "set":
|
|
426
|
-
set_implemented(
|
|
427
|
-
registry_dir=registry_dir,
|
|
428
|
-
node_id=node_id,
|
|
429
|
-
platform="ios",
|
|
430
|
-
updater="backfill-status",
|
|
431
|
-
source_file=None,
|
|
432
|
-
)
|
|
433
|
-
|
|
434
|
-
# Author detection - only meaningful when we actually set impl OR
|
|
435
|
-
# impl was already set (so the registry entry exists and we just
|
|
436
|
-
# want to populate the missing field).
|
|
437
|
-
if uicomponents_repo and decision.get("swift_path"):
|
|
438
|
-
swift_file = Path(decision["swift_path"])
|
|
439
|
-
author = detect_primary_author(swift_file, uicomponents_repo)
|
|
440
|
-
if author:
|
|
441
|
-
set_implemented_by(
|
|
442
|
-
registry_dir=registry_dir,
|
|
443
|
-
node_id=node_id,
|
|
444
|
-
platform="ios",
|
|
445
|
-
author=author,
|
|
446
|
-
updater="backfill-status",
|
|
447
|
-
)
|
|
448
|
-
decision["author"] = author
|
|
449
|
-
|
|
450
|
-
if decision.get("codeconnect_action") == "set":
|
|
451
|
-
set_flag(
|
|
452
|
-
registry_dir=registry_dir,
|
|
453
|
-
node_id=node_id,
|
|
454
|
-
platform="ios",
|
|
455
|
-
flag="codeConnect",
|
|
456
|
-
updater="backfill-status",
|
|
457
|
-
)
|
|
458
|
-
|
|
459
|
-
if decision.get("tested_action") == "set":
|
|
460
|
-
set_flag(
|
|
461
|
-
registry_dir=registry_dir,
|
|
462
|
-
node_id=node_id,
|
|
463
|
-
platform="ios",
|
|
464
|
-
flag="tested",
|
|
465
|
-
updater="backfill-status",
|
|
466
|
-
)
|
|
467
|
-
|
|
468
|
-
if decision.get("wiki_action") == "set":
|
|
469
|
-
set_flag(
|
|
470
|
-
registry_dir=registry_dir,
|
|
471
|
-
node_id=node_id,
|
|
472
|
-
platform="ios",
|
|
473
|
-
flag="wiki",
|
|
474
|
-
updater="backfill-status",
|
|
475
|
-
)
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
def run_backfill(
|
|
479
|
-
registry_dir: Path,
|
|
480
|
-
sources_dir: Path,
|
|
481
|
-
dry_run: bool,
|
|
482
|
-
limit: Optional[int] = None,
|
|
483
|
-
tests_dir: Optional[Path] = None,
|
|
484
|
-
wiki_dir: Optional[Path] = None,
|
|
485
|
-
uicomponents_repo: Optional[Path] = None,
|
|
486
|
-
) -> dict:
|
|
487
|
-
"""Top-level backfill. Returns a summary dict."""
|
|
488
|
-
swift_index = build_swift_file_index(sources_dir)
|
|
489
|
-
test_index = build_test_file_index(tests_dir) if tests_dir else {}
|
|
490
|
-
wiki_index = build_wiki_index(wiki_dir) if wiki_dir else {}
|
|
491
|
-
|
|
492
|
-
all_files = sorted(registry_dir.glob("*.json"))
|
|
493
|
-
if limit is not None:
|
|
494
|
-
all_files = all_files[:limit]
|
|
495
|
-
|
|
496
|
-
counts: Dict[str, int] = {}
|
|
497
|
-
flag_counts = {
|
|
498
|
-
"impl_set": 0,
|
|
499
|
-
"tested_set": 0,
|
|
500
|
-
"codeconnect_set": 0,
|
|
501
|
-
"wiki_set": 0,
|
|
502
|
-
"author_set": 0,
|
|
503
|
-
}
|
|
504
|
-
decisions: List[dict] = []
|
|
505
|
-
errors: List[dict] = []
|
|
506
|
-
|
|
507
|
-
for path in all_files:
|
|
508
|
-
try:
|
|
509
|
-
entry = json.loads(path.read_text(encoding="utf-8"))
|
|
510
|
-
except (json.JSONDecodeError, OSError) as e:
|
|
511
|
-
errors.append({"file": path.name, "error": f"read: {type(e).__name__}: {e}"})
|
|
512
|
-
continue
|
|
513
|
-
|
|
514
|
-
decision = decide_backfill(entry, swift_index, test_index, wiki_index)
|
|
515
|
-
decisions.append(decision)
|
|
516
|
-
|
|
517
|
-
key = f"{decision['impl_action']}/{decision['codeconnect_action']}/{decision['tested_action']}/{decision['wiki_action']}"
|
|
518
|
-
counts[key] = counts.get(key, 0) + 1
|
|
519
|
-
|
|
520
|
-
# per-flag set counts (dry-run accurate)
|
|
521
|
-
for flag_name, counter_key in (
|
|
522
|
-
("impl_action", "impl_set"),
|
|
523
|
-
("tested_action", "tested_set"),
|
|
524
|
-
("codeconnect_action", "codeconnect_set"),
|
|
525
|
-
("wiki_action", "wiki_set"),
|
|
526
|
-
):
|
|
527
|
-
if decision.get(flag_name) == "set":
|
|
528
|
-
flag_counts[counter_key] += 1
|
|
529
|
-
|
|
530
|
-
if not dry_run:
|
|
531
|
-
try:
|
|
532
|
-
apply_decision(registry_dir, decision, uicomponents_repo=uicomponents_repo)
|
|
533
|
-
if decision.get("author"):
|
|
534
|
-
flag_counts["author_set"] += 1
|
|
535
|
-
except (OSError, ValueError) as e:
|
|
536
|
-
errors.append({
|
|
537
|
-
"file": path.name,
|
|
538
|
-
"node_id": decision["node_id"],
|
|
539
|
-
"error": f"write: {type(e).__name__}: {e}",
|
|
540
|
-
})
|
|
541
|
-
|
|
542
|
-
return {
|
|
543
|
-
"status": "ok" if not errors else "partial",
|
|
544
|
-
"dry_run": dry_run,
|
|
545
|
-
"registry_dir": str(registry_dir),
|
|
546
|
-
"sources_dir": str(sources_dir),
|
|
547
|
-
"tests_dir": str(tests_dir) if tests_dir else None,
|
|
548
|
-
"wiki_dir": str(wiki_dir) if wiki_dir else None,
|
|
549
|
-
"total_files": len(all_files),
|
|
550
|
-
"swift_files_indexed": len(swift_index),
|
|
551
|
-
"test_files_indexed": len(test_index),
|
|
552
|
-
"wiki_files_indexed": len(wiki_index),
|
|
553
|
-
"flag_set_counts": flag_counts,
|
|
554
|
-
"action_counts": counts,
|
|
555
|
-
"errors": errors,
|
|
556
|
-
"sample_decisions": decisions[:5],
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
# --------------------------------------------------------------------
|
|
561
|
-
# CLI
|
|
562
|
-
# --------------------------------------------------------------------
|
|
563
|
-
|
|
564
|
-
def main() -> int:
|
|
565
|
-
parser = argparse.ArgumentParser(
|
|
566
|
-
description="Backfill status blocks in existing registry entries",
|
|
567
|
-
)
|
|
568
|
-
parser.add_argument("--registry-dir", help="Override registry path")
|
|
569
|
-
parser.add_argument("--sources-dir", help="Override uicomponents Sources path")
|
|
570
|
-
parser.add_argument("--tests-dir", help="Override uicomponents Tests path")
|
|
571
|
-
parser.add_argument("--wiki-dir", help="Override uicomponents-wiki path")
|
|
572
|
-
parser.add_argument("--uicomponents-repo", help="Override uicomponents repo root (for git-log author detection)")
|
|
573
|
-
parser.add_argument("--skip-authors", action="store_true", help="Skip git log author detection (fast mode)")
|
|
574
|
-
parser.add_argument("--dry-run", action="store_true", help="No writes, print summary only")
|
|
575
|
-
parser.add_argument("--limit", type=int, help="Process at most N registry files (smoke-test safety)")
|
|
576
|
-
args = parser.parse_args()
|
|
577
|
-
|
|
578
|
-
registry_dir = Path(args.registry_dir) if args.registry_dir else default_registry_dir()
|
|
579
|
-
sources_dir = Path(args.sources_dir) if args.sources_dir else default_sources_dir()
|
|
580
|
-
tests_dir = Path(args.tests_dir) if args.tests_dir else default_tests_dir()
|
|
581
|
-
wiki_dir = Path(args.wiki_dir) if args.wiki_dir else default_wiki_dir()
|
|
582
|
-
uicomponents_repo = None
|
|
583
|
-
if not args.skip_authors:
|
|
584
|
-
uicomponents_repo = (
|
|
585
|
-
Path(args.uicomponents_repo) if args.uicomponents_repo else default_uicomponents_repo_dir()
|
|
586
|
-
)
|
|
587
|
-
|
|
588
|
-
if not registry_dir.exists():
|
|
589
|
-
print(f"ERROR: registry directory does not exist: {registry_dir}", file=sys.stderr)
|
|
590
|
-
return 1
|
|
591
|
-
if not sources_dir.exists():
|
|
592
|
-
print(f"ERROR: sources directory does not exist: {sources_dir}", file=sys.stderr)
|
|
593
|
-
return 1
|
|
594
|
-
|
|
595
|
-
summary = run_backfill(
|
|
596
|
-
registry_dir=registry_dir,
|
|
597
|
-
sources_dir=sources_dir,
|
|
598
|
-
dry_run=args.dry_run,
|
|
599
|
-
limit=args.limit,
|
|
600
|
-
tests_dir=tests_dir,
|
|
601
|
-
wiki_dir=wiki_dir,
|
|
602
|
-
uicomponents_repo=uicomponents_repo,
|
|
603
|
-
)
|
|
604
|
-
print(json.dumps(summary, indent=2, ensure_ascii=False))
|
|
605
|
-
return 0 if summary["status"] == "ok" else 1
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
if __name__ == "__main__":
|
|
609
|
-
sys.exit(main())
|