opencodekit 0.16.14 → 0.16.17

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.
Files changed (70) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/template/.opencode/AGENTS.md +1 -1
  3. package/dist/template/.opencode/agent/plan.md +77 -161
  4. package/dist/template/.opencode/command/create.md +75 -307
  5. package/dist/template/.opencode/command/design.md +53 -589
  6. package/dist/template/.opencode/command/handoff.md +76 -180
  7. package/dist/template/.opencode/command/init.md +45 -211
  8. package/dist/template/.opencode/command/plan.md +62 -514
  9. package/dist/template/.opencode/command/pr.md +56 -226
  10. package/dist/template/.opencode/command/research.md +55 -266
  11. package/dist/template/.opencode/command/resume.md +33 -138
  12. package/dist/template/.opencode/command/review-codebase.md +54 -202
  13. package/dist/template/.opencode/command/ship.md +78 -127
  14. package/dist/template/.opencode/command/start.md +47 -577
  15. package/dist/template/.opencode/command/status.md +55 -354
  16. package/dist/template/.opencode/command/ui-review.md +52 -298
  17. package/dist/template/.opencode/command/verify.md +36 -250
  18. package/dist/template/.opencode/dcp.jsonc +10 -9
  19. package/dist/template/.opencode/memory.db-shm +0 -0
  20. package/dist/template/.opencode/memory.db-wal +0 -0
  21. package/dist/template/.opencode/plugin/README.md +8 -4
  22. package/dist/template/.opencode/plugin/swarm-enforcer.ts +182 -27
  23. package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +112 -0
  24. package/dist/template/.opencode/skill/augment-context-engine/mcp.json +6 -0
  25. package/dist/template/.opencode/skill/core-data-expert/SKILL.md +82 -0
  26. package/dist/template/.opencode/skill/core-data-expert/references/batch-operations.md +543 -0
  27. package/dist/template/.opencode/skill/core-data-expert/references/cloudkit-integration.md +259 -0
  28. package/dist/template/.opencode/skill/core-data-expert/references/concurrency.md +522 -0
  29. package/dist/template/.opencode/skill/core-data-expert/references/fetch-requests.md +643 -0
  30. package/dist/template/.opencode/skill/core-data-expert/references/glossary.md +233 -0
  31. package/dist/template/.opencode/skill/core-data-expert/references/migration.md +393 -0
  32. package/dist/template/.opencode/skill/core-data-expert/references/model-configuration.md +597 -0
  33. package/dist/template/.opencode/skill/core-data-expert/references/performance.md +300 -0
  34. package/dist/template/.opencode/skill/core-data-expert/references/persistent-history.md +553 -0
  35. package/dist/template/.opencode/skill/core-data-expert/references/project-audit.md +60 -0
  36. package/dist/template/.opencode/skill/core-data-expert/references/saving.md +574 -0
  37. package/dist/template/.opencode/skill/core-data-expert/references/stack-setup.md +625 -0
  38. package/dist/template/.opencode/skill/core-data-expert/references/testing.md +300 -0
  39. package/dist/template/.opencode/skill/core-data-expert/references/threading.md +589 -0
  40. package/dist/template/.opencode/skill/swift-concurrency/SKILL.md +246 -0
  41. package/dist/template/.opencode/skill/swift-concurrency/references/actors.md +640 -0
  42. package/dist/template/.opencode/skill/swift-concurrency/references/async-algorithms.md +822 -0
  43. package/dist/template/.opencode/skill/swift-concurrency/references/async-await-basics.md +249 -0
  44. package/dist/template/.opencode/skill/swift-concurrency/references/async-sequences.md +670 -0
  45. package/dist/template/.opencode/skill/swift-concurrency/references/core-data.md +533 -0
  46. package/dist/template/.opencode/skill/swift-concurrency/references/glossary.md +128 -0
  47. package/dist/template/.opencode/skill/swift-concurrency/references/linting.md +142 -0
  48. package/dist/template/.opencode/skill/swift-concurrency/references/memory-management.md +542 -0
  49. package/dist/template/.opencode/skill/swift-concurrency/references/migration.md +1076 -0
  50. package/dist/template/.opencode/skill/swift-concurrency/references/performance.md +574 -0
  51. package/dist/template/.opencode/skill/swift-concurrency/references/sendable.md +578 -0
  52. package/dist/template/.opencode/skill/swift-concurrency/references/tasks.md +604 -0
  53. package/dist/template/.opencode/skill/swift-concurrency/references/testing.md +565 -0
  54. package/dist/template/.opencode/skill/swift-concurrency/references/threading.md +452 -0
  55. package/dist/template/.opencode/skill/swiftui-expert-skill/SKILL.md +290 -0
  56. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
  57. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
  58. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
  59. package/dist/template/.opencode/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
  60. package/dist/template/.opencode/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
  61. package/dist/template/.opencode/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
  62. package/dist/template/.opencode/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
  63. package/dist/template/.opencode/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
  64. package/dist/template/.opencode/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
  65. package/dist/template/.opencode/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
  66. package/dist/template/.opencode/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
  67. package/dist/template/.opencode/skill/swiftui-expert-skill/references/state-management.md +447 -0
  68. package/dist/template/.opencode/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
  69. package/dist/template/.opencode/skill/swiftui-expert-skill/references/view-structure.md +276 -0
  70. package/package.json +1 -1
@@ -3,14 +3,13 @@
3
3
  *
4
4
  * Beads is the single source of truth for the swarm board.
5
5
  * This plugin provides non-intrusive enforcement:
6
+ * - System prompt injection with active beads state (via experimental.chat.system.transform)
7
+ * - Workflow stage tracking: /create → /start → /ship (enforced order)
6
8
  * - Toast warning when code is edited without a claimed task
7
- * - Toast warning when in-progress tasks are missing spec.md
9
+ * - Toast warning when in-progress tasks are missing prd.md
10
+ * - Toast warning when implementation starts before /start
8
11
  * - Session-end reminder to close/sync in-progress tasks
9
12
  *
10
- * NOTE: chat.message nudging was removed — AGENTS.md and the beads skill
11
- * already instruct agents on the beads protocol. Injecting ASCII blocks
12
- * on every user message mentioning work intent caused excessive noise.
13
- *
14
13
  * This plugin is intentionally non-destructive: it never runs `br update/close/sync`.
15
14
  */
16
15
 
@@ -22,8 +21,19 @@ type BeadsIssue = {
22
21
  id: string;
23
22
  title?: string;
24
23
  status?: string;
24
+ priority?: number;
25
+ issue_type?: string;
25
26
  };
26
27
 
28
+ /**
29
+ * Workflow stage for a bead:
30
+ * - "uncreated": No prd.md exists — needs `/create`
31
+ * - "created": Has prd.md but not in_progress — needs `/start`
32
+ * - "started": In progress with prd.md — ready for `/ship`
33
+ * - "started-no-prd": In progress but missing prd.md — needs `/create` first
34
+ */
35
+ type WorkflowStage = "uncreated" | "created" | "started" | "started-no-prd";
36
+
27
37
  const BEADS_DIR = ".beads";
28
38
  const ISSUES_FILE = "issues.jsonl";
29
39
 
@@ -88,6 +98,12 @@ async function readIssuesJsonl(repoDir: string): Promise<BeadsIssue[]> {
88
98
  id: parsed.id,
89
99
  title: typeof parsed.title === "string" ? parsed.title : undefined,
90
100
  status: typeof parsed.status === "string" ? parsed.status : undefined,
101
+ priority:
102
+ typeof parsed.priority === "number" ? parsed.priority : undefined,
103
+ issue_type:
104
+ typeof parsed.issue_type === "string"
105
+ ? parsed.issue_type
106
+ : undefined,
91
107
  });
92
108
  }
93
109
  } catch {
@@ -98,27 +114,46 @@ async function readIssuesJsonl(repoDir: string): Promise<BeadsIssue[]> {
98
114
  return issues;
99
115
  }
100
116
 
101
- async function specExists(repoDir: string, issueId: string): Promise<boolean> {
102
- const specPath = path.join(
117
+ async function artifactExists(
118
+ repoDir: string,
119
+ issueId: string,
120
+ filename: string,
121
+ ): Promise<boolean> {
122
+ const filePath = path.join(
103
123
  repoDir,
104
124
  BEADS_DIR,
105
125
  "artifacts",
106
126
  issueId,
107
- "spec.md",
127
+ filename,
108
128
  );
109
129
  try {
110
- await fsPromises.access(specPath);
130
+ await fsPromises.access(filePath);
111
131
  return true;
112
132
  } catch {
113
133
  return false;
114
134
  }
115
135
  }
116
136
 
137
+ function getWorkflowStage(issue: BeadsIssue, hasPrd: boolean): WorkflowStage {
138
+ const isInProgress = issue.status === "in_progress";
139
+
140
+ if (isInProgress && hasPrd) return "started";
141
+ if (isInProgress && !hasPrd) return "started-no-prd";
142
+ if (hasPrd) return "created";
143
+ return "uncreated";
144
+ }
145
+
146
+ type IssueWithStage = BeadsIssue & {
147
+ stage: WorkflowStage;
148
+ hasPrd: boolean;
149
+ hasPlan: boolean;
150
+ };
151
+
117
152
  export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
118
153
  const repoDir = directory || process.cwd();
119
154
  let lastStateAt = 0;
120
- let cachedInProgress: BeadsIssue[] = [];
121
- let cachedMissingSpec: BeadsIssue[] = [];
155
+ let cachedInProgress: IssueWithStage[] = [];
156
+ let cachedAllActive: IssueWithStage[] = [];
122
157
 
123
158
  const refreshState = async () => {
124
159
  const now = Date.now();
@@ -126,17 +161,20 @@ export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
126
161
  lastStateAt = now;
127
162
 
128
163
  const issues = await readIssuesJsonl(repoDir);
129
- const inProgress = issues.filter((i) => i.status === "in_progress");
164
+ const active = issues.filter(
165
+ (i) => i.status === "in_progress" || i.status === "open",
166
+ );
130
167
 
131
- const missingSpec: BeadsIssue[] = [];
132
- for (const issue of inProgress.slice(0, 10)) {
133
- if (!(await specExists(repoDir, issue.id))) {
134
- missingSpec.push(issue);
135
- }
168
+ const enriched: IssueWithStage[] = [];
169
+ for (const issue of active.slice(0, 15)) {
170
+ const hasPrd = await artifactExists(repoDir, issue.id, "prd.md");
171
+ const hasPlan = await artifactExists(repoDir, issue.id, "plan.md");
172
+ const stage = getWorkflowStage(issue, hasPrd);
173
+ enriched.push({ ...issue, stage, hasPrd, hasPlan });
136
174
  }
137
175
 
138
- cachedInProgress = inProgress;
139
- cachedMissingSpec = missingSpec;
176
+ cachedAllActive = enriched;
177
+ cachedInProgress = enriched.filter((i) => i.status === "in_progress");
140
178
  };
141
179
 
142
180
  const showToast = async (
@@ -159,7 +197,115 @@ export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
159
197
  };
160
198
 
161
199
  return {
162
- // Warn if code gets edited while no task is claimed / spec missing
200
+ // Inject active beads state + workflow stage into system prompt
201
+ "experimental.chat.system.transform": async (_input, output) => {
202
+ await refreshState();
203
+
204
+ if (cachedAllActive.length === 0) return;
205
+
206
+ const priorityLabel = (p?: number) => {
207
+ if (p === 0) return "P0-critical";
208
+ if (p === 1) return "P1-high";
209
+ if (p === 2) return "P2-normal";
210
+ if (p === 3) return "P3-low";
211
+ return "P?";
212
+ };
213
+
214
+ const stageLabel = (stage: WorkflowStage) => {
215
+ switch (stage) {
216
+ case "uncreated":
217
+ return "⏳needs:/create";
218
+ case "created":
219
+ return "⏳needs:/start";
220
+ case "started":
221
+ return "✅ready:/ship";
222
+ case "started-no-prd":
223
+ return "⚠needs:/create→/start";
224
+ }
225
+ };
226
+
227
+ const lines: string[] = [];
228
+ lines.push("<beads-state>");
229
+ lines.push("## Active Beads");
230
+ lines.push("");
231
+
232
+ // Show in-progress first, then open
233
+ const sorted = [...cachedAllActive].sort((a, b) => {
234
+ if (a.status === "in_progress" && b.status !== "in_progress") return -1;
235
+ if (a.status !== "in_progress" && b.status === "in_progress") return 1;
236
+ return 0;
237
+ });
238
+
239
+ for (const issue of sorted.slice(0, 7)) {
240
+ const typeTag = issue.issue_type || "task";
241
+ const prioTag = priorityLabel(issue.priority);
242
+ const stage = stageLabel(issue.stage);
243
+ const statusTag =
244
+ issue.status === "in_progress" ? "🔧in_progress" : "📋open";
245
+ lines.push(
246
+ `- **${issue.id}** ${issue.title || "(untitled)"} [${typeTag} ${prioTag}] ${statusTag} ${stage}`,
247
+ );
248
+ }
249
+
250
+ // Workflow enforcement warnings
251
+ const needsCreate = cachedAllActive.filter(
252
+ (i) => i.stage === "uncreated" || i.stage === "started-no-prd",
253
+ );
254
+ const needsStart = cachedAllActive.filter((i) => i.stage === "created");
255
+ const readyToShip = cachedInProgress.filter((i) => i.stage === "started");
256
+
257
+ lines.push("");
258
+ lines.push("**Workflow enforcement (required order):**");
259
+ lines.push(
260
+ "1. `/create <description>` — creates bead + prd.md (specification)",
261
+ );
262
+ lines.push(
263
+ "2. `/start <id>` — claims task, creates branch, sets in_progress",
264
+ );
265
+ lines.push("3. `/ship <id>` — implement, verify, review, close");
266
+ lines.push("");
267
+ lines.push(
268
+ "⛔ **Do NOT implement code until `/start` has been run.** Edit code only for beads marked ✅ready:/ship.",
269
+ );
270
+
271
+ if (needsCreate.length > 0) {
272
+ lines.push("");
273
+ lines.push(
274
+ `⚠ ${needsCreate.length} bead(s) need \`/create\`: ${needsCreate.map((i) => i.id).join(", ")}`,
275
+ );
276
+ }
277
+
278
+ if (needsStart.length > 0) {
279
+ lines.push("");
280
+ lines.push(
281
+ `⚠ ${needsStart.length} bead(s) have prd.md but need \`/start\`: ${needsStart.map((i) => i.id).join(", ")}`,
282
+ );
283
+ }
284
+
285
+ if (readyToShip.length > 0) {
286
+ lines.push("");
287
+ lines.push(
288
+ `✅ ${readyToShip.length} bead(s) ready for \`/ship\`: ${readyToShip.map((i) => i.id).join(", ")}`,
289
+ );
290
+ }
291
+
292
+ lines.push("");
293
+ lines.push("**Beads protocol reminders:**");
294
+ lines.push(
295
+ "- Claim before editing: `br update <id> --status in_progress`",
296
+ );
297
+ lines.push(
298
+ '- When done: `br close <id> --reason="..."` → `br sync --flush-only` → git commit',
299
+ );
300
+ lines.push(
301
+ '- Discovered work (>2min): `br create --title "..." --type bug|task`',
302
+ );
303
+ lines.push("</beads-state>");
304
+
305
+ output.system.push(lines.join("\n"));
306
+ },
307
+
308
+ // Warn if code gets edited while no task is claimed / workflow not followed
163
309
  event: async ({ event }) => {
164
310
  if (event.type === "file.edited") {
165
311
  const filePath = event.properties?.file;
@@ -174,22 +320,31 @@ export const SwarmEnforcer: Plugin = async ({ client, directory }) => {
174
320
 
175
321
  await refreshState();
176
322
 
323
+ // No tasks claimed at all
177
324
  if (cachedInProgress.length === 0) {
178
325
  await showToast(
179
326
  "Beads: No task claimed",
180
- "Run br ready/show/update to claim a task before edits.",
327
+ "Run /start <id> to claim a task before editing code.",
181
328
  "warning",
182
329
  );
183
330
  return;
184
331
  }
185
332
 
186
- if (cachedMissingSpec.length > 0) {
333
+ // Tasks in progress but none are ready for /ship
334
+ const readyForShip = cachedInProgress.filter(
335
+ (i) => i.stage === "started",
336
+ );
337
+ if (readyForShip.length === 0) {
338
+ const notReady = cachedInProgress.filter(
339
+ (i) => i.stage !== "started",
340
+ );
341
+ const ids = notReady
342
+ .slice(0, 3)
343
+ .map((i) => i.id)
344
+ .join(", ");
187
345
  await showToast(
188
- "Beads: Missing spec.md",
189
- `Create .beads/artifacts/<id>/spec.md for: ${cachedMissingSpec
190
- .slice(0, 3)
191
- .map((i) => i.id)
192
- .join(", ")}`,
346
+ "Beads: Workflow incomplete",
347
+ `Task(s) ${ids} need prd.md via /create before implementing.`,
193
348
  "warning",
194
349
  );
195
350
  }
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: augment-context-engine
3
+ description: Semantic codebase search via Augment Context Engine MCP. Use when you need to understand code relationships, find relevant implementations, or explore unfamiliar codebases beyond keyword matching.
4
+ ---
5
+
6
+ # Augment Context Engine (MCP)
7
+
8
+ Semantic code search powered by Augment's Context Engine. Unlike grep (text matching), this understands code meaning, relationships, and cross-file dependencies.
9
+
10
+ ## Available Tools
11
+
12
+ - `augment_code_search` - Semantic search across indexed GitHub repositories
13
+
14
+ **Parameters:**
15
+
16
+ - `repo_owner` (string, required) - GitHub org or username (e.g. `"augmentcode"`)
17
+ - `repo_name` (string, required) - Repository name (e.g. `"test-repo"`)
18
+ - `query` (string, required) - Natural language description of what you're looking for
19
+ - `branch` (string, optional) - Branch to search (defaults to `"main"`)
20
+ - `max_results` (integer, optional) - Max code snippets to return (defaults to 5)
21
+
22
+ ## Quick Start
23
+
24
+ ```
25
+ # Search a GitHub repo for authentication code
26
+ skill_mcp(skill_name="augment-context-engine", tool_name="augment_code_search", arguments='{"repo_owner": "myorg", "repo_name": "myapp", "query": "authentication middleware that validates JWT tokens"}')
27
+
28
+ # Search a specific branch with more results
29
+ skill_mcp(skill_name="augment-context-engine", tool_name="augment_code_search", arguments='{"repo_owner": "myorg", "repo_name": "myapp", "query": "error handling patterns", "branch": "develop", "max_results": 10}')
30
+ ```
31
+
32
+ > **Tip:** Get `repo_owner` and `repo_name` from git: `git remote get-url origin`
33
+
34
+ ## Setup
35
+
36
+ ### 1. Install the Augment GitHub App
37
+
38
+ Install at [github.com/apps/augmentcode](https://github.com/apps/augmentcode/installations/new) and grant access to the repos you want to index.
39
+
40
+ ### 2. Add the remote server
41
+
42
+ The skill's `mcp.json` uses `mcp-remote` to bridge the remote API via stdio.
43
+
44
+ For global access, add to `~/.config/opencode/opencode.json`:
45
+
46
+ ```json
47
+ {
48
+ "$schema": "https://opencode.ai/config.json",
49
+ "mcp": {
50
+ "auggie": {
51
+ "type": "remote",
52
+ "url": "https://api.augmentcode.com/mcp",
53
+ "enabled": true
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### 3. Authenticate
60
+
61
+ Sign in at [app.augmentcode.com](https://app.augmentcode.com) when prompted by `mcp-remote` on first use.
62
+
63
+ ## Query Tips
64
+
65
+ Good queries (natural language, conceptual):
66
+
67
+ - `"function that handles user authentication"`
68
+ - `"database connection setup code"`
69
+ - `"tests for the payment processing module"`
70
+
71
+ Bad queries (use grep instead):
72
+
73
+ - `"foo_bar"` — exact symbol search
74
+ - `"TODO"` — keyword search
75
+ - `"code that deals with everything"` — too vague
76
+
77
+ ## When to Use
78
+
79
+ | Scenario | Use This | Instead Of |
80
+ | ------------------------ | --------------------- | -------------------------- |
81
+ | Find code by meaning | `augment_code_search` | `grep` (text only) |
82
+ | Understand relationships | `augment_code_search` | `@explore` agent (heavier) |
83
+ | Unfamiliar codebase | `augment_code_search` | Manual file exploration |
84
+ | Cross-repo dependencies | `augment_code_search` | LSP references (narrower) |
85
+
86
+ ## When NOT to Use
87
+
88
+ - **Exact string matching** — Use `grep` instead (faster, free)
89
+ - **Known file paths** — Use `read` directly
90
+ - **Symbol definitions** — Use LSP `goToDefinition` (precise)
91
+ - **Local-only work** — This searches GitHub-indexed repos, not local files
92
+
93
+ ## Tool Priority Integration
94
+
95
+ ```
96
+ grep (text) → semantic search (meaning) → read (full file) → LSP (symbols) → edit
97
+ ```
98
+
99
+ Use grep first for exact matches. Escalate to semantic search when grep results are noisy or you need conceptual understanding.
100
+
101
+ ## Cost
102
+
103
+ - ~40-70 credits per query
104
+ - Not free — use judiciously
105
+ - Prefer grep for simple lookups
106
+
107
+ ## Resources
108
+
109
+ - Docs: https://docs.augmentcode.com/context-services/mcp/overview
110
+ - OpenCode Quickstart: https://docs.augmentcode.com/context-services/mcp/quickstart-open-code
111
+ - GitHub App: https://github.com/apps/augmentcode/installations/new
112
+ - Product: https://www.augmentcode.com/product/context-engine-mcp
@@ -0,0 +1,6 @@
1
+ {
2
+ "augment-context-engine": {
3
+ "command": "npx",
4
+ "args": ["-y", "mcp-remote", "https://api.augmentcode.com/mcp"]
5
+ }
6
+ }
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: core-data-expert
3
+ description: 'Expert Core Data guidance (iOS/macOS): stack setup, fetch requests & NSFetchedResultsController, saving/merge conflicts, threading & Swift Concurrency, batch operations & persistent history, migrations, performance, and NSPersistentCloudKitContainer/CloudKit sync.'
4
+ ---
5
+ # Core Data Expert
6
+
7
+ Fast, production-oriented guidance for building **correct**, **performant** Core Data stacks and fixing common crashes.
8
+
9
+ ## Agent behavior contract (follow these rules)
10
+
11
+ 1. Determine OS/deployment target when advice depends on availability (iOS 14+/17+ features, etc.).
12
+ 2. Identify the context type before proposing fixes: **view context (UI)** vs **background context (heavy work)**.
13
+ 3. Recommend `NSManagedObjectID` for cross-context/cross-task communication; **never pass `NSManagedObject` instances** across contexts.
14
+ 4. Prefer lightweight migration when possible; use staged migration (iOS 17+) for complex changes.
15
+ 5. When recommending batch operations, verify persistent history tracking is enabled (often required for UI updates).
16
+ 6. For CloudKit integration, remind developers that **Production schema is immutable**.
17
+ 7. Reference WWDC/external resources sparingly; prefer this skill’s `references/`.
18
+
19
+ ## First 60 seconds (triage template)
20
+
21
+ - **Clarify the goal**: setup, bugfix, migration, performance, CloudKit?
22
+ - **Collect minimal facts**:
23
+ - platform + deployment target
24
+ - store type (SQLite / in-memory) and whether CloudKit is enabled
25
+ - context involved (view vs background) and whether Swift Concurrency is in use
26
+ - exact error message + stack trace/logs
27
+ - **Branch immediately**:
28
+ - threading/crash → focus on context confinement + `NSManagedObjectID` handoff
29
+ - migration error → identify model versions + migration strategy
30
+ - batch ops not updating UI → persistent history tracking + merge pipeline
31
+
32
+ ## Routing map (pick the right reference fast)
33
+
34
+ - **Stack setup / merge policies / contexts** → `references/stack-setup.md`
35
+ - **Saving patterns** → `references/saving.md`
36
+ - **Fetch requests / list updates / aggregates** → `references/fetch-requests.md`
37
+ - **Traditional threading (perform/performAndWait, object IDs)** → `references/threading.md`
38
+ - **Swift Concurrency (async/await, actors, Sendable, DAOs)** → `references/concurrency.md`
39
+ - **Batch insert/delete/update** → `references/batch-operations.md`
40
+ - **Persistent history tracking + “batch ops not updating UI”** → `references/persistent-history.md`
41
+ - **Model configuration (constraints, validation, derived/composite, transformables)** → `references/model-configuration.md`
42
+ - **Schema migration (lightweight/staged/deferred)** → `references/migration.md`
43
+ - **CloudKit integration & debugging** → `references/cloudkit-integration.md`
44
+ - **Performance profiling & memory** → `references/performance.md`
45
+ - **Testing patterns** → `references/testing.md`
46
+ - **Terminology** → `references/glossary.md`
47
+
48
+ ## Common errors → next best move
49
+
50
+ - **“Failed to find a unique match for an NSEntityDescription”** → `references/testing.md` (shared `NSManagedObjectModel`)
51
+ - **`NSPersistentStoreIncompatibleVersionHashError`** → `references/migration.md` (versioning + migration)
52
+ - **Cross-context/threading exceptions** (e.g. delete/update from wrong context) → `references/threading.md` and/or `references/concurrency.md` (use `NSManagedObjectID`)
53
+ - **Sendable / actor-isolation warnings around Core Data** → `references/concurrency.md` (don’t “paper over” with `@unchecked Sendable`)
54
+ - **`NSMergeConflict` / constraint violations** → `references/model-configuration.md` + `references/stack-setup.md` (constraints + merge policy)
55
+ - **Batch operations not updating UI** → `references/persistent-history.md` + `references/batch-operations.md`
56
+ - **CloudKit schema/sync issues** → `references/cloudkit-integration.md`
57
+ - **Memory grows during fetch** → `references/performance.md` + `references/fetch-requests.md`
58
+
59
+ ## Verification checklist (when changing Core Data code)
60
+
61
+ - Confirm the context matches the work (UI vs background).
62
+ - Ensure `NSManagedObject` instances never cross contexts; pass `NSManagedObjectID` instead.
63
+ - If using batch ops, confirm persistent history tracking + merge pipeline.
64
+ - If using constraints, confirm merge policy and conflict resolution strategy.
65
+ - If performance-related, profile with Instruments and validate fetch batching/limits.
66
+
67
+ ## Reference files
68
+
69
+ - `references/_index.md` (navigation)
70
+ - `references/stack-setup.md`
71
+ - `references/saving.md`
72
+ - `references/fetch-requests.md`
73
+ - `references/threading.md`
74
+ - `references/concurrency.md`
75
+ - `references/batch-operations.md`
76
+ - `references/persistent-history.md`
77
+ - `references/model-configuration.md`
78
+ - `references/migration.md`
79
+ - `references/cloudkit-integration.md`
80
+ - `references/performance.md`
81
+ - `references/testing.md`
82
+ - `references/glossary.md`