@mmerterden/multi-agent-pipeline 20.2.1 → 20.3.1
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 +919 -1
- package/README.md +104 -81
- package/README.tr.md +103 -62
- package/docs/FIGMA_PIPELINE.md +35 -35
- package/docs/adr/0006-skills-core-external-split.md +1 -1
- package/docs/adr/0007-multi-tool-adapter-framework.md +6 -0
- package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +7 -0
- package/docs/architecture.md +50 -14
- package/docs/best-practices.md +1 -1
- package/docs/ecosystem.md +56 -32
- package/docs/facts.json +10 -10
- package/docs/features.md +97 -5
- package/docs/recovery-guide.md +7 -14
- package/docs/server-readiness.md +31 -24
- package/index.js +1 -1
- package/install/_common.mjs +3 -5
- package/install/_platform-filter.mjs +23 -1
- package/install/_unattended-profile.mjs +321 -75
- package/install/claude.mjs +51 -10
- package/install/codex.mjs +2 -0
- package/install/copilot.mjs +2 -0
- package/install/index.mjs +30 -17
- package/install/templates/claude-hooks.json +16 -5
- package/install/templates/copilot-instructions.md +1 -1
- package/install/templates/multi-agent-autopilot-awake.plist.template +48 -0
- package/install/templates/multi-agent-autopilot.plist.template +12 -5
- package/install/unattended-profile-legacy.json +80 -0
- package/manifest.json +617 -483
- package/package.json +8 -3
- package/pipeline/agents/code-reviewer.md +10 -0
- package/pipeline/agents/plan-critic.md +98 -0
- package/pipeline/agents/security-auditor.md +10 -0
- package/pipeline/agents/task-clarifier.md +10 -0
- package/pipeline/commands/multi-agent/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/analysis/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +12 -1
- package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +36 -6
- package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +77 -12
- package/pipeline/commands/multi-agent/autopilot-status/SKILL.md +29 -8
- package/pipeline/commands/multi-agent/build-optimize/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/channels/SKILL.md +9 -9
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/create-jira/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/design-check/SKILL.md +16 -11
- package/pipeline/commands/multi-agent/diff-explain/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/doctor/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/feedback/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/forget/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/graph/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/help/SKILL.md +37 -39
- package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/issue/SKILL.md +7 -1
- package/pipeline/commands/multi-agent/jira/SKILL.md +7 -1
- package/pipeline/commands/multi-agent/kill/SKILL.md +9 -3
- package/pipeline/commands/multi-agent/language/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/log/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/manual-test/SKILL.md +5 -0
- package/pipeline/commands/multi-agent/model/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/prune-logs/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/prune-prompts/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/purge/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/refactor/SKILL.md +5 -0
- package/pipeline/commands/multi-agent/research/SKILL.md +49 -0
- package/pipeline/commands/multi-agent/resume/SKILL.md +29 -6
- package/pipeline/commands/multi-agent/review/SKILL.md +28 -9
- package/pipeline/commands/multi-agent/review-analysis/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/review-issue/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/review-jira/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/route-off/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/route-on/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/route-status/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/routines/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/save/SKILL.md +6 -2
- package/pipeline/commands/multi-agent/scaffold/SKILL.md +47 -0
- package/pipeline/commands/multi-agent/scan/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/search/SKILL.md +12 -8
- package/pipeline/commands/multi-agent/security-review/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/serve/SKILL.md +62 -0
- package/pipeline/commands/multi-agent/setup/SKILL.md +27 -36
- package/pipeline/commands/multi-agent/stack/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/status/SKILL.md +10 -9
- package/pipeline/commands/multi-agent/steer/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/sync/SKILL.md +13 -13
- package/pipeline/commands/multi-agent/test/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-accessibility/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-dark-mode/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-dynamic-type/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/test-screenshots/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +4 -0
- package/pipeline/commands/multi-agent/uninstall/SKILL.md +5 -1
- package/pipeline/commands/multi-agent/update/SKILL.md +4 -0
- package/pipeline/contract/CHANGELOG.md +74 -0
- package/pipeline/contract/README.md +126 -0
- package/pipeline/contract/build.mjs +427 -0
- package/pipeline/contract/fixtures/answer-result.json +11 -0
- package/pipeline/contract/fixtures/error-invalid-request.json +8 -0
- package/pipeline/contract/fixtures/error-unauthorized.json +5 -0
- package/pipeline/contract/fixtures/error-unsigned.json +5 -0
- package/pipeline/contract/fixtures/issues-empty.json +18 -0
- package/pipeline/contract/fixtures/launch-plan.json +31 -0
- package/pipeline/contract/fixtures/runs-awaiting-question.json +70 -0
- package/pipeline/contract/fixtures/runs-empty.json +6 -0
- package/pipeline/contract/fixtures/runs-failed.json +84 -0
- package/pipeline/contract/fixtures/runs-old-schema.json +70 -0
- package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +101 -0
- package/pipeline/contract/fixtures/runs-pr-opened.json +106 -0
- package/pipeline/contract/fixtures/runs-running.json +84 -0
- package/pipeline/contract/fixtures/worktrees-empty.json +4 -0
- package/pipeline/contract/frozen/toolbox.json +107 -0
- package/pipeline/contract/manifest.json +263 -0
- package/pipeline/contract/types/index.d.ts +343 -0
- package/pipeline/lib/_jira-auth.sh +6 -2
- package/pipeline/lib/account-resolver.sh +1 -1
- package/pipeline/lib/autopilot-state.sh +19 -0
- package/pipeline/lib/context-link-extractor.sh +12 -5
- package/pipeline/lib/credential-inventory.sh +12 -5
- package/pipeline/lib/credential-store.sh +116 -185
- package/pipeline/lib/fetch-confluence.sh +44 -3
- package/pipeline/lib/fetch-document.sh +3 -4
- package/pipeline/lib/fetch-fortify.sh +1 -1
- package/pipeline/lib/figma-mcp-refresh.sh +2 -2
- package/pipeline/lib/figma-token.sh +5 -1
- package/pipeline/lib/issue-fetcher.sh +233 -16
- package/pipeline/lib/json-file-lock.mjs +172 -0
- package/pipeline/lib/model-dispatch.sh +21 -12
- package/pipeline/lib/model-rung.sh +6 -1
- package/pipeline/lib/multi-repo-pipeline.sh +1 -1
- package/pipeline/lib/outbound-gate.mjs +46 -16
- package/pipeline/lib/parse-complaints.sh +14 -7
- package/pipeline/lib/plan-todos.sh +3 -3
- package/pipeline/lib/post-pr-review.sh +9 -9
- package/pipeline/lib/pr-request-location.mjs +85 -0
- package/pipeline/lib/regular-file.mjs +153 -0
- package/pipeline/lib/repo-hygiene.sh +17 -0
- package/pipeline/lib/route-state.sh +5 -1
- package/pipeline/lib/run-paths.sh +3 -2
- package/pipeline/lib/stack-detect.sh +19 -1
- package/pipeline/lib/unattended-profile-check.mjs +178 -0
- package/pipeline/lib/unattended-settings-location.mjs +28 -0
- package/pipeline/lib/unattended.mjs +76 -0
- package/pipeline/lib/unattended.sh +32 -0
- package/pipeline/lib/untrusted.mjs +76 -0
- package/pipeline/lib/usage-endpoint.mjs +33 -0
- package/pipeline/lib/user-facing.mjs +82 -0
- package/pipeline/lib/user-facing.sh +58 -0
- package/pipeline/multi-agent-refs/_dev-context.md +1 -1
- package/pipeline/multi-agent-refs/analysis/evidence.md +4 -0
- package/pipeline/multi-agent-refs/analysis/locked.md +2 -2
- package/pipeline/multi-agent-refs/analysis/render.md +4 -3
- package/pipeline/multi-agent-refs/analysis/resolve.md +3 -1
- package/pipeline/multi-agent-refs/analysis/synthesis.md +4 -5
- package/pipeline/multi-agent-refs/analysis-template.md +10 -17
- package/pipeline/multi-agent-refs/channels/jira.md +1 -1
- package/pipeline/multi-agent-refs/component-dispatch.md +3 -3
- package/pipeline/multi-agent-refs/conventions-defaults.md +32 -32
- package/pipeline/multi-agent-refs/cross-cli-contract.md +10 -17
- package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +37 -9
- package/pipeline/multi-agent-refs/features/autopilot-operations.md +277 -0
- package/pipeline/multi-agent-refs/features/constitution.md +196 -0
- package/pipeline/multi-agent-refs/features/doctor.md +6 -3
- package/pipeline/multi-agent-refs/features/external-context-injection.md +6 -1
- package/pipeline/multi-agent-refs/features/jira-context.md +1 -1
- package/pipeline/multi-agent-refs/features/maturity-followup.md +43 -23
- package/pipeline/multi-agent-refs/features/model-fallback.md +9 -0
- package/pipeline/multi-agent-refs/features/phone-api.md +306 -0
- package/pipeline/multi-agent-refs/features/plan-critic.md +159 -0
- package/pipeline/multi-agent-refs/features/research.md +150 -0
- package/pipeline/multi-agent-refs/features/review-decision.md +185 -0
- package/pipeline/multi-agent-refs/features/scaffold.md +160 -0
- package/pipeline/multi-agent-refs/features/security-audit.md +6 -2
- package/pipeline/multi-agent-refs/features/skill-conformance.md +4 -1
- package/pipeline/multi-agent-refs/features/stack-adapters.md +116 -0
- package/pipeline/multi-agent-refs/features/unattended-gates.md +316 -0
- package/pipeline/multi-agent-refs/features/unattended-security.md +731 -0
- package/pipeline/multi-agent-refs/features/url-enrichment.md +2 -2
- package/pipeline/multi-agent-refs/features/usage-reporting.md +127 -35
- package/pipeline/multi-agent-refs/features/verify-by-test.md +1 -1
- package/pipeline/multi-agent-refs/features/visual-evidence.md +7 -7
- package/pipeline/multi-agent-refs/keychain.md +6 -11
- package/pipeline/multi-agent-refs/payload-contracts.md +2 -2
- package/pipeline/multi-agent-refs/phases/log-format.md +2 -3
- package/pipeline/multi-agent-refs/phases/modes.md +10 -12
- package/pipeline/multi-agent-refs/phases/operations.md +11 -5
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +73 -81
- package/pipeline/multi-agent-refs/phases/phase-1-plan.md +22 -22
- package/pipeline/multi-agent-refs/phases/phase-2-dev.md +42 -66
- package/pipeline/multi-agent-refs/phases/phase-3-review.md +45 -79
- package/pipeline/multi-agent-refs/phases/phase-4-commit.md +28 -38
- package/pipeline/multi-agent-refs/phases/phase-5-report.md +27 -25
- package/pipeline/multi-agent-refs/phases.md +1 -1
- package/pipeline/multi-agent-refs/picker-contract.md +1 -1
- package/pipeline/multi-agent-refs/progress-contract.md +13 -16
- package/pipeline/multi-agent-refs/readiness-review.md +1 -1
- package/pipeline/multi-agent-refs/research/engine.md +91 -0
- package/pipeline/multi-agent-refs/rules.md +6 -4
- package/pipeline/multi-agent-refs/setup/repo-discovery.md +2 -2
- package/pipeline/multi-agent-refs/tracker-contract.md +2 -2
- package/pipeline/multi-agent-refs/unattended-contract.md +68 -16
- package/pipeline/rules/figma-pipeline.md +12 -12
- package/pipeline/schemas/agent-state.schema.json +480 -18
- package/pipeline/schemas/analysis-spec.schema.json +4 -4
- package/pipeline/schemas/answer-request.schema.json +24 -0
- package/pipeline/schemas/answer-result.schema.json +28 -0
- package/pipeline/schemas/autopilot-config.schema.json +111 -13
- package/pipeline/schemas/command-parameters.schema.json +99 -0
- package/pipeline/schemas/constitution.schema.json +56 -0
- package/pipeline/schemas/contract-error.schema.json +52 -0
- package/pipeline/schemas/design-check-config.schema.json +5 -1
- package/pipeline/schemas/issues.schema.json +61 -0
- package/pipeline/schemas/launch-plan.schema.json +46 -0
- package/pipeline/schemas/launch-request.schema.json +45 -0
- package/pipeline/schemas/launch.json +61 -0
- package/pipeline/schemas/launch.schema.json +84 -0
- package/pipeline/schemas/phases.json +2 -2
- package/pipeline/schemas/phases.schema.json +68 -0
- package/pipeline/schemas/phone-devices.schema.json +61 -0
- package/pipeline/schemas/phone-signed-request.schema.json +67 -0
- package/pipeline/schemas/plan-critique.schema.json +99 -0
- package/pipeline/schemas/plan-todos.schema.json +7 -7
- package/pipeline/schemas/planning-output.schema.json +5 -0
- package/pipeline/schemas/pr-request.schema.json +46 -0
- package/pipeline/schemas/prefs.schema.json +79 -8
- package/pipeline/schemas/research-output.schema.json +118 -0
- package/pipeline/schemas/review-file-exclusions.schema.json +25 -0
- package/pipeline/schemas/reviewer-output.schema.json +40 -4
- package/pipeline/schemas/run-questions.json +392 -0
- package/pipeline/schemas/run-questions.schema.json +118 -0
- package/pipeline/schemas/runs-index.schema.json +189 -0
- package/pipeline/schemas/scaffold-manifest.schema.json +43 -0
- package/pipeline/schemas/secret-patterns.schema.json +28 -0
- package/pipeline/schemas/stack-adapters.json +527 -0
- package/pipeline/schemas/stack-adapters.schema.json +184 -0
- package/pipeline/schemas/token-budget.json +1 -1
- package/pipeline/schemas/token-budget.schema.json +26 -0
- package/pipeline/schemas/triage-output.schema.json +64 -3
- package/pipeline/schemas/unattended-policy.json +139 -0
- package/pipeline/schemas/unattended-policy.schema.json +73 -0
- package/pipeline/schemas/unattended-profile.json +248 -0
- package/pipeline/schemas/unattended-profile.schema.json +198 -0
- package/pipeline/schemas/worktrees.schema.json +51 -0
- package/pipeline/scripts/README.md +1 -0
- package/pipeline/scripts/_autopilot-config.mjs +130 -0
- package/pipeline/scripts/_autopilot-ops.mjs +567 -0
- package/pipeline/scripts/_autopilot-outcomes.mjs +174 -0
- package/pipeline/scripts/_command-contract.mjs +384 -0
- package/pipeline/scripts/_cost.mjs +40 -0
- package/pipeline/scripts/_notices.mjs +160 -0
- package/pipeline/scripts/_phone-auth.mjs +485 -0
- package/pipeline/scripts/_pre-existing.mjs +294 -0
- package/pipeline/scripts/_redact.mjs +77 -0
- package/pipeline/scripts/_run-paths.mjs +4 -2
- package/pipeline/scripts/_stack-adapter.mjs +678 -0
- package/pipeline/scripts/_stack-routing.mjs +1 -1
- package/pipeline/scripts/agent-guard.py +348 -37
- package/pipeline/scripts/agent-guard.sh +41 -13
- package/pipeline/scripts/analysis-story-tree.mjs +79 -3
- package/pipeline/scripts/answer-question.mjs +181 -0
- package/pipeline/scripts/audit-log-rotate.sh +1 -4
- package/pipeline/scripts/audit-log.sh +4 -4
- package/pipeline/scripts/autopilot-arming.mjs +389 -21
- package/pipeline/scripts/autopilot-awake.mjs +255 -0
- package/pipeline/scripts/autopilot-intake.mjs +137 -36
- package/pipeline/scripts/autopilot-menubar.swift +156 -44
- package/pipeline/scripts/autopilot-publish.mjs +1625 -0
- package/pipeline/scripts/autopilot-runner.mjs +1678 -222
- package/pipeline/scripts/autopilot-status.sh +198 -33
- package/pipeline/scripts/build-lock.sh +120 -0
- package/pipeline/scripts/build-references.mjs +4 -1
- package/pipeline/scripts/build-stack-plugins.mjs +59 -22
- package/pipeline/scripts/capture-flush.sh +1 -1
- package/pipeline/scripts/capture-resume.sh +13 -9
- package/pipeline/scripts/check-derived-drift.mjs +52 -11
- package/pipeline/scripts/commands.mjs +88 -0
- package/pipeline/scripts/constitution.mjs +362 -0
- package/pipeline/scripts/contract-server.mjs +776 -0
- package/pipeline/scripts/cost-analyze.mjs +89 -39
- package/pipeline/scripts/diff-explain.mjs +12 -1
- package/pipeline/scripts/doctor.mjs +77 -28
- package/pipeline/scripts/evidence-gate.mjs +192 -12
- package/pipeline/scripts/feedback-send.mjs +4 -2
- package/pipeline/scripts/gate-ledger.mjs +449 -0
- package/pipeline/scripts/gc-abandoned.sh +132 -13
- package/pipeline/scripts/gen-facts.mjs +31 -15
- package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
- package/pipeline/scripts/github-ssh-setup.sh +140 -29
- package/pipeline/scripts/graph-mermaid.mjs +4 -1
- package/pipeline/scripts/issues.mjs +236 -0
- package/pipeline/scripts/jira-attach.sh +6 -2
- package/pipeline/scripts/jira-search.sh +4 -3
- package/pipeline/scripts/keychain-save.sh +125 -24
- package/pipeline/scripts/keychain.py +63 -93
- package/pipeline/scripts/launch-request.mjs +747 -0
- package/pipeline/scripts/localize-commands.mjs +4 -10
- package/pipeline/scripts/log-metric.sh +6 -5
- package/pipeline/scripts/maturity-followup.mjs +13 -4
- package/pipeline/scripts/memory-save.sh +25 -0
- package/pipeline/scripts/migrate-prefs.mjs +4 -3
- package/pipeline/scripts/open-questions-gate.mjs +276 -0
- package/pipeline/scripts/phase-tracker.sh +41 -27
- package/pipeline/scripts/phase0-exit-gate.mjs +22 -4
- package/pipeline/scripts/phone-devices.mjs +224 -0
- package/pipeline/scripts/plan-coverage-gate.mjs +200 -66
- package/pipeline/scripts/plan-critique-gate.mjs +591 -0
- package/pipeline/scripts/pr-request.mjs +188 -0
- package/pipeline/scripts/pre-commit-check.sh +115 -4
- package/pipeline/scripts/probe-evidence-capability.sh +44 -5
- package/pipeline/scripts/record-phase.mjs +71 -0
- package/pipeline/scripts/render-agent-log-cost.sh +17 -2
- package/pipeline/scripts/render-cost-summary.sh +1 -1
- package/pipeline/scripts/render-work-summary.sh +1 -1
- package/pipeline/scripts/require-supported-version.sh +4 -1
- package/pipeline/scripts/research-gate.mjs +704 -0
- package/pipeline/scripts/review-decision-gate.mjs +403 -0
- package/pipeline/scripts/routine-registry.mjs +5 -2
- package/pipeline/scripts/runs-index.mjs +135 -27
- package/pipeline/scripts/scaffold-gate.mjs +393 -0
- package/pipeline/scripts/skill-conformance.mjs +25 -8
- package/pipeline/scripts/skill-siblings.mjs +2 -1
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +32 -6
- package/pipeline/scripts/smoke-schema-validation.sh +6 -2
- package/pipeline/scripts/spec-consistency-gate.mjs +469 -0
- package/pipeline/scripts/symbol-existence-gate.mjs +450 -0
- package/pipeline/scripts/test-gap-scan.mjs +40 -2
- package/pipeline/scripts/test-integrity-gate.mjs +20 -4
- package/pipeline/scripts/test-strength.mjs +484 -0
- package/pipeline/scripts/test-summary.mjs +651 -0
- package/pipeline/scripts/triage-memory.mjs +49 -9
- package/pipeline/scripts/unattended_policy.py +2786 -0
- package/pipeline/scripts/uninstall.mjs +10 -10
- package/pipeline/scripts/update-issue-progress.sh +1 -1
- package/pipeline/scripts/usage-identity.mjs +288 -0
- package/pipeline/scripts/usage-register.mjs +187 -67
- package/pipeline/scripts/usage-report.mjs +232 -67
- package/pipeline/scripts/validate-complaint-doc.mjs +28 -10
- package/pipeline/scripts/validate-planning.mjs +6 -0
- package/pipeline/scripts/verify-citations.mjs +151 -38
- package/pipeline/scripts/verify.mjs +58 -18
- package/pipeline/scripts/worktree-prepare.sh +126 -0
- package/pipeline/scripts/worktrees.mjs +124 -0
- package/pipeline/scripts/write-state.mjs +48 -17
- package/pipeline/skills/.skill-manifest.json +222 -226
- package/pipeline/skills/.skills-index.json +77 -88
- package/pipeline/skills/shared/README.md +44 -45
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +3 -2
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +10 -9
- package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +6 -5
- package/pipeline/skills/shared/core/multi-agent-analysis-jira/SKILL.md +11 -3
- package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +4 -3
- package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +32 -6
- package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +66 -8
- package/pipeline/skills/shared/core/multi-agent-autopilot-status/SKILL.md +27 -9
- package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +7 -4
- package/pipeline/skills/shared/core/multi-agent-complaint-analysis/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +7 -5
- package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-doctor/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-feedback/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +7 -4
- package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-model/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-prune-prompts/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-research/SKILL.md +35 -0
- package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +7 -3
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +7 -5
- package/pipeline/skills/shared/core/multi-agent-review-analysis/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-route-off/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-route-on/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-route-status/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-scaffold/SKILL.md +30 -0
- package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +4 -3
- package/pipeline/skills/shared/core/multi-agent-security-review/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-serve/SKILL.md +60 -0
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +8 -8
- package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +7 -8
- package/pipeline/skills/shared/core/multi-agent-steer/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +10 -10
- package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-accessibility/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-dark-mode/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-dynamic-type/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-test-screenshots/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +2 -1
- package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +3 -2
- package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +2 -1
- package/pipeline/skills/shared/external/NOTICE-avdlee-swiftui-agent-skill.md +46 -0
- package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +9 -3
- package/pipeline/skills/shared/external/NOTICE-paul-hudson-skills.md +54 -0
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +9 -11
- package/pipeline/skills/shared/external/NOTICE-vibeship-spawner-skills.md +203 -0
- package/pipeline/skills/shared/external/NOTICE-xcode-build-skills.md +10 -3
- package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +131 -25
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +4 -3
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +2 -1
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +85 -76
- package/pipeline/skills/shared/external/android-build-quality-gates/SKILL.md +51 -3
- package/pipeline/skills/shared/external/android-build-quality-gates/references/patterns.md +9 -0
- package/pipeline/skills/shared/external/android-datastore/SKILL.md +4 -3
- package/pipeline/skills/shared/external/android-design-tokens-codegen/SKILL.md +4 -3
- package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +106 -181
- package/pipeline/skills/shared/external/android-jetpack-compose-expert/references/patterns.md +147 -0
- package/pipeline/skills/shared/external/android-mvi-viewmodel/SKILL.md +45 -4
- package/pipeline/skills/shared/external/android-performance/SKILL.md +27 -2
- package/pipeline/skills/shared/external/android-performance/references/patterns.md +37 -37
- package/pipeline/skills/shared/external/api-patterns/SKILL.md +111 -67
- package/pipeline/skills/shared/external/api-patterns/references/contract-details.md +128 -0
- package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +136 -186
- package/pipeline/skills/shared/external/api-security-best-practices/references/abuse-controls.md +140 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/identity-and-access.md +207 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/operations.md +66 -0
- package/pipeline/skills/shared/external/api-security-best-practices/references/request-handling.md +175 -0
- package/pipeline/skills/shared/external/app-clips/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-intents/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-store-changelog/SKILL.md +4 -3
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +2 -0
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +2 -0
- package/pipeline/skills/shared/external/architecture/SKILL.md +106 -39
- package/pipeline/skills/shared/external/architecture/references/adr-and-review.md +76 -0
- package/pipeline/skills/shared/external/authentication/SKILL.md +2 -0
- package/pipeline/skills/shared/external/avkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/background-processing/SKILL.md +2 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +3 -2
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +2 -0
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +3 -2
- package/pipeline/skills/shared/external/clean-code/SKILL.md +192 -90
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +2 -1
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/compose-components/SKILL.md +4 -4
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +22 -22
- package/pipeline/skills/shared/external/compose-navigation/references/patterns.md +10 -10
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +13 -6
- package/pipeline/skills/shared/external/compose-testing/references/patterns.md +59 -59
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +2 -0
- package/pipeline/skills/shared/external/context-compression/SKILL.md +118 -250
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +2 -0
- package/pipeline/skills/shared/external/core-data/SKILL.md +2 -0
- package/pipeline/skills/shared/external/core-motion/SKILL.md +2 -0
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +2 -0
- package/pipeline/skills/shared/external/coreml/SKILL.md +2 -1
- package/pipeline/skills/shared/external/council/SKILL.md +2 -1
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/css-modern/SKILL.md +3 -2
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +3 -2
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +2 -0
- package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +130 -20
- package/pipeline/skills/shared/external/debugging-strategies/references/hard-cases.md +54 -0
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +2 -0
- package/pipeline/skills/shared/external/docker-expert/SKILL.md +137 -381
- package/pipeline/skills/shared/external/docker-expert/references/patterns.md +98 -0
- package/pipeline/skills/shared/external/energykit/SKILL.md +2 -1
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +3 -1
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +116 -185
- package/pipeline/skills/shared/external/fastapi-pro/references/app-structure.md +235 -0
- package/pipeline/skills/shared/external/fastapi-pro/references/testing-and-deployment.md +69 -0
- package/pipeline/skills/shared/external/firebase/SKILL.md +4 -3
- package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +151 -293
- package/pipeline/skills/shared/external/github-actions-templates/references/patterns.md +96 -0
- package/pipeline/skills/shared/external/healthkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/hig-components-content/SKILL.md +69 -72
- package/pipeline/skills/shared/external/hig-components-content/references/content-views.md +111 -0
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +77 -86
- package/pipeline/skills/shared/external/hig-components-layout/references/containers.md +98 -0
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +150 -78
- package/pipeline/skills/shared/external/hig-components-system/SKILL.md +76 -97
- package/pipeline/skills/shared/external/hig-components-system/references/surfaces.md +98 -0
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +48 -76
- package/pipeline/skills/shared/external/hig-foundations/references/foundations-detail.md +132 -0
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +147 -106
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +61 -77
- package/pipeline/skills/shared/external/hig-patterns/references/patterns.md +92 -0
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +147 -77
- package/pipeline/skills/shared/external/hig-technologies/SKILL.md +61 -121
- package/pipeline/skills/shared/external/hig-technologies/references/technologies.md +108 -0
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +2 -0
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +3 -2
- package/pipeline/skills/shared/external/humanizer/SKILL.md +2 -1
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +2 -1
- package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +14 -2
- package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +2 -2
- package/pipeline/skills/shared/external/ios-debugger-agent/SKILL.md +4 -3
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +8 -6
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +11 -11
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +2 -1
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +2 -0
- package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +102 -193
- package/pipeline/skills/shared/external/kotlin-coroutines-expert/references/patterns.md +103 -0
- package/pipeline/skills/shared/external/live-activities/SKILL.md +4 -2
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +7 -9
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +3 -3
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +2 -2
- package/pipeline/skills/shared/external/macos-menubar-tuist-app/SKILL.md +4 -3
- package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +5 -3
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +2 -0
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +2 -0
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +149 -46
- package/pipeline/skills/shared/external/monorepo-architect/references/patterns.md +70 -0
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +2 -0
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/natural-language/SKILL.md +2 -0
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +3 -2
- package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +91 -21
- package/pipeline/skills/shared/external/nodejs-backend-patterns/references/runtime-patterns.md +247 -0
- package/pipeline/skills/shared/external/nodejs-backend-patterns/references/testing-and-frameworks.md +57 -0
- package/pipeline/skills/shared/external/observability-engineer/SKILL.md +155 -232
- package/pipeline/skills/shared/external/observability-engineer/references/patterns.md +75 -0
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +2 -0
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +2 -2
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +18 -18
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +2 -1
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +2 -1
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +2 -0
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +3 -2
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +3 -2
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +2 -2
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +1 -1
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +3 -2
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +7 -7
- package/pipeline/skills/shared/external/retrofit-networking/references/patterns.md +69 -69
- package/pipeline/skills/shared/external/room-database/references/patterns.md +126 -126
- package/pipeline/skills/shared/external/search-first/SKILL.md +2 -1
- package/pipeline/skills/shared/external/security-review/SKILL.md +4 -3
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +2 -2
- package/pipeline/skills/shared/external/signal-community/SKILL.md +1 -1
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +2 -1
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +2 -1
- package/pipeline/skills/shared/external/spm-build-analysis/SKILL.md +2 -0
- package/pipeline/skills/shared/external/storekit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +5 -4
- package/pipeline/skills/shared/external/swift-concurrency-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-language/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swift-security/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swift-testing-pro/references/new-features.md +10 -0
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftdata-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-expert-skill/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +3 -1
- package/pipeline/skills/shared/external/swiftui-performance-audit/SKILL.md +5 -4
- package/pipeline/skills/shared/external/swiftui-pro/SKILL.md +2 -1
- package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +5 -4
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +2 -0
- package/pipeline/skills/shared/external/swiftui-view-refactor/SKILL.md +4 -3
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +3 -2
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +3 -2
- package/pipeline/skills/shared/external/tipkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +3 -2
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +2 -0
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +3 -2
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +3 -2
- package/pipeline/skills/shared/external/web-performance/SKILL.md +3 -2
- package/pipeline/skills/shared/external/web-testing/SKILL.md +3 -2
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +2 -0
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +1 -1
- package/pipeline/skills/shared/external/xcode-build-benchmark/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-build-fixer/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-build-orchestrator/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-compilation-analyzer/SKILL.md +2 -0
- package/pipeline/skills/shared/external/xcode-project-analyzer/SKILL.md +2 -0
- package/pipeline/skills/skills-index.md +40 -41
- package/docs/token-budget-history.md +0 -24
- package/pipeline/skills/shared/external/agentflow/SKILL.md +0 -199
- package/pipeline/skills/shared/external/android-ui-verification/SKILL.md +0 -66
- package/pipeline/skills/shared/external/api-security-best-practices/references/auth.md +0 -299
- package/pipeline/skills/shared/external/api-security-best-practices/references/input-validation.md +0 -255
- package/pipeline/skills/shared/external/api-security-best-practices/references/rate-limiting.md +0 -167
- package/pipeline/skills/shared/external/closed-loop-delivery/SKILL.md +0 -116
- package/pipeline/skills/shared/external/ios-developer/SKILL.md +0 -216
|
@@ -202,9 +202,9 @@ fun InfoCard(
|
|
|
202
202
|
|
|
203
203
|
// Usage
|
|
204
204
|
InfoCard(
|
|
205
|
-
icon = { Icon(Icons.Default.
|
|
206
|
-
title = { Text("
|
|
207
|
-
subtitle = { Text("
|
|
205
|
+
icon = { Icon(Icons.Default.ShoppingCart, contentDescription = null) },
|
|
206
|
+
title = { Text("London to New York") },
|
|
207
|
+
subtitle = { Text("Order AB1234") },
|
|
208
208
|
actions = {
|
|
209
209
|
IconButton(onClick = { /* bookmark */ }) {
|
|
210
210
|
Icon(Icons.Default.BookmarkBorder, contentDescription = "Bookmark")
|
|
@@ -331,7 +331,7 @@ val AppTypography = Typography(
|
|
|
331
331
|
|
|
332
332
|
// Usage: always reference tokens, never raw values
|
|
333
333
|
Text(
|
|
334
|
-
text = "
|
|
334
|
+
text = "Order Details",
|
|
335
335
|
style = MaterialTheme.typography.headlineMedium,
|
|
336
336
|
color = MaterialTheme.colorScheme.onSurface,
|
|
337
337
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: compose-navigation
|
|
3
|
-
description: "Implement type-safe navigation in Jetpack Compose using Navigation 2.8+ with @Serializable routes, NavHost, composable
|
|
3
|
+
description: "Implement type-safe navigation in Jetpack Compose using Navigation 2.8+ with @Serializable routes, NavHost, typed composable routes, nested navigation graphs, deep links, BackHandler, type-safe argument passing, and bottom navigation with NavigationBar integration. Use when building Compose navigation, adding new screens, handling deep links, or implementing bottom nav patterns."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Compose Navigation
|
|
@@ -102,7 +102,7 @@ fun AppNavHost(
|
|
|
102
102
|
|
|
103
103
|
```kotlin
|
|
104
104
|
// Navigate forward
|
|
105
|
-
navController.navigate(DetailRoute(id = "
|
|
105
|
+
navController.navigate(DetailRoute(id = "order-123"))
|
|
106
106
|
|
|
107
107
|
// Navigate with options
|
|
108
108
|
navController.navigate(HomeRoute) {
|
|
@@ -129,31 +129,31 @@ serializes them automatically.
|
|
|
129
129
|
|
|
130
130
|
```kotlin
|
|
131
131
|
@Serializable
|
|
132
|
-
data class
|
|
133
|
-
val
|
|
134
|
-
val
|
|
135
|
-
val
|
|
136
|
-
val
|
|
132
|
+
data class OrderDetailRoute(
|
|
133
|
+
val orderId: String,
|
|
134
|
+
val store: String,
|
|
135
|
+
val region: String,
|
|
136
|
+
val placedTimestamp: Long,
|
|
137
137
|
)
|
|
138
138
|
|
|
139
139
|
// Navigate with arguments
|
|
140
140
|
navController.navigate(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
OrderDetailRoute(
|
|
142
|
+
orderId = "ORD-101",
|
|
143
|
+
store = "LDN",
|
|
144
|
+
region = "NYC",
|
|
145
|
+
placedTimestamp = System.currentTimeMillis(),
|
|
146
146
|
)
|
|
147
147
|
)
|
|
148
148
|
|
|
149
149
|
// Retrieve arguments in destination
|
|
150
|
-
composable<
|
|
151
|
-
val route = backStackEntry.toRoute<
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
composable<OrderDetailRoute> { backStackEntry ->
|
|
151
|
+
val route = backStackEntry.toRoute<OrderDetailRoute>()
|
|
152
|
+
OrderDetailScreen(
|
|
153
|
+
orderId = route.orderId,
|
|
154
|
+
store = route.store,
|
|
155
|
+
region = route.region,
|
|
156
|
+
placedAt = Instant.fromEpochMilliseconds(route.placedTimestamp),
|
|
157
157
|
)
|
|
158
158
|
}
|
|
159
159
|
```
|
|
@@ -178,7 +178,7 @@ Passing a complex `@Serializable` type through a route needs a custom `NavType`
|
|
|
178
178
|
in a `typeMap` shared by `composable<>()` and every `toRoute` read (else only primitives resolve).
|
|
179
179
|
|
|
180
180
|
```kotlin
|
|
181
|
-
val searchTypeMap = mapOf(typeOf<
|
|
181
|
+
val searchTypeMap = mapOf(typeOf<SearchFilter>() to SearchFilterNavType)
|
|
182
182
|
|
|
183
183
|
composable<SearchRoute>(typeMap = searchTypeMap) { entry ->
|
|
184
184
|
val route = entry.toRoute<SearchRoute>(typeMap = searchTypeMap)
|
|
@@ -186,8 +186,8 @@ composable<SearchRoute>(typeMap = searchTypeMap) { entry ->
|
|
|
186
186
|
}
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
A shared holder owns the one `typeMap`; the ViewModel
|
|
190
|
-
`
|
|
189
|
+
A shared holder owns the one `typeMap`; wrap `composable<>()` and the ViewModel's `savedStateHandle.toRoute<SearchRoute>(typeMap = ...)` in helpers that always pass it,
|
|
190
|
+
and use them even for primitive-only routes - a bare `toRoute()` crashes the day the route gains a complex field. Full `NavType`
|
|
191
191
|
+ holder: [references/patterns.md#custom-navtype-type-map](references/patterns.md#custom-navtype-type-map).
|
|
192
192
|
|
|
193
193
|
## SafeNavController via CompositionLocal
|
|
@@ -18,22 +18,22 @@ only primitive nav args resolve and the route fails to build.
|
|
|
18
18
|
|
|
19
19
|
```kotlin
|
|
20
20
|
@Serializable
|
|
21
|
-
data class
|
|
21
|
+
data class SearchFilter(val category: String, val minPrice: Int, val maxPrice: Int)
|
|
22
22
|
|
|
23
23
|
@Serializable
|
|
24
|
-
data class SearchRoute(val filter:
|
|
24
|
+
data class SearchRoute(val filter: SearchFilter)
|
|
25
25
|
|
|
26
|
-
val
|
|
27
|
-
override fun get(bundle: Bundle, key: String):
|
|
26
|
+
val SearchFilterNavType = object : NavType<SearchFilter>(isNullableAllowed = false) {
|
|
27
|
+
override fun get(bundle: Bundle, key: String): SearchFilter? =
|
|
28
28
|
bundle.getString(key)?.let { Json.decodeFromString(it) }
|
|
29
29
|
|
|
30
|
-
override fun parseValue(value: String):
|
|
30
|
+
override fun parseValue(value: String): SearchFilter =
|
|
31
31
|
Json.decodeFromString(Uri.decode(value))
|
|
32
32
|
|
|
33
|
-
override fun serializeAsValue(value:
|
|
33
|
+
override fun serializeAsValue(value: SearchFilter): String =
|
|
34
34
|
Uri.encode(Json.encodeToString(value))
|
|
35
35
|
|
|
36
|
-
override fun put(bundle: Bundle, key: String, value:
|
|
36
|
+
override fun put(bundle: Bundle, key: String, value: SearchFilter) {
|
|
37
37
|
bundle.putString(key, Json.encodeToString(value))
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -46,7 +46,7 @@ One holder owns the map so the registration and every read agree:
|
|
|
46
46
|
```kotlin
|
|
47
47
|
object NavTypeMaps {
|
|
48
48
|
val search: Map<KType, NavType<*>> =
|
|
49
|
-
mapOf(typeOf<
|
|
49
|
+
mapOf(typeOf<SearchFilter>() to SearchFilterNavType)
|
|
50
50
|
}
|
|
51
51
|
```
|
|
52
52
|
|
|
@@ -68,7 +68,7 @@ composable<SearchRoute>(typeMap = NavTypeMaps.search) { entry ->
|
|
|
68
68
|
class SearchViewModel @Inject constructor(
|
|
69
69
|
savedStateHandle: SavedStateHandle,
|
|
70
70
|
) : ViewModel() {
|
|
71
|
-
private val filter:
|
|
71
|
+
private val filter: SearchFilter =
|
|
72
72
|
savedStateHandle.toRoute<SearchRoute>(typeMap = NavTypeMaps.search).filter
|
|
73
73
|
}
|
|
74
74
|
```
|
|
@@ -173,7 +173,7 @@ fun HomeRoute(viewModel: HomeViewModel = hiltViewModel()) {
|
|
|
173
173
|
viewModel.navEvents.collect { event ->
|
|
174
174
|
when (event) {
|
|
175
175
|
is HomeNavEvent.ToDetail -> nav.navigate(DetailRoute(event.id))
|
|
176
|
-
HomeNavEvent.ToSearch -> nav.navigate(SearchRoute(
|
|
176
|
+
HomeNavEvent.ToSearch -> nav.navigate(SearchRoute(SearchFilter("BOOKS", 0, 50)))
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
}
|
|
@@ -52,9 +52,9 @@ Select nodes by semantics, never by implementation details. Set
|
|
|
52
52
|
`Modifier.testTag("tag")` on key composables so tests find them reliably.
|
|
53
53
|
|
|
54
54
|
```kotlin
|
|
55
|
-
composeTestRule.onNodeWithText("
|
|
56
|
-
composeTestRule.onNodeWithTag("
|
|
57
|
-
composeTestRule.onNodeWithContentDescription("Search
|
|
55
|
+
composeTestRule.onNodeWithText("Place Order")
|
|
56
|
+
composeTestRule.onNodeWithTag("order_list")
|
|
57
|
+
composeTestRule.onNodeWithContentDescription("Search orders")
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
Combined matchers (`hasText and hasClickAction`), `onAllNodesWith*`, parent/child
|
|
@@ -70,10 +70,17 @@ shared identifier source; the codegen side lives in the
|
|
|
70
70
|
`android-design-tokens-codegen` skill.
|
|
71
71
|
|
|
72
72
|
```kotlin
|
|
73
|
-
Modifier.testTag(TestTags.
|
|
74
|
-
composeTestRule.onNodeWithTag(TestTags.
|
|
73
|
+
Modifier.testTag(TestTags.OrderCard)
|
|
74
|
+
composeTestRule.onNodeWithTag(TestTags.OrderCard).assertIsDisplayed()
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
Keep the registry predictable: keys follow one hierarchy (`Components.<Name>.<Element>`
|
|
78
|
+
in the source, generated as constants), a fixed element vocabulary (`Container` on
|
|
79
|
+
every component root, then `Title`, `Subtitle`, `LeadingIcon`, `TrailingIcon`,
|
|
80
|
+
`Action`, `CloseButton`, `Item`), and an indexed format such as `..._item_%s` for
|
|
81
|
+
repeated children. The tool that adds entries rejects a duplicate key or value, so
|
|
82
|
+
two components can never share a tag.
|
|
83
|
+
|
|
77
84
|
Full generated-registry and usage example: references/patterns.md#test-tags-from-a-generated-registry
|
|
78
85
|
|
|
79
86
|
## Performing Actions
|
|
@@ -130,7 +137,7 @@ the ViewModel with a fake repository rather than a mocking framework.
|
|
|
130
137
|
```kotlin
|
|
131
138
|
viewModel.uiState.test {
|
|
132
139
|
assertThat(awaitItem()).isEqualTo(HomeUiState.Loading)
|
|
133
|
-
viewModel.
|
|
140
|
+
viewModel.loadOrders("LDN", "NYC")
|
|
134
141
|
assertThat(awaitItem()).isInstanceOf(HomeUiState.Success::class.java)
|
|
135
142
|
cancelAndIgnoreRemainingEvents()
|
|
136
143
|
}
|
|
@@ -34,12 +34,12 @@ class ButtonComponentTest {
|
|
|
34
34
|
fun primaryButton_displaysLabel() {
|
|
35
35
|
composeTestRule.setContent {
|
|
36
36
|
AppTheme {
|
|
37
|
-
PrimaryButton(label = "
|
|
37
|
+
PrimaryButton(label = "Place Order", onClick = {})
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
composeTestRule
|
|
42
|
-
.onNodeWithText("
|
|
42
|
+
.onNodeWithText("Place Order")
|
|
43
43
|
.assertIsDisplayed()
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -77,19 +77,19 @@ class HomeScreenTest {
|
|
|
77
77
|
|
|
78
78
|
```kotlin
|
|
79
79
|
// By text content
|
|
80
|
-
composeTestRule.onNodeWithText("
|
|
81
|
-
composeTestRule.onNodeWithText("
|
|
82
|
-
composeTestRule.onNodeWithText("
|
|
80
|
+
composeTestRule.onNodeWithText("Place Order")
|
|
81
|
+
composeTestRule.onNodeWithText("place order", ignoreCase = true)
|
|
82
|
+
composeTestRule.onNodeWithText("Order", substring = true)
|
|
83
83
|
|
|
84
84
|
// By test tag (set via Modifier.testTag("tag"))
|
|
85
|
-
composeTestRule.onNodeWithTag("
|
|
85
|
+
composeTestRule.onNodeWithTag("order_list")
|
|
86
86
|
|
|
87
87
|
// By content description (accessibility)
|
|
88
|
-
composeTestRule.onNodeWithContentDescription("Search
|
|
88
|
+
composeTestRule.onNodeWithContentDescription("Search orders")
|
|
89
89
|
|
|
90
90
|
// Multiple nodes
|
|
91
91
|
composeTestRule.onAllNodesWithText("Select")
|
|
92
|
-
composeTestRule.onAllNodesWithTag("
|
|
92
|
+
composeTestRule.onAllNodesWithTag("order_card")
|
|
93
93
|
|
|
94
94
|
// Combined matchers
|
|
95
95
|
composeTestRule.onNode(
|
|
@@ -98,22 +98,22 @@ composeTestRule.onNode(
|
|
|
98
98
|
|
|
99
99
|
// Parent/child traversal
|
|
100
100
|
composeTestRule
|
|
101
|
-
.onNodeWithTag("
|
|
101
|
+
.onNodeWithTag("order_card")
|
|
102
102
|
.onChildren()
|
|
103
|
-
.filterToOne(hasText("
|
|
103
|
+
.filterToOne(hasText("LDN"))
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
### Setting Test Tags
|
|
107
107
|
|
|
108
108
|
```kotlin
|
|
109
109
|
@Composable
|
|
110
|
-
fun
|
|
110
|
+
fun OrderCard(order: Order, modifier: Modifier = Modifier) {
|
|
111
111
|
Card(
|
|
112
|
-
modifier = modifier.testTag("
|
|
112
|
+
modifier = modifier.testTag("order_card_${order.id}"),
|
|
113
113
|
) {
|
|
114
114
|
Text(
|
|
115
|
-
text =
|
|
116
|
-
modifier = Modifier.testTag("
|
|
115
|
+
text = order.store,
|
|
116
|
+
modifier = Modifier.testTag("order_store"),
|
|
117
117
|
)
|
|
118
118
|
}
|
|
119
119
|
}
|
|
@@ -130,19 +130,19 @@ the codegen side lives in the `android-design-tokens-codegen` skill.
|
|
|
130
130
|
```kotlin
|
|
131
131
|
// Generated -- do not edit by hand
|
|
132
132
|
object TestTags {
|
|
133
|
-
const val
|
|
134
|
-
const val
|
|
133
|
+
const val OrderCard = "order_card"
|
|
134
|
+
const val OrderStore = "order_store"
|
|
135
135
|
const val SearchField = "search_field"
|
|
136
136
|
}
|
|
137
137
|
```
|
|
138
138
|
|
|
139
139
|
```kotlin
|
|
140
140
|
// Production
|
|
141
|
-
Card(modifier = Modifier.testTag(TestTags.
|
|
141
|
+
Card(modifier = Modifier.testTag(TestTags.OrderCard)) { /* ... */ }
|
|
142
142
|
|
|
143
143
|
// Test -- same constant, so a rename is a compile error, not a silent miss
|
|
144
|
-
composeTestRule.onNodeWithTag(TestTags.
|
|
145
|
-
composeTestRule.onNodeWithTag(TestTags.SearchField).performTextInput("
|
|
144
|
+
composeTestRule.onNodeWithTag(TestTags.OrderCard).assertIsDisplayed()
|
|
145
|
+
composeTestRule.onNodeWithTag(TestTags.SearchField).performTextInput("London")
|
|
146
146
|
```
|
|
147
147
|
|
|
148
148
|
## Performing Actions
|
|
@@ -152,7 +152,7 @@ composeTestRule.onNodeWithTag(TestTags.SearchField).performTextInput("Istanbul")
|
|
|
152
152
|
composeTestRule.onNodeWithText("Book").performClick()
|
|
153
153
|
|
|
154
154
|
// Text input
|
|
155
|
-
composeTestRule.onNodeWithTag("search_field").performTextInput("
|
|
155
|
+
composeTestRule.onNodeWithTag("search_field").performTextInput("London")
|
|
156
156
|
|
|
157
157
|
// Clear and replace text
|
|
158
158
|
composeTestRule.onNodeWithTag("search_field").performTextClearance()
|
|
@@ -162,10 +162,10 @@ composeTestRule.onNodeWithTag("search_field").performTextReplacement("Ankara")
|
|
|
162
162
|
composeTestRule.onNodeWithText("Last Item").performScrollTo()
|
|
163
163
|
|
|
164
164
|
// Scroll to index in LazyColumn
|
|
165
|
-
composeTestRule.onNodeWithTag("
|
|
165
|
+
composeTestRule.onNodeWithTag("order_list").performScrollToIndex(15)
|
|
166
166
|
|
|
167
167
|
// Scroll to key in LazyColumn
|
|
168
|
-
composeTestRule.onNodeWithTag("
|
|
168
|
+
composeTestRule.onNodeWithTag("order_list").performScrollToKey("order-42")
|
|
169
169
|
|
|
170
170
|
// Swipe gestures
|
|
171
171
|
composeTestRule.onNodeWithTag("card").performTouchInput {
|
|
@@ -207,7 +207,7 @@ composeTestRule.onNodeWithTag("wifi_toggle").assertIsOn()
|
|
|
207
207
|
composeTestRule.onNodeWithTag("wifi_toggle").assertIsOff()
|
|
208
208
|
|
|
209
209
|
// Count assertions
|
|
210
|
-
composeTestRule.onAllNodesWithTag("
|
|
210
|
+
composeTestRule.onAllNodesWithTag("order_card").assertCountEquals(5)
|
|
211
211
|
|
|
212
212
|
// Focused state
|
|
213
213
|
composeTestRule.onNodeWithTag("search_field").assertIsFocused()
|
|
@@ -241,7 +241,7 @@ fun searchField_filtersResults() {
|
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
composeTestRule.onNodeWithTag("search_input").performTextInput("
|
|
244
|
+
composeTestRule.onNodeWithTag("search_input").performTextInput("London")
|
|
245
245
|
|
|
246
246
|
// Wait for async results
|
|
247
247
|
composeTestRule.waitUntil(timeoutMillis = 5_000) {
|
|
@@ -336,44 +336,44 @@ Turbine provides `test {}` extension on Flow for asserting emissions.
|
|
|
336
336
|
|
|
337
337
|
class HomeViewModelTest {
|
|
338
338
|
|
|
339
|
-
private val fakeRepository =
|
|
339
|
+
private val fakeRepository = FakeOrderRepository()
|
|
340
340
|
private lateinit var viewModel: HomeViewModel
|
|
341
341
|
|
|
342
342
|
@Before
|
|
343
343
|
fun setup() {
|
|
344
344
|
viewModel = HomeViewModel(
|
|
345
|
-
|
|
345
|
+
getOrdersUseCase = GetOrdersUseCase(fakeRepository),
|
|
346
346
|
)
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
@Test
|
|
350
|
-
fun `
|
|
351
|
-
fakeRepository.
|
|
350
|
+
fun `loadOrders emits loading then success`() = runTest {
|
|
351
|
+
fakeRepository.setOrders(listOf(testOrder))
|
|
352
352
|
|
|
353
353
|
viewModel.uiState.test {
|
|
354
354
|
// Initial state
|
|
355
355
|
assertThat(awaitItem()).isEqualTo(HomeUiState.Loading)
|
|
356
356
|
|
|
357
357
|
// Trigger load
|
|
358
|
-
viewModel.
|
|
358
|
+
viewModel.loadOrders("LDN", "NYC")
|
|
359
359
|
|
|
360
360
|
// Success state
|
|
361
361
|
val success = awaitItem()
|
|
362
362
|
assertThat(success).isInstanceOf(HomeUiState.Success::class.java)
|
|
363
|
-
assertThat((success as HomeUiState.Success).
|
|
363
|
+
assertThat((success as HomeUiState.Success).orders).hasSize(1)
|
|
364
364
|
|
|
365
365
|
cancelAndIgnoreRemainingEvents()
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
@Test
|
|
370
|
-
fun `
|
|
370
|
+
fun `loadOrders emits error on failure`() = runTest {
|
|
371
371
|
fakeRepository.setShouldFail(true)
|
|
372
372
|
|
|
373
373
|
viewModel.uiState.test {
|
|
374
374
|
skipItems(1) // skip Loading
|
|
375
375
|
|
|
376
|
-
viewModel.
|
|
376
|
+
viewModel.loadOrders("LDN", "NYC")
|
|
377
377
|
|
|
378
378
|
val error = awaitItem()
|
|
379
379
|
assertThat(error).isInstanceOf(HomeUiState.Error::class.java)
|
|
@@ -387,23 +387,23 @@ class HomeViewModelTest {
|
|
|
387
387
|
### Fake Repository
|
|
388
388
|
|
|
389
389
|
```kotlin
|
|
390
|
-
class
|
|
391
|
-
private val
|
|
390
|
+
class FakeOrderRepository : OrderRepository {
|
|
391
|
+
private val orders = MutableStateFlow<List<Order>>(emptyList())
|
|
392
392
|
private var shouldFail = false
|
|
393
393
|
|
|
394
|
-
fun
|
|
394
|
+
fun setOrders(list: List<Order>) { orders.value = list }
|
|
395
395
|
fun setShouldFail(fail: Boolean) { shouldFail = fail }
|
|
396
396
|
|
|
397
|
-
override fun
|
|
397
|
+
override fun getOrders(store: String, region: String): Flow<List<Order>> =
|
|
398
398
|
if (shouldFail) flow { throw IOException("Network error") }
|
|
399
|
-
else
|
|
399
|
+
else orders
|
|
400
400
|
|
|
401
|
-
override fun
|
|
402
|
-
|
|
401
|
+
override fun searchOrders(query: String, date: LocalDate): Flow<List<Order>> =
|
|
402
|
+
orders.map { it.filter { f -> f.store.code == query } }
|
|
403
403
|
|
|
404
|
-
override suspend fun
|
|
405
|
-
if (shouldFail) Result.failure(IOException("
|
|
406
|
-
else Result.success(
|
|
404
|
+
override suspend fun payOrder(orderId: String): Result<Payment> =
|
|
405
|
+
if (shouldFail) Result.failure(IOException("Payment failed"))
|
|
406
|
+
else Result.success(Payment(id = "P1", confirmationCode = "CONF", status = PaymentStatus.CONFIRMED))
|
|
407
407
|
}
|
|
408
408
|
```
|
|
409
409
|
|
|
@@ -413,7 +413,7 @@ Use `runTest` with `StandardTestDispatcher` or `UnconfinedTestDispatcher` to
|
|
|
413
413
|
control coroutine execution in tests.
|
|
414
414
|
|
|
415
415
|
```kotlin
|
|
416
|
-
class
|
|
416
|
+
class OrderRepositoryTest {
|
|
417
417
|
|
|
418
418
|
private val testDispatcher = StandardTestDispatcher()
|
|
419
419
|
|
|
@@ -429,13 +429,13 @@ class FlightRepositoryTest {
|
|
|
429
429
|
|
|
430
430
|
@Test
|
|
431
431
|
fun `repository returns cached data`() = runTest {
|
|
432
|
-
val repo =
|
|
432
|
+
val repo = OrderRepositoryImpl(
|
|
433
433
|
remoteDataSource = fakeRemote,
|
|
434
434
|
localDataSource = fakeLocal,
|
|
435
|
-
|
|
435
|
+
orderMapper = OrderMapper(),
|
|
436
436
|
)
|
|
437
437
|
|
|
438
|
-
val result = repo.
|
|
438
|
+
val result = repo.getOrders("LDN", "NYC").first()
|
|
439
439
|
assertThat(result).hasSize(2)
|
|
440
440
|
}
|
|
441
441
|
}
|
|
@@ -485,7 +485,7 @@ class TestDispatcherProvider(
|
|
|
485
485
|
@RunWith(RobolectricTestRunner::class)
|
|
486
486
|
@GraphicsMode(GraphicsMode.Mode.NATIVE)
|
|
487
487
|
@Config(sdk = [34])
|
|
488
|
-
class
|
|
488
|
+
class OrderCardScreenshotTest {
|
|
489
489
|
|
|
490
490
|
@get:Rule
|
|
491
491
|
val composeTestRule = createComposeRule()
|
|
@@ -498,28 +498,28 @@ class FlightCardScreenshotTest {
|
|
|
498
498
|
)
|
|
499
499
|
|
|
500
500
|
@Test
|
|
501
|
-
fun
|
|
501
|
+
fun orderCard_default() {
|
|
502
502
|
composeTestRule.setContent {
|
|
503
503
|
AppTheme {
|
|
504
|
-
|
|
504
|
+
OrderCard(order = previewOrder)
|
|
505
505
|
}
|
|
506
506
|
}
|
|
507
507
|
|
|
508
508
|
composeTestRule
|
|
509
|
-
.onNodeWithTag("
|
|
509
|
+
.onNodeWithTag("order_card")
|
|
510
510
|
.captureRoboImage()
|
|
511
511
|
}
|
|
512
512
|
|
|
513
513
|
@Test
|
|
514
|
-
fun
|
|
514
|
+
fun orderCard_dark() {
|
|
515
515
|
composeTestRule.setContent {
|
|
516
516
|
AppTheme(darkTheme = true) {
|
|
517
|
-
|
|
517
|
+
OrderCard(order = previewOrder)
|
|
518
518
|
}
|
|
519
519
|
}
|
|
520
520
|
|
|
521
521
|
composeTestRule
|
|
522
|
-
.onNodeWithTag("
|
|
522
|
+
.onNodeWithTag("order_card")
|
|
523
523
|
.captureRoboImage()
|
|
524
524
|
}
|
|
525
525
|
}
|
|
@@ -531,7 +531,7 @@ class FlightCardScreenshotTest {
|
|
|
531
531
|
// build.gradle.kts
|
|
532
532
|
// testImplementation(libs.paparazzi)
|
|
533
533
|
|
|
534
|
-
class
|
|
534
|
+
class OrderCardPaparazziTest {
|
|
535
535
|
|
|
536
536
|
@get:Rule
|
|
537
537
|
val paparazzi = Paparazzi(
|
|
@@ -540,10 +540,10 @@ class FlightCardPaparazziTest {
|
|
|
540
540
|
)
|
|
541
541
|
|
|
542
542
|
@Test
|
|
543
|
-
fun
|
|
543
|
+
fun orderCard_snapshot() {
|
|
544
544
|
paparazzi.snapshot {
|
|
545
545
|
AppTheme {
|
|
546
|
-
|
|
546
|
+
OrderCard(order = previewOrder)
|
|
547
547
|
}
|
|
548
548
|
}
|
|
549
549
|
}
|
|
@@ -599,20 +599,20 @@ Mark previews under the `screenshotTest` source set with `@PreviewTest`:
|
|
|
599
599
|
|
|
600
600
|
```kotlin
|
|
601
601
|
// src/screenshotTest/kotlin/...
|
|
602
|
-
class
|
|
602
|
+
class OrderCardScreenshots {
|
|
603
603
|
|
|
604
604
|
@PreviewTest
|
|
605
605
|
@Preview(showBackground = true)
|
|
606
606
|
@Composable
|
|
607
607
|
fun cardLight() {
|
|
608
|
-
AppTheme {
|
|
608
|
+
AppTheme { OrderCard(order = previewOrder) }
|
|
609
609
|
}
|
|
610
610
|
|
|
611
611
|
@PreviewTest
|
|
612
612
|
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
|
613
613
|
@Composable
|
|
614
614
|
fun cardDark() {
|
|
615
|
-
AppTheme(darkTheme = true) {
|
|
615
|
+
AppTheme(darkTheme = true) { OrderCard(order = previewOrder) }
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
```
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: contacts-framework
|
|
3
3
|
description: "Read, create, update, and pick contacts using the Contacts and ContactsUI frameworks. Use when fetching contact data, saving new contacts, wrapping CNContactPickerViewController in SwiftUI, handling contact permissions, or working with CNContactStore fetch and save requests."
|
|
4
|
+
metadata:
|
|
5
|
+
source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Contacts Framework
|