opencode-starterkit 1.0.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/README.md +47 -0
- package/baseline/.env.example +196 -0
- package/baseline/.template-manifest.json +646 -0
- package/baseline/.version +1 -0
- package/baseline/AGENTS.md +410 -0
- package/baseline/AGENT_ALIGNMENT.md +564 -0
- package/baseline/README.md +79 -0
- package/baseline/agent/build.md +373 -0
- package/baseline/agent/explore.md +96 -0
- package/baseline/agent/general.md +186 -0
- package/baseline/agent/painter.md +74 -0
- package/baseline/agent/plan.md +435 -0
- package/baseline/agent/review.md +243 -0
- package/baseline/agent/runner.md +79 -0
- package/baseline/agent/scout.md +100 -0
- package/baseline/agent/vision.md +91 -0
- package/baseline/command/compound.md +143 -0
- package/baseline/command/create.md +213 -0
- package/baseline/command/design.md +112 -0
- package/baseline/command/handoff.md +147 -0
- package/baseline/command/init-context.md +273 -0
- package/baseline/command/init-user.md +105 -0
- package/baseline/command/init.md +117 -0
- package/baseline/command/lfg.md +170 -0
- package/baseline/command/plan.md +355 -0
- package/baseline/command/pr.md +161 -0
- package/baseline/command/research.md +125 -0
- package/baseline/command/resume.md +87 -0
- package/baseline/command/review-codebase.md +131 -0
- package/baseline/command/ship.md +342 -0
- package/baseline/command/start.md +158 -0
- package/baseline/command/status.md +117 -0
- package/baseline/command/ui-review.md +92 -0
- package/baseline/command/ui-slop-check.md +146 -0
- package/baseline/command/verify.md +160 -0
- package/baseline/context/README.md +29 -0
- package/baseline/dcp.jsonc +72 -0
- package/baseline/memory/README.md +89 -0
- package/baseline/memory/_templates/design.md +59 -0
- package/baseline/memory/_templates/prd.md +192 -0
- package/baseline/memory/_templates/project.md +58 -0
- package/baseline/memory/_templates/proposal.md +38 -0
- package/baseline/memory/_templates/roadmap.md +93 -0
- package/baseline/memory/_templates/state.md +89 -0
- package/baseline/memory/_templates/tasks.md +198 -0
- package/baseline/memory/_templates/tech-stack.md +85 -0
- package/baseline/memory/_templates/user.md +26 -0
- package/baseline/memory/project/gotchas.md +67 -0
- package/baseline/memory/project/project.md +92 -0
- package/baseline/memory/project/roadmap.md +142 -0
- package/baseline/memory/project/state.md +84 -0
- package/baseline/memory/project/tech-stack.md +53 -0
- package/baseline/memory/project/user.md +38 -0
- package/baseline/memory/research/benchmark-framework.md +162 -0
- package/baseline/memory/research/ccpm-analysis.md +334 -0
- package/baseline/memory/research/context-management-analysis.md +685 -0
- package/baseline/memory/research/effectiveness-audit.md +213 -0
- package/baseline/memory/research/opencode-mcp-bug-report.md +129 -0
- package/baseline/memory/research/openspec-analysis.md +226 -0
- package/baseline/memory/session-context.md +40 -0
- package/baseline/opencode.json +1431 -0
- package/baseline/opencode.json.tui-migration.bak +1380 -0
- package/baseline/package-lock.json +87 -0
- package/baseline/package.json +21 -0
- package/baseline/plans/1768385996691-silent-wizard.md +247 -0
- package/baseline/plans/1770006237537-mighty-otter.md +418 -0
- package/baseline/plans/1770006913647-glowing-forest.md +170 -0
- package/baseline/plans/1770013678126-witty-planet.md +278 -0
- package/baseline/plans/1770112267595-shiny-rocket.md +258 -0
- package/baseline/plans/swarm-protocol.md +123 -0
- package/baseline/plugin/README.md +70 -0
- package/baseline/plugin/copilot-auth.ts +607 -0
- package/baseline/plugin/lib/capture.ts +177 -0
- package/baseline/plugin/lib/context.ts +198 -0
- package/baseline/plugin/lib/curator.ts +234 -0
- package/baseline/plugin/lib/db/maintenance.ts +312 -0
- package/baseline/plugin/lib/db/observations.ts +299 -0
- package/baseline/plugin/lib/db/pipeline.ts +520 -0
- package/baseline/plugin/lib/db/schema.ts +356 -0
- package/baseline/plugin/lib/db/types.ts +211 -0
- package/baseline/plugin/lib/distill.ts +376 -0
- package/baseline/plugin/lib/inject.ts +126 -0
- package/baseline/plugin/lib/memory-admin-tools.ts +188 -0
- package/baseline/plugin/lib/memory-db.ts +58 -0
- package/baseline/plugin/lib/memory-helpers.ts +111 -0
- package/baseline/plugin/lib/memory-hooks.ts +195 -0
- package/baseline/plugin/lib/memory-tools.ts +341 -0
- package/baseline/plugin/lib/notify.ts +81 -0
- package/baseline/plugin/memory.ts +89 -0
- package/baseline/plugin/notification.ts.bak +64 -0
- package/baseline/plugin/package.json +7 -0
- package/baseline/plugin/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +178 -0
- package/baseline/plugin/sdk/copilot/chat/get-response-metadata.ts +15 -0
- package/baseline/plugin/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +19 -0
- package/baseline/plugin/sdk/copilot/chat/openai-compatible-api-types.ts +72 -0
- package/baseline/plugin/sdk/copilot/chat/openai-compatible-chat-language-model.ts +833 -0
- package/baseline/plugin/sdk/copilot/chat/openai-compatible-chat-options.ts +30 -0
- package/baseline/plugin/sdk/copilot/chat/openai-compatible-metadata-extractor.ts +48 -0
- package/baseline/plugin/sdk/copilot/chat/openai-compatible-prepare-tools.ts +92 -0
- package/baseline/plugin/sdk/copilot/copilot-provider.ts +94 -0
- package/baseline/plugin/sdk/copilot/index.ts +5 -0
- package/baseline/plugin/sdk/copilot/openai-compatible-error.ts +30 -0
- package/baseline/plugin/sessions.ts +428 -0
- package/baseline/plugin/skill-mcp.ts +618 -0
- package/baseline/plugin/tsconfig.json +16 -0
- package/baseline/skill/accessibility-audit/SKILL.md +191 -0
- package/baseline/skill/agent-browser/SKILL.md +413 -0
- package/baseline/skill/agent-teams/SKILL.md +268 -0
- package/baseline/skill/augment-context-engine/SKILL.md +122 -0
- package/baseline/skill/augment-context-engine/mcp.json +6 -0
- package/baseline/skill/beads/SKILL.md +181 -0
- package/baseline/skill/beads/references/BEST_PRACTICES.md +27 -0
- package/baseline/skill/beads/references/BOUNDARIES.md +219 -0
- package/baseline/skill/beads/references/DEPENDENCIES.md +124 -0
- package/baseline/skill/beads/references/EXAMPLES.md +45 -0
- package/baseline/skill/beads/references/FILE_CLAIMING.md +101 -0
- package/baseline/skill/beads/references/GIT_SYNC.md +25 -0
- package/baseline/skill/beads/references/HIERARCHY.md +71 -0
- package/baseline/skill/beads/references/MULTI_AGENT.md +40 -0
- package/baseline/skill/beads/references/RESUMABILITY.md +177 -0
- package/baseline/skill/beads/references/SESSION_PROTOCOL.md +61 -0
- package/baseline/skill/beads/references/TASK_CREATION.md +38 -0
- package/baseline/skill/beads/references/TROUBLESHOOTING.md +38 -0
- package/baseline/skill/beads/references/WORKFLOWS.md +226 -0
- package/baseline/skill/beads-bridge/SKILL.md +321 -0
- package/baseline/skill/brainstorming/SKILL.md +114 -0
- package/baseline/skill/chrome-devtools/SKILL.md +76 -0
- package/baseline/skill/chrome-devtools/mcp.json +19 -0
- package/baseline/skill/cloudflare/SKILL.md +253 -0
- package/baseline/skill/cloudflare/references/agents-sdk/README.md +35 -0
- package/baseline/skill/cloudflare/references/agents-sdk/api.md +100 -0
- package/baseline/skill/cloudflare/references/agents-sdk/configuration.md +99 -0
- package/baseline/skill/cloudflare/references/agents-sdk/gotchas.md +59 -0
- package/baseline/skill/cloudflare/references/agents-sdk/patterns.md +89 -0
- package/baseline/skill/cloudflare/references/ai-gateway/README.md +695 -0
- package/baseline/skill/cloudflare/references/ai-search/README.md +14 -0
- package/baseline/skill/cloudflare/references/ai-search/api.md +38 -0
- package/baseline/skill/cloudflare/references/ai-search/configuration.md +52 -0
- package/baseline/skill/cloudflare/references/ai-search/gotchas.md +41 -0
- package/baseline/skill/cloudflare/references/ai-search/patterns.md +45 -0
- package/baseline/skill/cloudflare/references/analytics-engine/README.md +14 -0
- package/baseline/skill/cloudflare/references/analytics-engine/api.md +27 -0
- package/baseline/skill/cloudflare/references/analytics-engine/configuration.md +45 -0
- package/baseline/skill/cloudflare/references/analytics-engine/gotchas.md +3 -0
- package/baseline/skill/cloudflare/references/analytics-engine/patterns.md +36 -0
- package/baseline/skill/cloudflare/references/api/README.md +21 -0
- package/baseline/skill/cloudflare/references/api/api.md +31 -0
- package/baseline/skill/cloudflare/references/api/configuration.md +20 -0
- package/baseline/skill/cloudflare/references/api/gotchas.md +28 -0
- package/baseline/skill/cloudflare/references/api/patterns.md +47 -0
- package/baseline/skill/cloudflare/references/api-shield/README.md +20 -0
- package/baseline/skill/cloudflare/references/api-shield/api.md +78 -0
- package/baseline/skill/cloudflare/references/api-shield/configuration.md +128 -0
- package/baseline/skill/cloudflare/references/api-shield/gotchas.md +51 -0
- package/baseline/skill/cloudflare/references/api-shield/patterns.md +145 -0
- package/baseline/skill/cloudflare/references/argo-smart-routing/README.md +16 -0
- package/baseline/skill/cloudflare/references/argo-smart-routing/api.md +50 -0
- package/baseline/skill/cloudflare/references/argo-smart-routing/configuration.md +53 -0
- package/baseline/skill/cloudflare/references/argo-smart-routing/gotchas.md +16 -0
- package/baseline/skill/cloudflare/references/argo-smart-routing/patterns.md +45 -0
- package/baseline/skill/cloudflare/references/bindings/README.md +14 -0
- package/baseline/skill/cloudflare/references/bindings/api.md +3 -0
- package/baseline/skill/cloudflare/references/bindings/configuration.md +58 -0
- package/baseline/skill/cloudflare/references/bindings/gotchas.md +35 -0
- package/baseline/skill/cloudflare/references/bindings/patterns.md +37 -0
- package/baseline/skill/cloudflare/references/bot-management/README.md +71 -0
- package/baseline/skill/cloudflare/references/bot-management/api.md +168 -0
- package/baseline/skill/cloudflare/references/bot-management/configuration.md +114 -0
- package/baseline/skill/cloudflare/references/bot-management/gotchas.md +99 -0
- package/baseline/skill/cloudflare/references/bot-management/patterns.md +125 -0
- package/baseline/skill/cloudflare/references/browser-rendering/README.md +16 -0
- package/baseline/skill/cloudflare/references/browser-rendering/api.md +54 -0
- package/baseline/skill/cloudflare/references/browser-rendering/configuration.md +47 -0
- package/baseline/skill/cloudflare/references/browser-rendering/gotchas.md +29 -0
- package/baseline/skill/cloudflare/references/browser-rendering/patterns.md +29 -0
- package/baseline/skill/cloudflare/references/c3/README.md +264 -0
- package/baseline/skill/cloudflare/references/cache-reserve/README.md +93 -0
- package/baseline/skill/cloudflare/references/cache-reserve/api.md +176 -0
- package/baseline/skill/cloudflare/references/cache-reserve/configuration.md +164 -0
- package/baseline/skill/cloudflare/references/cache-reserve/gotchas.md +203 -0
- package/baseline/skill/cloudflare/references/cache-reserve/patterns.md +180 -0
- package/baseline/skill/cloudflare/references/containers/README.md +16 -0
- package/baseline/skill/cloudflare/references/containers/api.md +43 -0
- package/baseline/skill/cloudflare/references/containers/configuration.md +56 -0
- package/baseline/skill/cloudflare/references/containers/gotchas.md +21 -0
- package/baseline/skill/cloudflare/references/containers/patterns.md +40 -0
- package/baseline/skill/cloudflare/references/cron-triggers/README.md +85 -0
- package/baseline/skill/cloudflare/references/cron-triggers/api.md +198 -0
- package/baseline/skill/cloudflare/references/cron-triggers/configuration.md +151 -0
- package/baseline/skill/cloudflare/references/cron-triggers/gotchas.md +129 -0
- package/baseline/skill/cloudflare/references/cron-triggers/patterns.md +122 -0
- package/baseline/skill/cloudflare/references/d1/README.md +92 -0
- package/baseline/skill/cloudflare/references/d1/api.md +141 -0
- package/baseline/skill/cloudflare/references/d1/configuration.md +127 -0
- package/baseline/skill/cloudflare/references/d1/gotchas.md +70 -0
- package/baseline/skill/cloudflare/references/d1/patterns.md +144 -0
- package/baseline/skill/cloudflare/references/ddos/README.md +34 -0
- package/baseline/skill/cloudflare/references/ddos/api.md +136 -0
- package/baseline/skill/cloudflare/references/ddos/configuration.md +67 -0
- package/baseline/skill/cloudflare/references/ddos/gotchas.md +114 -0
- package/baseline/skill/cloudflare/references/ddos/patterns.md +158 -0
- package/baseline/skill/cloudflare/references/do-storage/README.md +62 -0
- package/baseline/skill/cloudflare/references/do-storage/api.md +89 -0
- package/baseline/skill/cloudflare/references/do-storage/configuration.md +116 -0
- package/baseline/skill/cloudflare/references/do-storage/gotchas.md +93 -0
- package/baseline/skill/cloudflare/references/do-storage/patterns.md +112 -0
- package/baseline/skill/cloudflare/references/durable-objects/README.md +125 -0
- package/baseline/skill/cloudflare/references/durable-objects/api.md +152 -0
- package/baseline/skill/cloudflare/references/durable-objects/configuration.md +148 -0
- package/baseline/skill/cloudflare/references/durable-objects/gotchas.md +158 -0
- package/baseline/skill/cloudflare/references/durable-objects/patterns.md +255 -0
- package/baseline/skill/cloudflare/references/email-routing/README.md +18 -0
- package/baseline/skill/cloudflare/references/email-routing/api.md +46 -0
- package/baseline/skill/cloudflare/references/email-routing/configuration.md +63 -0
- package/baseline/skill/cloudflare/references/email-routing/gotchas.md +16 -0
- package/baseline/skill/cloudflare/references/email-routing/patterns.md +46 -0
- package/baseline/skill/cloudflare/references/email-workers/README.md +598 -0
- package/baseline/skill/cloudflare/references/hyperdrive/README.md +62 -0
- package/baseline/skill/cloudflare/references/hyperdrive/api.md +137 -0
- package/baseline/skill/cloudflare/references/hyperdrive/configuration.md +133 -0
- package/baseline/skill/cloudflare/references/hyperdrive/gotchas.md +184 -0
- package/baseline/skill/cloudflare/references/hyperdrive/patterns.md +176 -0
- package/baseline/skill/cloudflare/references/images/README.md +14 -0
- package/baseline/skill/cloudflare/references/images/api.md +3 -0
- package/baseline/skill/cloudflare/references/images/configuration.md +45 -0
- package/baseline/skill/cloudflare/references/images/gotchas.md +23 -0
- package/baseline/skill/cloudflare/references/images/patterns.md +31 -0
- package/baseline/skill/cloudflare/references/kv/README.md +60 -0
- package/baseline/skill/cloudflare/references/kv/api.md +114 -0
- package/baseline/skill/cloudflare/references/kv/configuration.md +92 -0
- package/baseline/skill/cloudflare/references/kv/gotchas.md +117 -0
- package/baseline/skill/cloudflare/references/kv/patterns.md +139 -0
- package/baseline/skill/cloudflare/references/miniflare/README.md +64 -0
- package/baseline/skill/cloudflare/references/miniflare/api.md +144 -0
- package/baseline/skill/cloudflare/references/miniflare/configuration.md +203 -0
- package/baseline/skill/cloudflare/references/miniflare/gotchas.md +187 -0
- package/baseline/skill/cloudflare/references/miniflare/patterns.md +211 -0
- package/baseline/skill/cloudflare/references/network-interconnect/README.md +60 -0
- package/baseline/skill/cloudflare/references/network-interconnect/api.md +240 -0
- package/baseline/skill/cloudflare/references/network-interconnect/configuration.md +127 -0
- package/baseline/skill/cloudflare/references/network-interconnect/gotchas.md +171 -0
- package/baseline/skill/cloudflare/references/network-interconnect/patterns.md +171 -0
- package/baseline/skill/cloudflare/references/observability/README.md +18 -0
- package/baseline/skill/cloudflare/references/observability/api.md +51 -0
- package/baseline/skill/cloudflare/references/observability/configuration.md +60 -0
- package/baseline/skill/cloudflare/references/observability/gotchas.md +36 -0
- package/baseline/skill/cloudflare/references/observability/patterns.md +42 -0
- package/baseline/skill/cloudflare/references/pages/README.md +76 -0
- package/baseline/skill/cloudflare/references/pages/api.md +200 -0
- package/baseline/skill/cloudflare/references/pages/configuration.md +228 -0
- package/baseline/skill/cloudflare/references/pages/gotchas.md +161 -0
- package/baseline/skill/cloudflare/references/pages/patterns.md +145 -0
- package/baseline/skill/cloudflare/references/pages-functions/README.md +57 -0
- package/baseline/skill/cloudflare/references/pages-functions/api.md +201 -0
- package/baseline/skill/cloudflare/references/pages-functions/configuration.md +159 -0
- package/baseline/skill/cloudflare/references/pages-functions/gotchas.md +151 -0
- package/baseline/skill/cloudflare/references/pages-functions/patterns.md +190 -0
- package/baseline/skill/cloudflare/references/pipelines/README.md +664 -0
- package/baseline/skill/cloudflare/references/pulumi/README.md +107 -0
- package/baseline/skill/cloudflare/references/pulumi/api.md +194 -0
- package/baseline/skill/cloudflare/references/pulumi/configuration.md +216 -0
- package/baseline/skill/cloudflare/references/pulumi/gotchas.md +223 -0
- package/baseline/skill/cloudflare/references/pulumi/patterns.md +139 -0
- package/baseline/skill/cloudflare/references/queues/README.md +69 -0
- package/baseline/skill/cloudflare/references/queues/api.md +138 -0
- package/baseline/skill/cloudflare/references/queues/configuration.md +125 -0
- package/baseline/skill/cloudflare/references/queues/gotchas.md +112 -0
- package/baseline/skill/cloudflare/references/queues/patterns.md +155 -0
- package/baseline/skill/cloudflare/references/r2/README.md +61 -0
- package/baseline/skill/cloudflare/references/r2/api.md +127 -0
- package/baseline/skill/cloudflare/references/r2/configuration.md +76 -0
- package/baseline/skill/cloudflare/references/r2/gotchas.md +94 -0
- package/baseline/skill/cloudflare/references/r2/patterns.md +127 -0
- package/baseline/skill/cloudflare/references/r2-data-catalog/README.md +18 -0
- package/baseline/skill/cloudflare/references/r2-data-catalog/api.md +29 -0
- package/baseline/skill/cloudflare/references/r2-data-catalog/configuration.md +39 -0
- package/baseline/skill/cloudflare/references/r2-data-catalog/gotchas.md +20 -0
- package/baseline/skill/cloudflare/references/r2-data-catalog/patterns.md +46 -0
- package/baseline/skill/cloudflare/references/r2-sql/README.md +512 -0
- package/baseline/skill/cloudflare/references/realtime-sfu/README.md +21 -0
- package/baseline/skill/cloudflare/references/realtime-sfu/api.md +135 -0
- package/baseline/skill/cloudflare/references/realtime-sfu/configuration.md +63 -0
- package/baseline/skill/cloudflare/references/realtime-sfu/gotchas.md +75 -0
- package/baseline/skill/cloudflare/references/realtime-sfu/patterns.md +102 -0
- package/baseline/skill/cloudflare/references/realtimekit/README.md +81 -0
- package/baseline/skill/cloudflare/references/realtimekit/api.md +164 -0
- package/baseline/skill/cloudflare/references/realtimekit/configuration.md +147 -0
- package/baseline/skill/cloudflare/references/realtimekit/gotchas.md +172 -0
- package/baseline/skill/cloudflare/references/realtimekit/patterns.md +155 -0
- package/baseline/skill/cloudflare/references/sandbox/README.md +90 -0
- package/baseline/skill/cloudflare/references/sandbox/api.md +178 -0
- package/baseline/skill/cloudflare/references/sandbox/configuration.md +131 -0
- package/baseline/skill/cloudflare/references/sandbox/gotchas.md +156 -0
- package/baseline/skill/cloudflare/references/sandbox/patterns.md +203 -0
- package/baseline/skill/cloudflare/references/secrets-store/README.md +58 -0
- package/baseline/skill/cloudflare/references/secrets-store/api.md +182 -0
- package/baseline/skill/cloudflare/references/secrets-store/configuration.md +140 -0
- package/baseline/skill/cloudflare/references/secrets-store/gotchas.md +129 -0
- package/baseline/skill/cloudflare/references/secrets-store/patterns.md +218 -0
- package/baseline/skill/cloudflare/references/smart-placement/README.md +91 -0
- package/baseline/skill/cloudflare/references/smart-placement/api.md +139 -0
- package/baseline/skill/cloudflare/references/smart-placement/configuration.md +129 -0
- package/baseline/skill/cloudflare/references/smart-placement/gotchas.md +87 -0
- package/baseline/skill/cloudflare/references/smart-placement/patterns.md +135 -0
- package/baseline/skill/cloudflare/references/snippets/README.md +15 -0
- package/baseline/skill/cloudflare/references/snippets/api.md +47 -0
- package/baseline/skill/cloudflare/references/snippets/configuration.md +33 -0
- package/baseline/skill/cloudflare/references/snippets/gotchas.md +21 -0
- package/baseline/skill/cloudflare/references/snippets/patterns.md +34 -0
- package/baseline/skill/cloudflare/references/spectrum/README.md +16 -0
- package/baseline/skill/cloudflare/references/spectrum/api.md +24 -0
- package/baseline/skill/cloudflare/references/spectrum/configuration.md +43 -0
- package/baseline/skill/cloudflare/references/spectrum/gotchas.md +42 -0
- package/baseline/skill/cloudflare/references/spectrum/patterns.md +40 -0
- package/baseline/skill/cloudflare/references/static-assets/README.md +14 -0
- package/baseline/skill/cloudflare/references/static-assets/api.md +3 -0
- package/baseline/skill/cloudflare/references/static-assets/configuration.md +47 -0
- package/baseline/skill/cloudflare/references/static-assets/gotchas.md +44 -0
- package/baseline/skill/cloudflare/references/static-assets/patterns.md +42 -0
- package/baseline/skill/cloudflare/references/stream/README.md +103 -0
- package/baseline/skill/cloudflare/references/stream/api.md +204 -0
- package/baseline/skill/cloudflare/references/stream/configuration.md +127 -0
- package/baseline/skill/cloudflare/references/stream/gotchas.md +131 -0
- package/baseline/skill/cloudflare/references/stream/patterns.md +152 -0
- package/baseline/skill/cloudflare/references/tail-workers/README.md +640 -0
- package/baseline/skill/cloudflare/references/terraform/README.md +76 -0
- package/baseline/skill/cloudflare/references/terraform/api.md +159 -0
- package/baseline/skill/cloudflare/references/terraform/configuration.md +156 -0
- package/baseline/skill/cloudflare/references/terraform/gotchas.md +207 -0
- package/baseline/skill/cloudflare/references/terraform/patterns.md +135 -0
- package/baseline/skill/cloudflare/references/tunnel/README.md +82 -0
- package/baseline/skill/cloudflare/references/tunnel/api.md +105 -0
- package/baseline/skill/cloudflare/references/tunnel/configuration.md +113 -0
- package/baseline/skill/cloudflare/references/tunnel/gotchas.md +115 -0
- package/baseline/skill/cloudflare/references/tunnel/patterns.md +157 -0
- package/baseline/skill/cloudflare/references/turn/README.md +699 -0
- package/baseline/skill/cloudflare/references/turnstile/README.md +14 -0
- package/baseline/skill/cloudflare/references/turnstile/api.md +3 -0
- package/baseline/skill/cloudflare/references/turnstile/configuration.md +19 -0
- package/baseline/skill/cloudflare/references/turnstile/gotchas.md +27 -0
- package/baseline/skill/cloudflare/references/turnstile/patterns.md +41 -0
- package/baseline/skill/cloudflare/references/vectorize/README.md +682 -0
- package/baseline/skill/cloudflare/references/waf/README.md +14 -0
- package/baseline/skill/cloudflare/references/waf/api.md +3 -0
- package/baseline/skill/cloudflare/references/waf/configuration.md +44 -0
- package/baseline/skill/cloudflare/references/waf/gotchas.md +24 -0
- package/baseline/skill/cloudflare/references/waf/patterns.md +29 -0
- package/baseline/skill/cloudflare/references/web-analytics/README.md +19 -0
- package/baseline/skill/cloudflare/references/web-analytics/api.md +52 -0
- package/baseline/skill/cloudflare/references/web-analytics/configuration.md +31 -0
- package/baseline/skill/cloudflare/references/web-analytics/gotchas.md +28 -0
- package/baseline/skill/cloudflare/references/web-analytics/patterns.md +52 -0
- package/baseline/skill/cloudflare/references/workerd/README.md +47 -0
- package/baseline/skill/cloudflare/references/workerd/api.md +199 -0
- package/baseline/skill/cloudflare/references/workerd/configuration.md +185 -0
- package/baseline/skill/cloudflare/references/workerd/gotchas.md +203 -0
- package/baseline/skill/cloudflare/references/workerd/patterns.md +216 -0
- package/baseline/skill/cloudflare/references/workers/README.md +96 -0
- package/baseline/skill/cloudflare/references/workers/api.md +137 -0
- package/baseline/skill/cloudflare/references/workers/configuration.md +147 -0
- package/baseline/skill/cloudflare/references/workers/gotchas.md +99 -0
- package/baseline/skill/cloudflare/references/workers/patterns.md +149 -0
- package/baseline/skill/cloudflare/references/workers-ai/README.md +116 -0
- package/baseline/skill/cloudflare/references/workers-for-platforms/README.md +48 -0
- package/baseline/skill/cloudflare/references/workers-for-platforms/api.md +169 -0
- package/baseline/skill/cloudflare/references/workers-for-platforms/configuration.md +136 -0
- package/baseline/skill/cloudflare/references/workers-for-platforms/gotchas.md +130 -0
- package/baseline/skill/cloudflare/references/workers-for-platforms/patterns.md +170 -0
- package/baseline/skill/cloudflare/references/workers-playground/README.md +16 -0
- package/baseline/skill/cloudflare/references/workers-playground/api.md +20 -0
- package/baseline/skill/cloudflare/references/workers-playground/configuration.md +3 -0
- package/baseline/skill/cloudflare/references/workers-playground/gotchas.md +35 -0
- package/baseline/skill/cloudflare/references/workers-playground/patterns.md +42 -0
- package/baseline/skill/cloudflare/references/workers-vpc/README.md +579 -0
- package/baseline/skill/cloudflare/references/workflows/README.md +62 -0
- package/baseline/skill/cloudflare/references/workflows/api.md +125 -0
- package/baseline/skill/cloudflare/references/workflows/configuration.md +177 -0
- package/baseline/skill/cloudflare/references/workflows/gotchas.md +136 -0
- package/baseline/skill/cloudflare/references/workflows/patterns.md +132 -0
- package/baseline/skill/cloudflare/references/wrangler/README.md +90 -0
- package/baseline/skill/cloudflare/references/wrangler/api.md +140 -0
- package/baseline/skill/cloudflare/references/wrangler/configuration.md +128 -0
- package/baseline/skill/cloudflare/references/wrangler/gotchas.md +93 -0
- package/baseline/skill/cloudflare/references/wrangler/patterns.md +150 -0
- package/baseline/skill/cloudflare/references/zaraz/README.md +360 -0
- package/baseline/skill/code-navigation/SKILL.md +130 -0
- package/baseline/skill/compaction/SKILL.md +317 -0
- package/baseline/skill/condition-based-waiting/SKILL.md +123 -0
- package/baseline/skill/condition-based-waiting/example.ts +158 -0
- package/baseline/skill/context-engineering/SKILL.md +176 -0
- package/baseline/skill/context-initialization/SKILL.md +70 -0
- package/baseline/skill/context-management/SKILL.md +163 -0
- package/baseline/skill/core-data-expert/SKILL.md +93 -0
- package/baseline/skill/core-data-expert/references/batch-operations.md +543 -0
- package/baseline/skill/core-data-expert/references/cloudkit-integration.md +259 -0
- package/baseline/skill/core-data-expert/references/concurrency.md +522 -0
- package/baseline/skill/core-data-expert/references/fetch-requests.md +643 -0
- package/baseline/skill/core-data-expert/references/glossary.md +233 -0
- package/baseline/skill/core-data-expert/references/migration.md +393 -0
- package/baseline/skill/core-data-expert/references/model-configuration.md +597 -0
- package/baseline/skill/core-data-expert/references/performance.md +300 -0
- package/baseline/skill/core-data-expert/references/persistent-history.md +553 -0
- package/baseline/skill/core-data-expert/references/project-audit.md +60 -0
- package/baseline/skill/core-data-expert/references/saving.md +574 -0
- package/baseline/skill/core-data-expert/references/stack-setup.md +625 -0
- package/baseline/skill/core-data-expert/references/testing.md +300 -0
- package/baseline/skill/core-data-expert/references/threading.md +589 -0
- package/baseline/skill/deep-research/SKILL.md +384 -0
- package/baseline/skill/defense-in-depth/SKILL.md +166 -0
- package/baseline/skill/design-system-audit/SKILL.md +153 -0
- package/baseline/skill/development-lifecycle/SKILL.md +356 -0
- package/baseline/skill/dispatching-parallel-agents/SKILL.md +191 -0
- package/baseline/skill/executing-plans/SKILL.md +247 -0
- package/baseline/skill/figma/SKILL.md +224 -0
- package/baseline/skill/finishing-a-development-branch/SKILL.md +357 -0
- package/baseline/skill/frontend-design/SKILL.md +235 -0
- package/baseline/skill/frontend-design/references/animation/motion-advanced.md +224 -0
- package/baseline/skill/frontend-design/references/animation/motion-core.md +181 -0
- package/baseline/skill/frontend-design/references/canvas/execution.md +90 -0
- package/baseline/skill/frontend-design/references/canvas/philosophy.md +94 -0
- package/baseline/skill/frontend-design/references/design/color-system.md +111 -0
- package/baseline/skill/frontend-design/references/design/interaction.md +149 -0
- package/baseline/skill/frontend-design/references/design/typography-rules.md +106 -0
- package/baseline/skill/frontend-design/references/design/ux-writing.md +99 -0
- package/baseline/skill/frontend-design/references/shadcn/accessibility.md +132 -0
- package/baseline/skill/frontend-design/references/shadcn/core-components.md +153 -0
- package/baseline/skill/frontend-design/references/shadcn/form-components.md +158 -0
- package/baseline/skill/frontend-design/references/shadcn/setup.md +69 -0
- package/baseline/skill/frontend-design/references/shadcn/theming.md +152 -0
- package/baseline/skill/frontend-design/references/tailwind/responsive.md +112 -0
- package/baseline/skill/frontend-design/references/tailwind/utilities-layout.md +134 -0
- package/baseline/skill/frontend-design/references/tailwind/utilities-styling.md +165 -0
- package/baseline/skill/frontend-design/references/tailwind/v4-config.md +147 -0
- package/baseline/skill/frontend-design/references/tailwind/v4-features.md +128 -0
- package/baseline/skill/gemini-large-context/SKILL.md +216 -0
- package/baseline/skill/index-knowledge/SKILL.md +413 -0
- package/baseline/skill/jira/SKILL.md +283 -0
- package/baseline/skill/jira/mcp.json +6 -0
- package/baseline/skill/memory-system/SKILL.md +84 -0
- package/baseline/skill/mockup-to-code/SKILL.md +184 -0
- package/baseline/skill/mqdh/SKILL.md +171 -0
- package/baseline/skill/obsidian/SKILL.md +192 -0
- package/baseline/skill/obsidian/mcp.json +22 -0
- package/baseline/skill/opensrc/SKILL.md +127 -0
- package/baseline/skill/opensrc/references/architecture.md +176 -0
- package/baseline/skill/opensrc/references/cli-usage.md +176 -0
- package/baseline/skill/opensrc/references/registry-support.md +137 -0
- package/baseline/skill/pdf-extract/SKILL.md +438 -0
- package/baseline/skill/playwright/SKILL.md +320 -0
- package/baseline/skill/playwright/mcp.json +16 -0
- package/baseline/skill/playwriter/SKILL.md +158 -0
- package/baseline/skill/polar/SKILL.md +102 -0
- package/baseline/skill/prd/SKILL.md +146 -0
- package/baseline/skill/prd-task/SKILL.md +182 -0
- package/baseline/skill/prd-task/references/prd-schema.json +124 -0
- package/baseline/skill/ralph/SKILL.md +296 -0
- package/baseline/skill/react-best-practices/AGENTS.md +2410 -0
- package/baseline/skill/react-best-practices/README.md +123 -0
- package/baseline/skill/react-best-practices/SKILL.md +133 -0
- package/baseline/skill/react-best-practices/metadata.json +15 -0
- package/baseline/skill/react-best-practices/rules/_sections.md +46 -0
- package/baseline/skill/react-best-practices/rules/_template.md +28 -0
- package/baseline/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/baseline/skill/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/baseline/skill/react-best-practices/rules/async-api-routes.md +38 -0
- package/baseline/skill/react-best-practices/rules/async-defer-await.md +80 -0
- package/baseline/skill/react-best-practices/rules/async-dependencies.md +36 -0
- package/baseline/skill/react-best-practices/rules/async-parallel.md +28 -0
- package/baseline/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/baseline/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/baseline/skill/react-best-practices/rules/bundle-conditional.md +31 -0
- package/baseline/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/baseline/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/baseline/skill/react-best-practices/rules/bundle-preload.md +50 -0
- package/baseline/skill/react-best-practices/rules/client-event-listeners.md +74 -0
- package/baseline/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/baseline/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/baseline/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/baseline/skill/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/baseline/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/baseline/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/baseline/skill/react-best-practices/rules/js-cache-storage.md +70 -0
- package/baseline/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/baseline/skill/react-best-practices/rules/js-early-exit.md +50 -0
- package/baseline/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/baseline/skill/react-best-practices/rules/js-index-maps.md +37 -0
- package/baseline/skill/react-best-practices/rules/js-length-check-first.md +49 -0
- package/baseline/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/baseline/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/baseline/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/baseline/skill/react-best-practices/rules/rendering-activity.md +26 -0
- package/baseline/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/baseline/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/baseline/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/baseline/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/baseline/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/baseline/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/baseline/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/baseline/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/baseline/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/baseline/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/baseline/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/baseline/skill/react-best-practices/rules/rerender-memo.md +44 -0
- package/baseline/skill/react-best-practices/rules/rerender-transitions.md +40 -0
- package/baseline/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/baseline/skill/react-best-practices/rules/server-cache-lru.md +41 -0
- package/baseline/skill/react-best-practices/rules/server-cache-react.md +76 -0
- package/baseline/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/baseline/skill/react-best-practices/rules/server-serialization.md +38 -0
- package/baseline/skill/receiving-code-review/SKILL.md +252 -0
- package/baseline/skill/requesting-code-review/SKILL.md +397 -0
- package/baseline/skill/requesting-code-review/review.md +160 -0
- package/baseline/skill/resend/SKILL.md +177 -0
- package/baseline/skill/resend/references/react-email.md +287 -0
- package/baseline/skill/resend/references/receive-email.md +248 -0
- package/baseline/skill/resend/references/send-email.md +318 -0
- package/baseline/skill/root-cause-tracing/SKILL.md +192 -0
- package/baseline/skill/root-cause-tracing/find-polluter.sh +63 -0
- package/baseline/skill/session-management/SKILL.md +9 -0
- package/baseline/skill/sharing-skills/SKILL.md +214 -0
- package/baseline/skill/skill-creator/SKILL.md +156 -0
- package/baseline/skill/source-code-research/SKILL.md +293 -0
- package/baseline/skill/source-code-research/references/analysis-tips.md +43 -0
- package/baseline/skill/source-code-research/references/anti-patterns.md +36 -0
- package/baseline/skill/source-code-research/references/common-patterns.md +57 -0
- package/baseline/skill/source-code-research/references/example-workflow.md +60 -0
- package/baseline/skill/source-code-research/references/further-reading.md +5 -0
- package/baseline/skill/source-code-research/references/source-structure.md +45 -0
- package/baseline/skill/stitch/SKILL.md +147 -0
- package/baseline/skill/stitch/mcp.json +9 -0
- package/baseline/skill/structured-edit/SKILL.md +181 -0
- package/baseline/skill/subagent-driven-development/SKILL.md +237 -0
- package/baseline/skill/supabase/SKILL.md +130 -0
- package/baseline/skill/supabase/mcp.json +27 -0
- package/baseline/skill/supabase-postgres-best-practices/AGENTS.md +1490 -0
- package/baseline/skill/supabase-postgres-best-practices/SKILL.md +65 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/advanced-full-text-search.md +55 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/advanced-jsonb-indexing.md +49 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/conn-idle-timeout.md +46 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/conn-limits.md +44 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/conn-pooling.md +41 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/conn-prepared-statements.md +46 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/data-batch-inserts.md +54 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/data-n-plus-one.md +53 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/data-pagination.md +50 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/data-upsert.md +50 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/lock-advisory.md +56 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/lock-deadlock-prevention.md +68 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/lock-short-transactions.md +50 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/lock-skip-locked.md +54 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/monitor-explain-analyze.md +45 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/monitor-pg-stat-statements.md +55 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/monitor-vacuum-analyze.md +55 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/query-composite-indexes.md +44 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/query-covering-indexes.md +40 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/query-index-types.md +45 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/query-missing-indexes.md +43 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/query-partial-indexes.md +45 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/schema-data-types.md +46 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/schema-foreign-key-indexes.md +59 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/schema-lowercase-identifiers.md +55 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/schema-partitioning.md +55 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/schema-primary-keys.md +61 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/security-privileges.md +54 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/security-rls-basics.md +50 -0
- package/baseline/skill/supabase-postgres-best-practices/rules/security-rls-performance.md +57 -0
- package/baseline/skill/swarm-coordination/SKILL.md +179 -0
- package/baseline/skill/swarm-coordination/references/architecture.md +39 -0
- package/baseline/skill/swarm-coordination/references/delegation-worker-protocol.md +145 -0
- package/baseline/skill/swarm-coordination/references/dependency-graph.md +50 -0
- package/baseline/skill/swarm-coordination/references/drift-check.md +90 -0
- package/baseline/skill/swarm-coordination/references/integration-beads.md +20 -0
- package/baseline/skill/swarm-coordination/references/launch-flow.md +186 -0
- package/baseline/skill/swarm-coordination/references/reconciler.md +172 -0
- package/baseline/skill/swarm-coordination/references/tier-enforcement.md +78 -0
- package/baseline/skill/swarm-coordination/references/tmux-integration.md +134 -0
- package/baseline/skill/swift-concurrency/SKILL.md +266 -0
- package/baseline/skill/swift-concurrency/references/actors.md +640 -0
- package/baseline/skill/swift-concurrency/references/async-algorithms.md +822 -0
- package/baseline/skill/swift-concurrency/references/async-await-basics.md +249 -0
- package/baseline/skill/swift-concurrency/references/async-sequences.md +670 -0
- package/baseline/skill/swift-concurrency/references/core-data.md +533 -0
- package/baseline/skill/swift-concurrency/references/glossary.md +128 -0
- package/baseline/skill/swift-concurrency/references/linting.md +142 -0
- package/baseline/skill/swift-concurrency/references/memory-management.md +542 -0
- package/baseline/skill/swift-concurrency/references/migration.md +1076 -0
- package/baseline/skill/swift-concurrency/references/performance.md +574 -0
- package/baseline/skill/swift-concurrency/references/sendable.md +578 -0
- package/baseline/skill/swift-concurrency/references/tasks.md +604 -0
- package/baseline/skill/swift-concurrency/references/testing.md +565 -0
- package/baseline/skill/swift-concurrency/references/threading.md +452 -0
- package/baseline/skill/swiftui-expert-skill/SKILL.md +329 -0
- package/baseline/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
- package/baseline/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
- package/baseline/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
- package/baseline/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
- package/baseline/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
- package/baseline/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
- package/baseline/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
- package/baseline/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
- package/baseline/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
- package/baseline/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
- package/baseline/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
- package/baseline/skill/swiftui-expert-skill/references/state-management.md +447 -0
- package/baseline/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
- package/baseline/skill/swiftui-expert-skill/references/view-structure.md +276 -0
- package/baseline/skill/systematic-debugging/SKILL.md +402 -0
- package/baseline/skill/test-driven-development/SKILL.md +388 -0
- package/baseline/skill/testing-anti-patterns/SKILL.md +333 -0
- package/baseline/skill/testing-skills-with-subagents/SKILL.md +405 -0
- package/baseline/skill/tilth-cli/SKILL.md +180 -0
- package/baseline/skill/tool-priority/SKILL.md +299 -0
- package/baseline/skill/ui-ux-research/SKILL.md +9 -0
- package/baseline/skill/using-git-worktrees/SKILL.md +259 -0
- package/baseline/skill/using-skills/SKILL.md +117 -0
- package/baseline/skill/v0/SKILL.md +158 -0
- package/baseline/skill/v1-run/SKILL.md +175 -0
- package/baseline/skill/v1-run/mcp.json +6 -0
- package/baseline/skill/vercel-deploy-claimable/SKILL.md +124 -0
- package/baseline/skill/vercel-deploy-claimable/scripts/deploy.sh +249 -0
- package/baseline/skill/verification-before-completion/SKILL.md +236 -0
- package/baseline/skill/verification-before-completion/references/VERIFICATION_PROTOCOL.md +171 -0
- package/baseline/skill/visual-analysis/SKILL.md +154 -0
- package/baseline/skill/web-design-guidelines/SKILL.md +46 -0
- package/baseline/skill/writing-plans/SKILL.md +320 -0
- package/baseline/skill/writing-skills/SKILL.md +287 -0
- package/baseline/skill/writing-skills/anthropic-best-practices.md +1173 -0
- package/baseline/skill/writing-skills/graphviz-conventions.dot +172 -0
- package/baseline/skill/writing-skills/persuasion-principles.md +220 -0
- package/baseline/skill/writing-skills/references/anti-patterns.md +25 -0
- package/baseline/skill/writing-skills/references/claude-search-optimization.md +140 -0
- package/baseline/skill/writing-skills/references/discovery-workflow.md +11 -0
- package/baseline/skill/writing-skills/references/file-organization.md +32 -0
- package/baseline/skill/writing-skills/references/flowcharts-and-examples.md +57 -0
- package/baseline/skill/writing-skills/references/rationalization-hardening.md +75 -0
- package/baseline/skill/writing-skills/references/testing-skill-types.md +52 -0
- package/baseline/tool/context7.ts +191 -0
- package/baseline/tool/grepsearch.ts +143 -0
- package/baseline/tsconfig.json +21 -0
- package/baseline/tui.json +15 -0
- package/bin/mrc-opc.mjs +25 -0
- package/bin/ocp.mjs +25 -0
- package/bin/opc.mjs +25 -0
- package/bin/opencode-starterkit.mjs +25 -0
- package/docs/reports/2026-03-18-memory-db-architecture-note.md +47 -0
- package/docs/reports/2026-03-18-vat-opencode-classification-matrix.md +180 -0
- package/package.json +25 -0
- package/src/cli.mjs +41 -0
- package/src/config-merge.mjs +61 -0
- package/src/constants.mjs +58 -0
- package/src/fs-utils.mjs +46 -0
- package/src/install-global.mjs +102 -0
- package/src/install-project.mjs +81 -0
- package/src/memory-bootstrap.mjs +29 -0
- package/src/prompt.mjs +31 -0
- package/src/templates.mjs +31 -0
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
# Core Data Stack Setup
|
|
2
|
+
|
|
3
|
+
Setting up your Core Data stack correctly is foundational to a well-architected app. This guide covers best practices for configuring `NSPersistentContainer`, managing contexts, and establishing patterns that scale.
|
|
4
|
+
|
|
5
|
+
## Custom NSPersistentContainer
|
|
6
|
+
|
|
7
|
+
Create a custom subclass instead of configuring everything in `AppDelegate`. This keeps your stack configuration organized and testable.
|
|
8
|
+
|
|
9
|
+
```swift
|
|
10
|
+
import CoreData
|
|
11
|
+
|
|
12
|
+
class PersistentContainer: NSPersistentContainer {
|
|
13
|
+
static let shared = PersistentContainer(name: "DataModel")
|
|
14
|
+
|
|
15
|
+
private override init(name: String, managedObjectModel model: NSManagedObjectModel) {
|
|
16
|
+
super.init(name: name, managedObjectModel: model)
|
|
17
|
+
configure()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
convenience init(name: String) {
|
|
21
|
+
guard let modelURL = Bundle.main.url(forResource: name, withExtension: "momd"),
|
|
22
|
+
let model = NSManagedObjectModel(contentsOf: modelURL) else {
|
|
23
|
+
fatalError("Failed to load data model")
|
|
24
|
+
}
|
|
25
|
+
self.init(name: name, managedObjectModel: model)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private func configure() {
|
|
29
|
+
// Set merge policy for constraint handling
|
|
30
|
+
viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
31
|
+
|
|
32
|
+
// Enable automatic merging from parent
|
|
33
|
+
viewContext.automaticallyMergesChangesFromParent = true
|
|
34
|
+
|
|
35
|
+
// Name the view context for debugging
|
|
36
|
+
viewContext.name = "ViewContext"
|
|
37
|
+
|
|
38
|
+
// Configure store options before loading
|
|
39
|
+
configureStoreDescription()
|
|
40
|
+
|
|
41
|
+
// Load persistent stores
|
|
42
|
+
loadPersistentStores { description, error in
|
|
43
|
+
if let error = error {
|
|
44
|
+
// Handle error appropriately
|
|
45
|
+
fatalError("Failed to load persistent store: \(error)")
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private func configureStoreDescription() {
|
|
51
|
+
guard let description = persistentStoreDescriptions.first else { return }
|
|
52
|
+
|
|
53
|
+
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
|
|
54
|
+
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Singleton Pattern vs Dependency Injection
|
|
60
|
+
|
|
61
|
+
### Singleton Pattern (Recommended for Most Apps)
|
|
62
|
+
|
|
63
|
+
```swift
|
|
64
|
+
class PersistentContainer: NSPersistentContainer {
|
|
65
|
+
static let shared = PersistentContainer(name: "DataModel")
|
|
66
|
+
|
|
67
|
+
// Prevent external initialization
|
|
68
|
+
private override init(name: String, managedObjectModel model: NSManagedObjectModel) {
|
|
69
|
+
super.init(name: name, managedObjectModel: model)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Usage
|
|
74
|
+
let context = PersistentContainer.shared.viewContext
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Pros:**
|
|
78
|
+
- Simple, consistent access across the app
|
|
79
|
+
- No need to pass container through the app
|
|
80
|
+
- Works well with SwiftUI environment
|
|
81
|
+
|
|
82
|
+
**Cons:**
|
|
83
|
+
- Harder to test with different configurations
|
|
84
|
+
- Global state
|
|
85
|
+
|
|
86
|
+
### Dependency Injection (Better for Testing)
|
|
87
|
+
|
|
88
|
+
```swift
|
|
89
|
+
class DataController {
|
|
90
|
+
let container: NSPersistentContainer
|
|
91
|
+
|
|
92
|
+
init(inMemory: Bool = false) {
|
|
93
|
+
container = NSPersistentContainer(name: "DataModel")
|
|
94
|
+
|
|
95
|
+
if inMemory {
|
|
96
|
+
container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
container.loadPersistentStores { description, error in
|
|
100
|
+
if let error = error {
|
|
101
|
+
fatalError("Failed to load store: \(error)")
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
var viewContext: NSManagedObjectContext {
|
|
107
|
+
container.viewContext
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Usage
|
|
112
|
+
let dataController = DataController()
|
|
113
|
+
let context = dataController.viewContext
|
|
114
|
+
|
|
115
|
+
// Testing
|
|
116
|
+
let testController = DataController(inMemory: true)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Pros:**
|
|
120
|
+
- Easier to test with in-memory stores
|
|
121
|
+
- More flexible configuration
|
|
122
|
+
- Better for unit testing
|
|
123
|
+
|
|
124
|
+
**Cons:**
|
|
125
|
+
- Must pass controller through the app
|
|
126
|
+
- More boilerplate
|
|
127
|
+
|
|
128
|
+
## Merge Policies
|
|
129
|
+
|
|
130
|
+
Merge policies determine how Core Data resolves conflicts when saving. Choose based on your app's needs.
|
|
131
|
+
|
|
132
|
+
### NSMergeByPropertyStoreTrumpMergePolicy (Recommended)
|
|
133
|
+
|
|
134
|
+
Store values win over in-memory values. **Required for constraints to work.**
|
|
135
|
+
|
|
136
|
+
```swift
|
|
137
|
+
viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Use when:**
|
|
141
|
+
- Using unique constraints
|
|
142
|
+
- Store data should take precedence
|
|
143
|
+
- Multiple contexts might modify the same objects
|
|
144
|
+
|
|
145
|
+
### NSMergeByPropertyObjectTrumpMergePolicy
|
|
146
|
+
|
|
147
|
+
In-memory values win over store values.
|
|
148
|
+
|
|
149
|
+
```swift
|
|
150
|
+
viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Use when:**
|
|
154
|
+
- User edits should always win
|
|
155
|
+
- In-memory changes are more important
|
|
156
|
+
|
|
157
|
+
### NSOverwriteMergePolicy
|
|
158
|
+
|
|
159
|
+
In-memory object completely replaces store object.
|
|
160
|
+
|
|
161
|
+
```swift
|
|
162
|
+
viewContext.mergePolicy = NSOverwriteMergePolicy
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Use when:**
|
|
166
|
+
- You want complete replacement
|
|
167
|
+
- Conflicts should never occur
|
|
168
|
+
|
|
169
|
+
### NSRollbackMergePolicy
|
|
170
|
+
|
|
171
|
+
Discard in-memory changes, keep store values.
|
|
172
|
+
|
|
173
|
+
```swift
|
|
174
|
+
viewContext.mergePolicy = NSRollbackMergePolicy
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Use when:**
|
|
178
|
+
- Store is source of truth
|
|
179
|
+
- In-memory changes should be discarded on conflict
|
|
180
|
+
|
|
181
|
+
### NSErrorMergePolicy (Default)
|
|
182
|
+
|
|
183
|
+
Throws an error on conflict. You must handle manually.
|
|
184
|
+
|
|
185
|
+
```swift
|
|
186
|
+
viewContext.mergePolicy = NSErrorMergePolicy
|
|
187
|
+
|
|
188
|
+
do {
|
|
189
|
+
try context.save()
|
|
190
|
+
} catch let error as NSError {
|
|
191
|
+
if error.code == NSManagedObjectMergeError {
|
|
192
|
+
// Handle merge conflict
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Use when:**
|
|
198
|
+
- You need custom conflict resolution
|
|
199
|
+
- Conflicts should be explicitly handled
|
|
200
|
+
|
|
201
|
+
## Context Configuration
|
|
202
|
+
|
|
203
|
+
### View Context
|
|
204
|
+
|
|
205
|
+
The view context runs on the main thread and should be used for all UI operations.
|
|
206
|
+
|
|
207
|
+
```swift
|
|
208
|
+
let viewContext = container.viewContext
|
|
209
|
+
viewContext.name = "ViewContext"
|
|
210
|
+
viewContext.automaticallyMergesChangesFromParent = true
|
|
211
|
+
viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Best Practices:**
|
|
215
|
+
- Only use for UI-related fetches and updates
|
|
216
|
+
- Keep operations lightweight
|
|
217
|
+
- Enable automatic merging from parent
|
|
218
|
+
- Set a descriptive name for debugging
|
|
219
|
+
|
|
220
|
+
### Background Context
|
|
221
|
+
|
|
222
|
+
Background contexts run on private queues and should be used for heavy work.
|
|
223
|
+
|
|
224
|
+
```swift
|
|
225
|
+
override func newBackgroundContext() -> NSManagedObjectContext {
|
|
226
|
+
let context = super.newBackgroundContext()
|
|
227
|
+
context.name = "BackgroundContext"
|
|
228
|
+
context.transactionAuthor = "BackgroundAuthor"
|
|
229
|
+
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
230
|
+
context.automaticallyMergesChangesFromParent = true
|
|
231
|
+
return context
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Usage
|
|
235
|
+
let context = container.newBackgroundContext()
|
|
236
|
+
context.perform {
|
|
237
|
+
// Heavy work here
|
|
238
|
+
try? context.save()
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Best Practices:**
|
|
243
|
+
- Use for imports, exports, batch operations
|
|
244
|
+
- Always wrap work in `perform { }`
|
|
245
|
+
- Set transaction author for persistent history tracking
|
|
246
|
+
- Enable automatic merging
|
|
247
|
+
|
|
248
|
+
### Context Naming and Transaction Authors
|
|
249
|
+
|
|
250
|
+
Naming contexts helps with debugging and persistent history tracking.
|
|
251
|
+
|
|
252
|
+
```swift
|
|
253
|
+
context.name = "ImportContext"
|
|
254
|
+
context.transactionAuthor = "ImportAuthor"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**Benefits:**
|
|
258
|
+
- Identify contexts in Instruments
|
|
259
|
+
- Filter persistent history transactions
|
|
260
|
+
- Debug threading issues more easily
|
|
261
|
+
- Track which part of app made changes
|
|
262
|
+
|
|
263
|
+
**Example with App Extensions:**
|
|
264
|
+
|
|
265
|
+
```swift
|
|
266
|
+
// Main app
|
|
267
|
+
mainContext.transactionAuthor = "MainApp"
|
|
268
|
+
|
|
269
|
+
// Share extension
|
|
270
|
+
shareContext.transactionAuthor = "ShareExtension"
|
|
271
|
+
|
|
272
|
+
// Filter transactions by author
|
|
273
|
+
let fetchRequest = NSPersistentHistoryChangeRequest.fetchHistory(after: lastToken)
|
|
274
|
+
if let historyFetch = fetchRequest as? NSPersistentHistoryChangeRequest {
|
|
275
|
+
historyFetch.fetchRequest?.predicate = NSPredicate(
|
|
276
|
+
format: "author != %@", "MainApp"
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Understanding Store Loading Behavior
|
|
282
|
+
|
|
283
|
+
The `loadPersistentStores` method is **always asynchronous** - it uses a completion handler that's called when loading finishes. There is no synchronous version of this API.
|
|
284
|
+
|
|
285
|
+
### Standard Pattern (Recommended)
|
|
286
|
+
|
|
287
|
+
```swift
|
|
288
|
+
container.loadPersistentStores { description, error in
|
|
289
|
+
if let error = error {
|
|
290
|
+
fatalError("Failed to load store: \(error)")
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Code here executes immediately, before stores finish loading
|
|
294
|
+
// However, in typical setup() methods, the app waits for completion
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Characteristics:**
|
|
298
|
+
- Completion handler called asynchronously when loading finishes
|
|
299
|
+
- Code after `loadPersistentStores` executes immediately
|
|
300
|
+
- App typically waits for stores to load before showing UI
|
|
301
|
+
- Most common and recommended pattern
|
|
302
|
+
|
|
303
|
+
**When to use:**
|
|
304
|
+
- Standard app initialization
|
|
305
|
+
- When you control the setup flow
|
|
306
|
+
- When you can ensure UI doesn't appear until stores are ready
|
|
307
|
+
|
|
308
|
+
### Modern async/await Pattern (iOS 15+)
|
|
309
|
+
|
|
310
|
+
```swift
|
|
311
|
+
extension NSPersistentContainer {
|
|
312
|
+
func loadPersistentStores() async throws {
|
|
313
|
+
try await withCheckedThrowingContinuation { continuation in
|
|
314
|
+
self.loadPersistentStores { description, error in
|
|
315
|
+
if let error {
|
|
316
|
+
continuation.resume(throwing: error)
|
|
317
|
+
} else {
|
|
318
|
+
continuation.resume(returning: ())
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Usage in async context
|
|
326
|
+
func setupCoreData() async throws {
|
|
327
|
+
let container = NSPersistentContainer(name: "Model")
|
|
328
|
+
try await container.loadPersistentStores()
|
|
329
|
+
// Stores are guaranteed loaded here
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Benefits:**
|
|
334
|
+
- Cleaner async/await syntax
|
|
335
|
+
- Better error handling with try/catch
|
|
336
|
+
- Easier to compose with other async operations
|
|
337
|
+
- Explicit about async nature
|
|
338
|
+
|
|
339
|
+
**When to use:**
|
|
340
|
+
- iOS 15+ deployment target
|
|
341
|
+
- Modern Swift concurrency codebase
|
|
342
|
+
- When composing with other async operations
|
|
343
|
+
|
|
344
|
+
### Deferred Loading Pattern (Advanced)
|
|
345
|
+
|
|
346
|
+
For rare cases where you need the app to start before stores are loaded:
|
|
347
|
+
|
|
348
|
+
```swift
|
|
349
|
+
class CoreDataStack {
|
|
350
|
+
let container: NSPersistentContainer
|
|
351
|
+
private(set) var isStoreLoaded = false
|
|
352
|
+
|
|
353
|
+
init() {
|
|
354
|
+
container = NSPersistentContainer(name: "Model")
|
|
355
|
+
loadStoresInBackground()
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
private func loadStoresInBackground() {
|
|
359
|
+
container.loadPersistentStores { [weak self] description, error in
|
|
360
|
+
if let error = error {
|
|
361
|
+
print("Failed to load store: \(error)")
|
|
362
|
+
return
|
|
363
|
+
}
|
|
364
|
+
self?.isStoreLoaded = true
|
|
365
|
+
NotificationCenter.default.post(name: .storeDidLoad, object: nil)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
func waitForStoreLoad() async {
|
|
370
|
+
guard !isStoreLoaded else { return }
|
|
371
|
+
|
|
372
|
+
await withCheckedContinuation { continuation in
|
|
373
|
+
let observer = NotificationCenter.default.addObserver(
|
|
374
|
+
forName: .storeDidLoad,
|
|
375
|
+
object: nil,
|
|
376
|
+
queue: nil
|
|
377
|
+
) { _ in
|
|
378
|
+
continuation.resume()
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Check again in case it loaded while setting up observer
|
|
382
|
+
if self.isStoreLoaded {
|
|
383
|
+
NotificationCenter.default.removeObserver(observer)
|
|
384
|
+
continuation.resume()
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Cautions:**
|
|
392
|
+
- Must handle "not ready" state throughout app
|
|
393
|
+
- More complex error handling
|
|
394
|
+
- Potential race conditions if not careful
|
|
395
|
+
- Only use if you have a specific reason
|
|
396
|
+
|
|
397
|
+
**When to use:**
|
|
398
|
+
- Very large databases where loading takes significant time
|
|
399
|
+
- Apps that can show UI before data is available
|
|
400
|
+
- Background initialization scenarios
|
|
401
|
+
|
|
402
|
+
### Recommendation
|
|
403
|
+
|
|
404
|
+
**Use the standard pattern** with completion handler for most apps. The loading time is typically negligible (milliseconds), and waiting for stores to load before showing UI provides predictable behavior and avoids race conditions.
|
|
405
|
+
|
|
406
|
+
**Use async/await** if you're on iOS 15+ and want modern Swift concurrency patterns.
|
|
407
|
+
|
|
408
|
+
**Avoid deferred loading** unless you have a specific, measured need for it. The complexity and potential for bugs usually outweigh any perceived benefits.
|
|
409
|
+
|
|
410
|
+
## Store Configuration Options
|
|
411
|
+
|
|
412
|
+
### In-Memory Store (Testing)
|
|
413
|
+
|
|
414
|
+
```swift
|
|
415
|
+
let description = NSPersistentStoreDescription()
|
|
416
|
+
description.type = NSInMemoryStoreType
|
|
417
|
+
container.persistentStoreDescriptions = [description]
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Use for:**
|
|
421
|
+
- Unit tests
|
|
422
|
+
- Temporary data
|
|
423
|
+
- Prototyping
|
|
424
|
+
|
|
425
|
+
### SQLite Store (Production)
|
|
426
|
+
|
|
427
|
+
```swift
|
|
428
|
+
let description = NSPersistentStoreDescription(url: storeURL)
|
|
429
|
+
description.type = NSSQLiteStoreType
|
|
430
|
+
container.persistentStoreDescriptions = [description]
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
**Use for:**
|
|
434
|
+
- Production apps
|
|
435
|
+
- Persistent data
|
|
436
|
+
- Most common use case
|
|
437
|
+
|
|
438
|
+
### Store Location
|
|
439
|
+
|
|
440
|
+
```swift
|
|
441
|
+
// Default location
|
|
442
|
+
let storeURL = NSPersistentContainer.defaultDirectoryURL()
|
|
443
|
+
.appendingPathComponent("Model.sqlite")
|
|
444
|
+
|
|
445
|
+
// Custom location
|
|
446
|
+
let storeURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
|
447
|
+
.appendingPathComponent("MyApp.sqlite")
|
|
448
|
+
|
|
449
|
+
// App Group (for extensions)
|
|
450
|
+
let storeURL = FileManager.default.containerURL(
|
|
451
|
+
forSecurityApplicationGroupIdentifier: "group.com.example.app"
|
|
452
|
+
)?.appendingPathComponent("Shared.sqlite")
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## Complete Example
|
|
456
|
+
|
|
457
|
+
Here's a production-ready stack setup:
|
|
458
|
+
|
|
459
|
+
```swift
|
|
460
|
+
import CoreData
|
|
461
|
+
|
|
462
|
+
final class CoreDataStack {
|
|
463
|
+
static let shared = CoreDataStack()
|
|
464
|
+
|
|
465
|
+
private let containerName = "DataModel"
|
|
466
|
+
|
|
467
|
+
lazy var persistentContainer: NSPersistentContainer = {
|
|
468
|
+
let container = NSPersistentContainer(name: containerName)
|
|
469
|
+
|
|
470
|
+
// Configure store description
|
|
471
|
+
guard let description = container.persistentStoreDescriptions.first else {
|
|
472
|
+
fatalError("Failed to retrieve store description")
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Enable persistent history tracking
|
|
476
|
+
description.setOption(true as NSNumber,
|
|
477
|
+
forKey: NSPersistentHistoryTrackingKey)
|
|
478
|
+
description.setOption(true as NSNumber,
|
|
479
|
+
forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
|
|
480
|
+
|
|
481
|
+
// Load stores
|
|
482
|
+
container.loadPersistentStores { storeDescription, error in
|
|
483
|
+
if let error = error as NSError? {
|
|
484
|
+
// Handle error appropriately in production
|
|
485
|
+
fatalError("Unresolved error \(error), \(error.userInfo)")
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Configure view context
|
|
490
|
+
container.viewContext.automaticallyMergesChangesFromParent = true
|
|
491
|
+
container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
492
|
+
container.viewContext.name = "ViewContext"
|
|
493
|
+
|
|
494
|
+
return container
|
|
495
|
+
}()
|
|
496
|
+
|
|
497
|
+
var viewContext: NSManagedObjectContext {
|
|
498
|
+
persistentContainer.viewContext
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
func newBackgroundContext() -> NSManagedObjectContext {
|
|
502
|
+
let context = persistentContainer.newBackgroundContext()
|
|
503
|
+
context.name = "BackgroundContext"
|
|
504
|
+
context.transactionAuthor = "BackgroundAuthor"
|
|
505
|
+
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
506
|
+
context.automaticallyMergesChangesFromParent = true
|
|
507
|
+
return context
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
|
|
511
|
+
persistentContainer.performBackgroundTask { context in
|
|
512
|
+
context.name = "BackgroundTask"
|
|
513
|
+
context.transactionAuthor = "BackgroundTaskAuthor"
|
|
514
|
+
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
515
|
+
block(context)
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
private init() {}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Usage
|
|
523
|
+
let context = CoreDataStack.shared.viewContext
|
|
524
|
+
|
|
525
|
+
// Background work
|
|
526
|
+
CoreDataStack.shared.performBackgroundTask { context in
|
|
527
|
+
// Heavy work here
|
|
528
|
+
try? context.save()
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
## SwiftUI Integration
|
|
533
|
+
|
|
534
|
+
### Environment Object Pattern
|
|
535
|
+
|
|
536
|
+
```swift
|
|
537
|
+
import SwiftUI
|
|
538
|
+
|
|
539
|
+
@main
|
|
540
|
+
struct MyApp: App {
|
|
541
|
+
let persistenceController = PersistentContainer.shared
|
|
542
|
+
|
|
543
|
+
var body: some Scene {
|
|
544
|
+
WindowGroup {
|
|
545
|
+
ContentView()
|
|
546
|
+
.environment(\.managedObjectContext, persistenceController.viewContext)
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Usage in views
|
|
552
|
+
struct ContentView: View {
|
|
553
|
+
@Environment(\.managedObjectContext) private var viewContext
|
|
554
|
+
|
|
555
|
+
@FetchRequest(
|
|
556
|
+
sortDescriptors: [NSSortDescriptor(keyPath: \Article.name, ascending: true)],
|
|
557
|
+
animation: .default)
|
|
558
|
+
private var articles: FetchedResults<Article>
|
|
559
|
+
|
|
560
|
+
var body: some View {
|
|
561
|
+
List(articles) { article in
|
|
562
|
+
Text(article.name ?? "")
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
## Common Pitfalls
|
|
569
|
+
|
|
570
|
+
### ❌ Configuring in AppDelegate
|
|
571
|
+
|
|
572
|
+
```swift
|
|
573
|
+
// Don't do this - hard to test and maintain
|
|
574
|
+
class AppDelegate: UIApplicationDelegate {
|
|
575
|
+
lazy var persistentContainer: NSPersistentContainer = {
|
|
576
|
+
let container = NSPersistentContainer(name: "Model")
|
|
577
|
+
// Lots of configuration code here...
|
|
578
|
+
return container
|
|
579
|
+
}()
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### ❌ Not Setting Merge Policy with Constraints
|
|
584
|
+
|
|
585
|
+
```swift
|
|
586
|
+
// This will crash when constraints are violated
|
|
587
|
+
let entity = MyEntity(context: context)
|
|
588
|
+
entity.uniqueField = "duplicate" // Constraint violation
|
|
589
|
+
try context.save() // CRASH!
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### ❌ Not Naming Contexts
|
|
593
|
+
|
|
594
|
+
```swift
|
|
595
|
+
// Hard to debug which context has issues
|
|
596
|
+
let context = container.newBackgroundContext()
|
|
597
|
+
// No name, no transaction author
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### ✅ Correct Approach
|
|
601
|
+
|
|
602
|
+
```swift
|
|
603
|
+
class PersistentContainer: NSPersistentContainer {
|
|
604
|
+
static let shared = PersistentContainer(name: "Model")
|
|
605
|
+
|
|
606
|
+
override func newBackgroundContext() -> NSManagedObjectContext {
|
|
607
|
+
let context = super.newBackgroundContext()
|
|
608
|
+
context.name = "BackgroundContext"
|
|
609
|
+
context.transactionAuthor = "BackgroundAuthor"
|
|
610
|
+
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
|
|
611
|
+
context.automaticallyMergesChangesFromParent = true
|
|
612
|
+
return context
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
## Summary
|
|
618
|
+
|
|
619
|
+
1. **Create a custom NSPersistentContainer subclass** for organized configuration
|
|
620
|
+
2. **Use singleton pattern for simplicity** or dependency injection for testability
|
|
621
|
+
3. **Set merge policy** to NSMergeByPropertyStoreTrumpMergePolicy (required for constraints)
|
|
622
|
+
4. **Name contexts and set transaction authors** for debugging and history tracking
|
|
623
|
+
5. **Enable automaticallyMergesChangesFromParent** on all contexts
|
|
624
|
+
6. **Load stores using the completion handler (or async bridge)** and gate access until loading completes
|
|
625
|
+
7. **Configure persistent history tracking** if using batch operations or app extensions
|