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