@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
|
@@ -1,244 +1,153 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kotlin-coroutines-expert
|
|
3
|
-
description: "
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
description: "Kotlin coroutines and Flow: scopes, structured concurrency, cancellation, exception handling, dispatcher injection, StateFlow versus SharedFlow, runTest and Turbine. Use when a coroutine leaks, hangs, swallows errors or tests flake."
|
|
4
|
+
metadata:
|
|
5
|
+
risk: safe
|
|
6
|
+
source: multi-agent-pipeline
|
|
7
|
+
date_added: "2026-09-25"
|
|
7
8
|
---
|
|
8
9
|
|
|
9
|
-
# Kotlin Coroutines
|
|
10
|
+
# Kotlin Coroutines and Flow
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
Targets Kotlin 2.x and kotlinx.coroutines 1.9 or later. Android specifics
|
|
13
|
+
(viewModelScope, lifecycle-aware collection) appear where they change the answer;
|
|
14
|
+
the rest applies to any JVM or multiplatform code.
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
## Mental model in five sentences
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
1. Every coroutine runs inside a `CoroutineScope`, and its `Job` is a child of
|
|
19
|
+
that scope's job.
|
|
20
|
+
2. A parent does not complete until all its children complete.
|
|
21
|
+
3. Cancelling a parent cancels every child; a failing child cancels its parent
|
|
22
|
+
and siblings, unless a `SupervisorJob` sits in between.
|
|
23
|
+
4. Cancellation is cooperative: it is only observed at suspension points or
|
|
24
|
+
explicit checks.
|
|
25
|
+
5. A `suspend` function should be main-safe: callers may invoke it from any
|
|
26
|
+
thread, and it moves blocking work off the caller's dispatcher itself.
|
|
16
27
|
|
|
17
|
-
|
|
18
|
-
- Use when designing reactive data streams with `Flow`.
|
|
19
|
-
- Use when debugging coroutine cancellations or exceptions.
|
|
20
|
-
- Use when writing unit tests for suspending functions or Flows.
|
|
28
|
+
## Scopes: pick the one whose lifetime matches the work
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
| Work | Scope |
|
|
31
|
+
|---|---|
|
|
32
|
+
| Loading data for a screen | `viewModelScope` (cancelled in `onCleared`) |
|
|
33
|
+
| UI-bound collection | `lifecycleScope` + `repeatOnLifecycle(STARTED)`, or `collectAsStateWithLifecycle` in Compose |
|
|
34
|
+
| Several calls that must all finish before returning | `coroutineScope { }` inside a suspend function |
|
|
35
|
+
| Work that must outlive the screen (sync, upload) | an application-level scope injected as a dependency, or WorkManager if it must survive process death |
|
|
36
|
+
| Tests | `runTest`'s `TestScope`, or `backgroundScope` for never-ending collectors |
|
|
23
37
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Always launch coroutines within a defined `CoroutineScope`. Use `coroutineScope` or `supervisorScope` to group concurrent tasks.
|
|
38
|
+
`GlobalScope` has no owner, no cancellation and no error routing. Replace it
|
|
39
|
+
with an injected application scope:
|
|
27
40
|
|
|
28
41
|
```kotlin
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
val settingsDeferred = async { settingsRepo.getSettings() }
|
|
32
|
-
|
|
33
|
-
DashboardData(
|
|
34
|
-
user = userDeferred.await(),
|
|
35
|
-
settings = settingsDeferred.await()
|
|
36
|
-
)
|
|
37
|
-
}
|
|
42
|
+
@Singleton
|
|
43
|
+
class AppScope @Inject constructor() : CoroutineScope by CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
|
38
44
|
```
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Use `CoroutineExceptionHandler` for top-level scopes, but rely on `try-catch` within suspending functions for granular control.
|
|
46
|
+
## Parallel decomposition
|
|
43
47
|
|
|
44
48
|
```kotlin
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
suspend fun loadOrderSummary(orderId: String): OrderSummary = coroutineScope {
|
|
50
|
+
val order = async { orderApi.fetch(orderId) }
|
|
51
|
+
val items = async { itemApi.fetchForOrder(orderId) }
|
|
52
|
+
val invoice = async { invoiceApi.latest(orderId) }
|
|
53
|
+
OrderSummary(order.await(), items.await(), invoice.await())
|
|
47
54
|
}
|
|
48
|
-
|
|
49
|
-
viewModelScope.launch(handler) {
|
|
50
|
-
try {
|
|
51
|
-
riskyOperation()
|
|
52
|
-
} catch (e: IOException) {
|
|
53
|
-
// Handle network error specifically
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### 3. Reactive Streams with Flow
|
|
59
|
-
|
|
60
|
-
Use `StateFlow` for state that needs to be retained, and `SharedFlow` for events.
|
|
61
|
-
|
|
62
|
-
```kotlin
|
|
63
|
-
// Cold Flow (Lazy)
|
|
64
|
-
val searchResults: Flow<List<Item>> = searchQuery
|
|
65
|
-
.debounce(300)
|
|
66
|
-
.flatMapLatest { query -> searchRepo.search(query) }
|
|
67
|
-
.flowOn(Dispatchers.IO)
|
|
68
|
-
|
|
69
|
-
// Hot Flow (State)
|
|
70
|
-
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
|
|
71
55
|
```
|
|
72
56
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
57
|
+
If any call throws, `coroutineScope` cancels the other two and rethrows. That
|
|
58
|
+
is usually what you want. When partial results are acceptable, use
|
|
59
|
+
`supervisorScope` and handle each failure at its `await`:
|
|
76
60
|
|
|
77
61
|
```kotlin
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@Module
|
|
87
|
-
@InstallIn(SingletonComponent::class)
|
|
88
|
-
object DispatchersModule {
|
|
89
|
-
@IoDispatcher
|
|
90
|
-
@Provides
|
|
91
|
-
fun provideIoDispatcher(): CoroutineDispatcher = Dispatchers.IO
|
|
92
|
-
|
|
93
|
-
@DefaultDispatcher
|
|
94
|
-
@Provides
|
|
95
|
-
fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
class ItemRepository @Inject constructor(
|
|
99
|
-
private val api: ItemApi,
|
|
100
|
-
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
|
101
|
-
) {
|
|
102
|
-
suspend fun load(id: String): Item = withContext(ioDispatcher) {
|
|
103
|
-
api.fetch(id).toDomain()
|
|
104
|
-
}
|
|
62
|
+
suspend fun loadDashboard(): Dashboard = supervisorScope {
|
|
63
|
+
val recent = async { orderRepository.recent() }
|
|
64
|
+
val promos = async { promoRepository.active() }
|
|
65
|
+
Dashboard(
|
|
66
|
+
recentOrders = recent.await(),
|
|
67
|
+
promotions = runCatchingCancellable { promos.await() }.getOrDefault(emptyList()),
|
|
68
|
+
)
|
|
105
69
|
}
|
|
106
70
|
```
|
|
107
71
|
|
|
108
|
-
|
|
72
|
+
## Cancellation
|
|
109
73
|
|
|
110
|
-
|
|
74
|
+
- Suspending library calls (`delay`, `withContext`, `Flow.collect`, Retrofit and
|
|
75
|
+
Room suspend functions) check cancellation for you.
|
|
76
|
+
- A CPU loop must check: call `ensureActive()` or `yield()` every iteration.
|
|
77
|
+
- Blocking Java I/O does not observe cancellation; wrap it in
|
|
78
|
+
`runInterruptible(Dispatchers.IO) { }` if it can block for long.
|
|
79
|
+
- Cleanup that itself suspends needs `withContext(NonCancellable) { }` inside
|
|
80
|
+
`finally`, otherwise the first suspension throws immediately.
|
|
81
|
+
- Timeouts: `withTimeout` throws `TimeoutCancellationException`;
|
|
82
|
+
`withTimeoutOrNull` returns null. Prefer the latter at boundaries.
|
|
111
83
|
|
|
112
|
-
###
|
|
84
|
+
### Never swallow CancellationException
|
|
113
85
|
|
|
114
|
-
|
|
86
|
+
`catch (e: Exception)` and `runCatching` both catch `CancellationException`,
|
|
87
|
+
which keeps a cancelled coroutine running. Rethrow it:
|
|
115
88
|
|
|
116
89
|
```kotlin
|
|
117
|
-
|
|
90
|
+
inline fun <T> runCatchingCancellable(block: () -> T): Result<T> =
|
|
118
91
|
try {
|
|
119
|
-
|
|
92
|
+
Result.success(block())
|
|
120
93
|
} catch (e: CancellationException) {
|
|
121
94
|
throw e
|
|
122
|
-
} catch (e:
|
|
123
|
-
|
|
95
|
+
} catch (e: Exception) {
|
|
96
|
+
Result.failure(e)
|
|
124
97
|
}
|
|
125
98
|
```
|
|
126
99
|
|
|
127
|
-
|
|
100
|
+
## Exceptions
|
|
128
101
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
} catch (e: CancellationException) {
|
|
136
|
-
throw e
|
|
137
|
-
} catch (e: Throwable) {
|
|
138
|
-
null
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
ScreenData(core = core.await(), banner = banner.await())
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Examples
|
|
102
|
+
| Builder | Where the exception goes |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `launch` | propagates to the parent job; if it reaches a root scope, to its `CoroutineExceptionHandler`, else the thread's uncaught handler (crash on Android) |
|
|
105
|
+
| `async` | stored in the `Deferred`, thrown at `await()`, and also propagates to the parent unless under a supervisor |
|
|
106
|
+
| `coroutineScope` | rethrown to the caller after cancelling siblings |
|
|
107
|
+
| `supervisorScope` / `SupervisorJob` | a child's failure does not cancel siblings; each `launch` child needs its own handling |
|
|
146
108
|
|
|
147
|
-
|
|
109
|
+
A `CoroutineExceptionHandler` is a last-resort logger. It only works on a root
|
|
110
|
+
coroutine or a direct child of a supervisor, and it cannot resume the work.
|
|
111
|
+
Handle expected failures with `try`/`catch` or `Result` close to the call.
|
|
148
112
|
|
|
149
|
-
|
|
150
|
-
suspend fun fetchDataWithErrorHandling() = supervisorScope {
|
|
151
|
-
val task1 = async {
|
|
152
|
-
try { api.fetchA() } catch (e: Exception) { null }
|
|
153
|
-
}
|
|
154
|
-
val task2 = async { api.fetchB() }
|
|
155
|
-
|
|
156
|
-
// If task2 fails, task1 is NOT cancelled because of supervisorScope
|
|
157
|
-
val result1 = task1.await()
|
|
158
|
-
val result2 = task2.await() // May throw
|
|
159
|
-
}
|
|
160
|
-
```
|
|
113
|
+
## Dispatchers
|
|
161
114
|
|
|
162
|
-
|
|
115
|
+
- `Dispatchers.Main.immediate` for UI state updates (the default in
|
|
116
|
+
`viewModelScope`).
|
|
117
|
+
- `Dispatchers.IO` for blocking I/O; it is elastic, 64 threads by default.
|
|
118
|
+
- `Dispatchers.Default` for CPU work, sized to the core count.
|
|
119
|
+
- `Dispatchers.IO.limitedParallelism(n)` for a bounded pool, for example a
|
|
120
|
+
database that tolerates only one writer.
|
|
163
121
|
|
|
164
|
-
|
|
122
|
+
Inject dispatchers instead of hard-coding them so tests can substitute a
|
|
123
|
+
`TestDispatcher`:
|
|
165
124
|
|
|
166
125
|
```kotlin
|
|
167
|
-
class
|
|
168
|
-
|
|
126
|
+
class NoteRepository(
|
|
127
|
+
private val dao: NoteDao,
|
|
128
|
+
private val io: CoroutineDispatcher = Dispatchers.IO,
|
|
169
129
|
) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
fun persist(entry: CacheEntry) {
|
|
173
|
-
scope.launch {
|
|
174
|
-
try {
|
|
175
|
-
dao.upsert(entry)
|
|
176
|
-
} catch (e: CancellationException) {
|
|
177
|
-
throw e
|
|
178
|
-
} catch (e: Throwable) {
|
|
179
|
-
logger.warn("cache write failed", e)
|
|
180
|
-
}
|
|
181
|
-
}
|
|
130
|
+
suspend fun export(file: File) = withContext(io) {
|
|
131
|
+
file.writeText(dao.all().joinToString("\n") { it.body })
|
|
182
132
|
}
|
|
183
133
|
}
|
|
184
134
|
```
|
|
185
135
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Guard a one-time async initialization with `Mutex.withLock`, not `synchronized`. `synchronized` blocks the thread and cannot host suspend calls; `withLock` suspends the coroutine and releases cooperatively.
|
|
189
|
-
|
|
190
|
-
```kotlin
|
|
191
|
-
class TokenProvider @Inject constructor(private val api: AuthApi) {
|
|
192
|
-
private val mutex = Mutex()
|
|
193
|
-
@Volatile private var cached: Token? = null
|
|
194
|
-
|
|
195
|
-
suspend fun token(): Token {
|
|
196
|
-
cached?.let { return it }
|
|
197
|
-
return mutex.withLock {
|
|
198
|
-
cached ?: api.fetchToken().also { cached = it }
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### Example 4: Awaiting a Suspend Result Inside a Synchronous Callback
|
|
205
|
-
|
|
206
|
-
A framework callback that must return a value synchronously cannot call a suspend function directly, and `runBlocking` on the main or a callback thread risks deadlock. Bridge with a scoped `launch`, a lock/condition, and `withTimeout` so a stalled producer cannot block forever.
|
|
207
|
-
|
|
208
|
-
```kotlin
|
|
209
|
-
fun interceptSync(request: Request): Response {
|
|
210
|
-
val lock = ReentrantLock()
|
|
211
|
-
val done = lock.newCondition()
|
|
212
|
-
var result: Response? = null
|
|
213
|
-
|
|
214
|
-
scope.launch {
|
|
215
|
-
val value = try {
|
|
216
|
-
withTimeout(5_000) { resolver.resolve(request) }
|
|
217
|
-
} catch (e: Throwable) {
|
|
218
|
-
Response.passthrough(request)
|
|
219
|
-
}
|
|
220
|
-
lock.withLock {
|
|
221
|
-
result = value
|
|
222
|
-
done.signalAll()
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
lock.withLock {
|
|
227
|
-
while (result == null) done.await()
|
|
228
|
-
return result!!
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
```
|
|
136
|
+
Room and Retrofit suspend functions already switch threads; wrapping them in
|
|
137
|
+
`withContext(io)` is harmless but unnecessary.
|
|
232
138
|
|
|
233
|
-
##
|
|
139
|
+
## Review checklist
|
|
234
140
|
|
|
235
|
-
-
|
|
236
|
-
-
|
|
237
|
-
-
|
|
238
|
-
-
|
|
239
|
-
-
|
|
141
|
+
- No `GlobalScope`, no `runBlocking` outside `main` and tests.
|
|
142
|
+
- Each coroutine's scope matches the lifetime of its work.
|
|
143
|
+
- `CancellationException` is rethrown everywhere exceptions are caught.
|
|
144
|
+
- Long loops call `ensureActive()`; blocking calls are on `IO` or interruptible.
|
|
145
|
+
- Dispatchers are injected; suspend functions are main-safe.
|
|
146
|
+
- Flows exposed to UI are `StateFlow` built with `stateIn` and `WhileSubscribed`.
|
|
147
|
+
- One-shot events have exactly one consumer and are not lost on rotation.
|
|
148
|
+
- `callbackFlow` ends with `awaitClose`.
|
|
149
|
+
- Tests use `runTest`, a shared scheduler and Turbine; no `Thread.sleep`.
|
|
240
150
|
|
|
241
|
-
##
|
|
151
|
+
## References
|
|
242
152
|
|
|
243
|
-
|
|
244
|
-
**Solution:** Ensure you are using `runTest` and injecting `TestDispatcher` into your classes so you can control virtual time.
|
|
153
|
+
- `references/patterns.md`: Flow operators, callbackFlow, StateFlow/SharedFlow/Channel and stateIn; runTest, schedulers, MainDispatcherRule and Turbine. Load it when the task reaches those topics.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Coroutines: Flow and testing
|
|
2
|
+
|
|
3
|
+
Loaded on demand from `../SKILL.md`.
|
|
4
|
+
|
|
5
|
+
## Flow
|
|
6
|
+
|
|
7
|
+
A `Flow` is cold: the block runs once per collector, from scratch.
|
|
8
|
+
|
|
9
|
+
### Operators worth knowing by reflex
|
|
10
|
+
|
|
11
|
+
| Goal | Operator |
|
|
12
|
+
|---|---|
|
|
13
|
+
| React to the latest input only, cancel stale work | `mapLatest`, `flatMapLatest`, `collectLatest` |
|
|
14
|
+
| Search-as-you-type | `debounce(300)` then `distinctUntilChanged()` then `flatMapLatest` |
|
|
15
|
+
| Merge several state sources into one | `combine(a, b, c) { ... }` |
|
|
16
|
+
| Pair up emissions one to one | `zip` |
|
|
17
|
+
| Run upstream on another dispatcher | `flowOn(Dispatchers.IO)` (affects operators above it only) |
|
|
18
|
+
| Handle upstream errors | `catch { emit(fallback) }` (does not catch downstream errors) |
|
|
19
|
+
| Retry transient failures | `retryWhen { cause, attempt -> cause is IOException && attempt < 3 }` |
|
|
20
|
+
| Side effect at boundaries | `onStart`, `onEach`, `onCompletion` |
|
|
21
|
+
| Absorb a fast producer | `buffer()`, `conflate()` |
|
|
22
|
+
|
|
23
|
+
Never call `withContext` inside `flow { }` to change the emitting context; it
|
|
24
|
+
throws an `IllegalStateException`. Use `flowOn`, or `channelFlow` when emitting
|
|
25
|
+
from several coroutines.
|
|
26
|
+
|
|
27
|
+
### Bridging callbacks
|
|
28
|
+
|
|
29
|
+
```kotlin
|
|
30
|
+
fun ConnectivityManager.onlineUpdates(): Flow<Boolean> = callbackFlow {
|
|
31
|
+
val callback = object : ConnectivityManager.NetworkCallback() {
|
|
32
|
+
override fun onAvailable(network: Network) { trySend(true) }
|
|
33
|
+
override fun onLost(network: Network) { trySend(false) }
|
|
34
|
+
}
|
|
35
|
+
registerDefaultNetworkCallback(callback)
|
|
36
|
+
awaitClose { unregisterNetworkCallback(callback) }
|
|
37
|
+
}.distinctUntilChanged()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`awaitClose` is mandatory; without it the flow completes immediately and the
|
|
41
|
+
listener leaks.
|
|
42
|
+
|
|
43
|
+
### Hot streams
|
|
44
|
+
|
|
45
|
+
| Type | Holds a value | Replays | Drops when nobody listens | Use for |
|
|
46
|
+
|---|---|---|---|---|
|
|
47
|
+
| `StateFlow` | yes, always | latest value | no, keeps the latest | UI state, equality-conflated |
|
|
48
|
+
| `SharedFlow` | optional | configurable `replay` | depends on buffer config | broadcasting to many collectors |
|
|
49
|
+
| `Channel` | no | no | no, suspends or buffers until received | one-shot events for exactly one consumer |
|
|
50
|
+
|
|
51
|
+
Convert a cold flow to state in a ViewModel with `stateIn`:
|
|
52
|
+
|
|
53
|
+
```kotlin
|
|
54
|
+
val state: StateFlow<ProductListState> =
|
|
55
|
+
combine(repository.products(), filter) { products, f -> ProductListState(products.filter(f::matches)) }
|
|
56
|
+
.stateIn(
|
|
57
|
+
scope = viewModelScope,
|
|
58
|
+
started = SharingStarted.WhileSubscribed(5_000),
|
|
59
|
+
initialValue = ProductListState.Loading,
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`WhileSubscribed(5_000)` keeps the upstream alive across a configuration change
|
|
64
|
+
and stops it when the screen is really gone. Update `MutableStateFlow` with
|
|
65
|
+
`update { it.copy(...) }` for an atomic read-modify-write.
|
|
66
|
+
|
|
67
|
+
## Testing
|
|
68
|
+
|
|
69
|
+
```kotlin
|
|
70
|
+
class ProductListViewModelTest {
|
|
71
|
+
@get:Rule val mainRule = MainDispatcherRule()
|
|
72
|
+
|
|
73
|
+
@Test
|
|
74
|
+
fun filterNarrowsProducts() = runTest {
|
|
75
|
+
val repo = FakeProductRepository(listOf(product("mug"), product("lamp")))
|
|
76
|
+
val vm = ProductListViewModel(repo)
|
|
77
|
+
|
|
78
|
+
vm.state.test {
|
|
79
|
+
assertEquals(ProductListState.Loading, awaitItem())
|
|
80
|
+
assertEquals(2, (awaitItem() as ProductListState.Ready).items.size)
|
|
81
|
+
vm.setQuery("mug")
|
|
82
|
+
assertEquals(1, (awaitItem() as ProductListState.Ready).items.size)
|
|
83
|
+
cancelAndIgnoreRemainingEvents()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
class MainDispatcherRule(
|
|
89
|
+
private val dispatcher: TestDispatcher = UnconfinedTestDispatcher(),
|
|
90
|
+
) : TestWatcher() {
|
|
91
|
+
override fun starting(description: Description) = Dispatchers.setMain(dispatcher)
|
|
92
|
+
override fun finished(description: Description) = Dispatchers.resetMain()
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- `runTest` skips `delay` using virtual time; `advanceTimeBy`,
|
|
97
|
+
`advanceUntilIdle` and `testScheduler.currentTime` control it.
|
|
98
|
+
- Share one `TestCoroutineScheduler` between every injected `TestDispatcher`
|
|
99
|
+
in a test, or virtual time diverges.
|
|
100
|
+
- `StandardTestDispatcher` queues work until advanced (good for ordering
|
|
101
|
+
assertions); `UnconfinedTestDispatcher` runs eagerly (good for collectors).
|
|
102
|
+
- Start never-ending collectors in `backgroundScope` so the test can finish.
|
|
103
|
+
- Turbine's `test { }` fails on unconsumed events; that is the point.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: live-activities
|
|
3
3
|
description: "Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time updating widgets for the Lock Screen and Dynamic Island - delivery tracking, sports scores, ride-sharing status, workout timers, media playback, or any time-sensitive information that updates in real time. Also use when working with ActivityKit, ActivityAttributes, Activity lifecycle (request/update/end), Dynamic Island layouts (compact/minimal/expanded), push-to-update Live Activities, or Lock Screen live widgets."
|
|
4
|
+
metadata:
|
|
5
|
+
source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# ActivityKit
|
|
@@ -365,7 +367,7 @@ the system-managed push update budget. When cadence matters, check
|
|
|
365
367
|
|
|
366
368
|
Schedule a Live Activity to start at a future time. The system starts the
|
|
367
369
|
activity automatically without the app being in the foreground. Use for events
|
|
368
|
-
with known start times (sports games,
|
|
370
|
+
with known start times (sports games, product launches, scheduled deliveries).
|
|
369
371
|
|
|
370
372
|
```swift
|
|
371
373
|
let scheduledDate = Calendar.current.date(
|
|
@@ -390,7 +392,7 @@ let activity = try Activity.request(
|
|
|
390
392
|
|
|
391
393
|
Use the iOS 18+ `style:` request parameter to choose persistence behavior. Use
|
|
392
394
|
`.standard` for persistent Live Activities such as deliveries, rides, sports
|
|
393
|
-
scores, timers, and
|
|
395
|
+
scores, timers, and order-status boards. Use `.transient` only for a
|
|
394
396
|
short-lived expanded Dynamic Island presentation; it can auto-end when the user
|
|
395
397
|
locks the device, collapses or shrinks the expanded presentation, leaves the
|
|
396
398
|
app, or does other work outside Dynamic Island.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"skill_name": "
|
|
2
|
+
"skill_name": "live-activities",
|
|
3
3
|
"evals": [
|
|
4
4
|
{
|
|
5
5
|
"id": 1,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"id": 2,
|
|
19
|
-
"prompt": "Review this Live Activity plan for mistakes: use Activity.request(attributes:content:pushType:start:) on iOS 26 to schedule
|
|
19
|
+
"prompt": "Review this Live Activity plan for mistakes: use Activity.request(attributes:content:pushType:start:) on iOS 26 to schedule an order-status board; use style: .transient but guard it as iOS 26 only; send a push-to-start payload without alert because the user already opted into notifications; set NSSupportsLiveActivitiesFrequentUpdates and push updates every 30 seconds; say ended activities always disappear after 8 hours.",
|
|
20
20
|
"expected_output": "A correction-focused review that identifies stale or inaccurate ActivityKit claims and replaces them with current Apple-source behavior.",
|
|
21
21
|
"files": [],
|
|
22
22
|
"expectations": [
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: localization-reuse-map
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
element
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
to new keys for this screen", "which legacy translations can we reuse", "reuse existing translations",
|
|
12
|
-
"CMS copy from Figma annotations", "localization excel", "CMS import sheet", "/localization-reuse-map".
|
|
4
|
+
Builds a per-screen localization-reuse map for one redesigned screen (iOS, Android, web): pairs each
|
|
5
|
+
UI element's new key and values with the legacy key per platform and the live CMS copy from Figma Dev
|
|
6
|
+
Mode annotations, recommends reuse, review or new for the content team to confirm, renders a key-to-UI
|
|
7
|
+
overlay, publishes a Confluence page, and flags error and dynamic keys the registry misses. Use when
|
|
8
|
+
mapping one redesigned screen's strings to legacy ones. Triggers - localization reuse map, map old
|
|
9
|
+
keys to new keys, reuse legacy translations, CMS copy from Figma annotations, localization excel, CMS
|
|
10
|
+
import sheet, /localization-reuse-map.
|
|
13
11
|
---
|
|
14
12
|
|
|
15
13
|
# Localization Reuse Map - old↔new localization map for one screen
|
package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md
CHANGED
|
@@ -33,7 +33,7 @@ what it **wires**; neither alone is complete. Do all three:
|
|
|
33
33
|
gh api "repos/<org>/<specs-repo>/contents/design-export/<project>/screens/<screen-slug>/components-used.md" -H "Accept: application/vnd.github.raw"
|
|
34
34
|
```
|
|
35
35
|
Read **every state frame** of the screen (empty / 1-item / filled) - components only present in the
|
|
36
|
-
filled state (e.g.
|
|
36
|
+
filled state (e.g. an item list) still belong to the screen. The folder also has `screenshot.png`,
|
|
37
37
|
`tree.json` (node ids), `tokens.json`. *(Live alternative if a frame isn't exported: Figma REST via a
|
|
38
38
|
host Figma tool - REST works with a token; MCP/live needs Figma Desktop in Dev Mode. The export is
|
|
39
39
|
preferred - single-repo.)*
|
|
@@ -42,7 +42,7 @@ what it **wires**; neither alone is complete. Do all three:
|
|
|
42
42
|
python3 -c "import json;d=json.load(open('Resources/Figma/Components/<NODE-DASH>.json'));print([k['key'] for k in d.get('localizationKeys',[])])"
|
|
43
43
|
```
|
|
44
44
|
These include keys the component renders that **never appear in the screen code** (e.g.
|
|
45
|
-
`
|
|
45
|
+
`ItemListGroup.Title`, `ItemListRow.Delete`). Beware the inverse: a shared
|
|
46
46
|
component (e.g. `HeaderMain`, `BottomActions`) owns many keys the screen does **not** use because the
|
|
47
47
|
screen passes its own title in - confirm against the code.
|
|
48
48
|
3. **What the screen wires** - read the scene/screen file: each `LocalizationStringKey.<Ns>.<leaf>` call
|
|
@@ -66,7 +66,7 @@ keys: map once where that component is mapped - flag, don't duplicate per scre
|
|
|
66
66
|
# then fetch each cell class and grep its keys:
|
|
67
67
|
gh api ".../Forms/TextInputCell/PresentationModels/<Field>TextInputCellPresentationModel.swift" -H "Accept: application/vnd.github.raw" | grep -oE '"[^"]+"\.localized'
|
|
68
68
|
```
|
|
69
|
-
This is how `NewSurnameReq` / `
|
|
69
|
+
This is how `NewSurnameReq` / `OrderNumber` / `ShippingAddressPlaceHolder` surface - a VM-only grep
|
|
70
70
|
misses them. Keys are the string literal before `.localized`.
|
|
71
71
|
3. **Android.** Layout XML carries labels as `@string/Key`; fragment carries runtime strings as `R.string.`:
|
|
72
72
|
```bash
|
package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py
CHANGED
|
@@ -9,9 +9,9 @@ Why a script: the model otherwise hand-copies 8 languages x N keys out of JSON
|
|
|
9
9
|
files - slow, token-heavy, and error-prone. This is pure file IO, so it is a
|
|
10
10
|
script. Read-only; touches nothing.
|
|
11
11
|
|
|
12
|
-
Key-form handling: code often references a key as `
|
|
12
|
+
Key-form handling: code often references a key as `AddAddress.continueButton`
|
|
13
13
|
(camelCase leaf) while the Suggested filename PascalCases every dotted segment
|
|
14
|
-
(`
|
|
14
|
+
(`AddAddress.ContinueButton.json`). We normalise the first character of
|
|
15
15
|
each segment to upper-case before resolving, so either form works as input.
|
|
16
16
|
Accessibility keys live under `AccessibilityStrings/Sources/Suggested/` - pass
|
|
17
17
|
`--domain accessibility` for those.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: macos-menubar-tuist-app
|
|
3
3
|
description: "Build, refactor, or review SwiftUI macOS menubar apps that use Tuist. Use when building, refactoring or reviewing a SwiftUI macOS menubar app that uses Tuist."
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
risk: safe
|
|
6
|
+
source: "Dimillian/Skills (MIT)"
|
|
7
|
+
date_added: "2026-03-25"
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# macos-menubar-tuist-app
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: macos-spm-app-packaging
|
|
3
3
|
description: "Scaffold, build, sign, and package SwiftPM macOS apps without Xcode projects. Use when a SwiftPM macOS app has to be built, signed or packaged without an Xcode project."
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
risk: safe
|
|
6
|
+
source: "Dimillian/Skills (MIT)"
|
|
7
|
+
date_added: "2026-03-25"
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# macOS SwiftPM App Packaging (No Xcode)
|
|
10
11
|
|
|
11
12
|
## Overview
|
|
12
13
|
Bootstrap a complete SwiftPM macOS app folder, then build, package, and run it without Xcode. Use `assets/templates/bootstrap/` for the starter layout and `references/packaging.md` + `references/release.md` for packaging and release details.
|
|
14
|
+
Read `references/scaffold.md` when building the package from `swift package init` by hand instead of copying the bootstrap template.
|
|
13
15
|
|
|
14
16
|
## When to Use
|
|
15
17
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mapkit-location
|
|
3
3
|
description: "Implement, review, or improve maps and location features in iOS/macOS apps using MapKit and CoreLocation. Use when working with Map views, annotations, markers, polylines, user location tracking, geocoding, reverse geocoding, search/autocomplete, directions and routes, geofencing, region monitoring, CLLocationUpdate async streams, or location authorization flows. Also use when working with maps, coordinates, addresses, places, directions, distance calculations, or location-based features in Swift apps."
|
|
4
|
+
metadata:
|
|
5
|
+
source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# MapKit
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: metrickit-diagnostics
|
|
3
3
|
description: "Collect and analyze on-device performance metrics and crash diagnostics using MetricKit. Use when setting up MXMetricManager, handling MXMetricPayload or MXDiagnosticPayload, processing crash/hang/disk-write diagnostics via MXCallStackTree, adding custom signpost metrics, correcting mxSignpost or extended launch measurement code, or uploading telemetry to an analytics backend."
|
|
4
|
+
metadata:
|
|
5
|
+
source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# MetricKit
|