@bonesofspring/ai-rules 0.2.1 → 0.2.3

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 (205) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +17 -5
  3. package/bin/cli.js +4 -4
  4. package/package.json +3 -11
  5. package/presets/claude/ios-swift/CLAUDE.md +35 -0
  6. package/presets/claude/ios-swift/README.md +30 -0
  7. package/presets/claude/ios-swift/agents/README.md +55 -0
  8. package/presets/claude/ios-swift/agents/accessibility-reviewer.md +67 -0
  9. package/presets/claude/ios-swift/agents/api-contract-reviewer.md +72 -0
  10. package/presets/claude/ios-swift/agents/build-verifier.md +64 -0
  11. package/presets/claude/ios-swift/agents/ci-investigator.md +73 -0
  12. package/presets/claude/ios-swift/agents/code-reviewer.md +75 -0
  13. package/presets/claude/ios-swift/agents/debugger.md +72 -0
  14. package/presets/claude/ios-swift/agents/feature-developer.md +35 -0
  15. package/presets/claude/ios-swift/agents/migration-specialist.md +73 -0
  16. package/presets/claude/ios-swift/agents/performance-auditor.md +72 -0
  17. package/presets/claude/ios-swift/agents/qa-tester.md +65 -0
  18. package/presets/claude/ios-swift/agents/security-reviewer.md +69 -0
  19. package/presets/claude/ios-swift/agents/solution-architect.md +17 -0
  20. package/presets/claude/ios-swift/agents/task-analyst.md +25 -0
  21. package/presets/claude/ios-swift/agents/task-router.md +62 -0
  22. package/presets/claude/ios-swift/agents/tech-writer.md +63 -0
  23. package/presets/claude/ios-swift/agents/unit-test-generator.md +54 -0
  24. package/presets/claude/ios-swift/agents/unit-test-healer.md +53 -0
  25. package/presets/claude/ios-swift/agents/unit-test-planner.md +64 -0
  26. package/presets/claude/ios-swift/agents/xcuitest-test-generator.md +47 -0
  27. package/presets/claude/ios-swift/agents/xcuitest-test-healer.md +47 -0
  28. package/presets/claude/ios-swift/agents/xcuitest-test-planner.md +67 -0
  29. package/presets/claude/ios-swift/commands/README.md +13 -0
  30. package/presets/claude/ios-swift/commands/feature-continue.md +51 -0
  31. package/presets/claude/ios-swift/commands/feature-start.md +30 -0
  32. package/presets/claude/ios-swift/commands/task-continue.md +49 -0
  33. package/presets/claude/ios-swift/commands/task.md +50 -0
  34. package/presets/claude/ios-swift/commands/technical-retro.md +58 -0
  35. package/presets/claude/ios-swift/hooks/README.md +10 -0
  36. package/presets/claude/ios-swift/hooks/chain-team-phases.sh +382 -0
  37. package/presets/claude/ios-swift/hooks/guard-shell-command.sh +79 -0
  38. package/presets/claude/ios-swift/rules/README.md +55 -0
  39. package/presets/claude/ios-swift/rules/api-and-data/README.md +10 -0
  40. package/presets/claude/ios-swift/rules/api-and-data/networking.md +49 -0
  41. package/presets/claude/ios-swift/rules/api-and-data/persistence.md +30 -0
  42. package/presets/claude/ios-swift/rules/architecture/README.md +12 -0
  43. package/presets/claude/ios-swift/rules/architecture/boundaries.md +33 -0
  44. package/presets/claude/ios-swift/rules/architecture/feature-delivery.md +68 -0
  45. package/presets/claude/ios-swift/rules/architecture/module-public-api.md +25 -0
  46. package/presets/claude/ios-swift/rules/architecture/reference-features.md +50 -0
  47. package/presets/claude/ios-swift/rules/stack/README.md +10 -0
  48. package/presets/claude/ios-swift/rules/stack/ios-app-core.md +43 -0
  49. package/presets/claude/ios-swift/rules/stack/swift-conventions.md +51 -0
  50. package/presets/claude/ios-swift/rules/testing/README.md +10 -0
  51. package/presets/claude/ios-swift/rules/testing/ui.md +43 -0
  52. package/presets/claude/ios-swift/rules/testing/unit.md +41 -0
  53. package/presets/claude/ios-swift/rules/tooling-and-review/README.md +16 -0
  54. package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-intake.md +18 -0
  55. package/presets/claude/ios-swift/rules/tooling-and-review/agent-team-orchestrator.md +47 -0
  56. package/presets/claude/ios-swift/rules/tooling-and-review/code-quality.md +38 -0
  57. package/presets/claude/ios-swift/rules/tooling-and-review/code-review.md +46 -0
  58. package/presets/claude/ios-swift/rules/tooling-and-review/post-change-build.md +36 -0
  59. package/presets/claude/ios-swift/rules/tooling-and-review/security-ios.md +36 -0
  60. package/presets/claude/ios-swift/rules/tooling-and-review/technical-retro.md +14 -0
  61. package/presets/claude/ios-swift/rules/tooling-and-review/xcode-tooling.md +24 -0
  62. package/presets/claude/ios-swift/rules/ui-and-accessibility/README.md +11 -0
  63. package/presets/claude/ios-swift/rules/ui-and-accessibility/navigation.md +28 -0
  64. package/presets/claude/ios-swift/rules/ui-and-accessibility/swiftui.md +61 -0
  65. package/presets/claude/ios-swift/rules/ui-and-accessibility/viewmodels.md +43 -0
  66. package/presets/claude/ios-swift/skills/README.md +13 -0
  67. package/presets/claude/ios-swift/skills/ci-investigation/SKILL.md +39 -0
  68. package/presets/claude/ios-swift/skills/code-review/SKILL.md +27 -0
  69. package/presets/claude/ios-swift/skills/debug-investigation/SKILL.md +30 -0
  70. package/presets/claude/ios-swift/skills/feature-delivery/SKILL.md +27 -0
  71. package/presets/claude/ios-swift/skills/technical-retro/SKILL.md +10 -0
  72. package/presets/claude/ios-swift/skills/unit-testing/SKILL.md +32 -0
  73. package/presets/claude/ios-swift/skills/xcuitest-e2e/SKILL.md +33 -0
  74. package/presets/claude/ios-swift/team/README.md +27 -0
  75. package/presets/claude/ios-swift/team/fixtures/bugfix-standard.json +33 -0
  76. package/presets/claude/ios-swift/team/fixtures/feature-full.json +48 -0
  77. package/presets/claude/ios-swift/team/fixtures/feature-light.json +36 -0
  78. package/presets/claude/next/CLAUDE.md +4 -8
  79. package/presets/claude/next/agents/README.md +62 -34
  80. package/presets/claude/next/agents/code-reviewer.md +6 -5
  81. package/presets/claude/next/agents/playwright-test-generator.md +65 -16
  82. package/presets/claude/next/agents/playwright-test-healer.md +51 -16
  83. package/presets/claude/next/agents/playwright-test-planner.md +55 -15
  84. package/presets/claude/next/agents/task-analyst.md +3 -1
  85. package/presets/claude/next/agents/task-router.md +4 -4
  86. package/presets/claude/next/agents/tech-writer.md +1 -0
  87. package/presets/claude/next/hooks/chain-team-phases.sh +73 -35
  88. package/presets/claude/next/rules/README.md +16 -3
  89. package/presets/claude/next/rules/architecture/README.md +2 -1
  90. package/presets/claude/next/rules/stack/README.md +1 -1
  91. package/presets/claude/next/rules/stack/navigation-router.md +2 -0
  92. package/presets/claude/next/rules/stack/next-app-core.md +1 -1
  93. package/presets/claude/next/rules/tooling-and-review/README.md +12 -14
  94. package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +1 -0
  95. package/presets/claude/next/rules/tooling-and-review/code-review-mr.md +3 -3
  96. package/presets/claude/next/rules/tooling-and-review/post-change-lint.md +11 -0
  97. package/presets/claude/next/rules/ui-and-accessibility/README.md +6 -3
  98. package/presets/claude/next/skills/feature-delivery/SKILL.md +1 -1
  99. package/presets/claude/next/team/README.md +65 -7
  100. package/presets/cursor/ios-swift/AGENTS.md +47 -0
  101. package/presets/cursor/ios-swift/BUGBOT.md +15 -0
  102. package/presets/cursor/ios-swift/README.md +36 -0
  103. package/presets/cursor/ios-swift/agents/README.md +55 -0
  104. package/presets/cursor/ios-swift/agents/accessibility-reviewer.md +67 -0
  105. package/presets/cursor/ios-swift/agents/api-contract-reviewer.md +72 -0
  106. package/presets/cursor/ios-swift/agents/build-verifier.md +64 -0
  107. package/presets/cursor/ios-swift/agents/ci-investigator.md +73 -0
  108. package/presets/cursor/ios-swift/agents/code-reviewer.md +75 -0
  109. package/presets/cursor/ios-swift/agents/debugger.md +72 -0
  110. package/presets/cursor/ios-swift/agents/feature-developer.md +35 -0
  111. package/presets/cursor/ios-swift/agents/migration-specialist.md +73 -0
  112. package/presets/cursor/ios-swift/agents/performance-auditor.md +72 -0
  113. package/presets/cursor/ios-swift/agents/qa-tester.md +65 -0
  114. package/presets/cursor/ios-swift/agents/security-reviewer.md +69 -0
  115. package/presets/cursor/ios-swift/agents/solution-architect.md +17 -0
  116. package/presets/cursor/ios-swift/agents/task-analyst.md +25 -0
  117. package/presets/cursor/ios-swift/agents/task-router.md +62 -0
  118. package/presets/cursor/ios-swift/agents/tech-writer.md +63 -0
  119. package/presets/cursor/ios-swift/agents/unit-test-generator.md +54 -0
  120. package/presets/cursor/ios-swift/agents/unit-test-healer.md +53 -0
  121. package/presets/cursor/ios-swift/agents/unit-test-planner.md +64 -0
  122. package/presets/cursor/ios-swift/agents/xcuitest-test-generator.md +47 -0
  123. package/presets/cursor/ios-swift/agents/xcuitest-test-healer.md +47 -0
  124. package/presets/cursor/ios-swift/agents/xcuitest-test-planner.md +67 -0
  125. package/presets/cursor/ios-swift/commands/README.md +51 -0
  126. package/presets/cursor/ios-swift/commands/feature-continue.md +19 -0
  127. package/presets/cursor/ios-swift/commands/feature-start.md +33 -0
  128. package/presets/cursor/ios-swift/commands/task-continue.md +49 -0
  129. package/presets/cursor/ios-swift/commands/task.md +50 -0
  130. package/presets/cursor/ios-swift/commands/technical-retro.md +81 -0
  131. package/presets/cursor/ios-swift/hooks/README.md +8 -0
  132. package/presets/cursor/ios-swift/hooks/chain-team-phases.sh +382 -0
  133. package/presets/cursor/ios-swift/hooks/guard-shell-command.sh +79 -0
  134. package/presets/{claude/next → cursor/ios-swift}/hooks.json +2 -2
  135. package/presets/cursor/ios-swift/rules/README.md +65 -0
  136. package/presets/cursor/ios-swift/rules/agent-team-intake.mdc +16 -0
  137. package/presets/cursor/ios-swift/rules/agent-team-orchestrator.mdc +80 -0
  138. package/presets/cursor/ios-swift/rules/architecture-boundaries.mdc +34 -0
  139. package/presets/cursor/ios-swift/rules/code-quality-and-refactoring.mdc +39 -0
  140. package/presets/cursor/ios-swift/rules/code-review-mr.mdc +43 -0
  141. package/presets/cursor/ios-swift/rules/feature-delivery-workflow.mdc +61 -0
  142. package/presets/cursor/ios-swift/rules/ios-app-core.mdc +44 -0
  143. package/presets/cursor/ios-swift/rules/module-public-api.mdc +26 -0
  144. package/presets/cursor/ios-swift/rules/navigation-coordinators.mdc +29 -0
  145. package/presets/cursor/ios-swift/rules/networking-services.mdc +49 -0
  146. package/presets/cursor/ios-swift/rules/persistence-data.mdc +31 -0
  147. package/presets/cursor/ios-swift/rules/post-change-build.mdc +32 -0
  148. package/presets/cursor/ios-swift/rules/reference-features.mdc +53 -0
  149. package/presets/cursor/ios-swift/rules/security-ios.mdc +35 -0
  150. package/presets/cursor/ios-swift/rules/state-and-viewmodels.mdc +43 -0
  151. package/presets/cursor/ios-swift/rules/swift-conventions.mdc +51 -0
  152. package/presets/cursor/ios-swift/rules/swiftui-ui.mdc +61 -0
  153. package/presets/cursor/ios-swift/rules/technical-retro.mdc +12 -0
  154. package/presets/cursor/ios-swift/rules/tests-ui.mdc +42 -0
  155. package/presets/cursor/ios-swift/rules/tests-unit.mdc +41 -0
  156. package/presets/cursor/ios-swift/rules/xcode-tooling.mdc +20 -0
  157. package/presets/cursor/ios-swift/skills/README.md +13 -0
  158. package/presets/cursor/ios-swift/skills/ci-investigation/SKILL.md +39 -0
  159. package/presets/cursor/ios-swift/skills/code-review/SKILL.md +27 -0
  160. package/presets/cursor/ios-swift/skills/debug-investigation/SKILL.md +30 -0
  161. package/presets/cursor/ios-swift/skills/feature-delivery/SKILL.md +27 -0
  162. package/presets/cursor/ios-swift/skills/technical-retro/SKILL.md +10 -0
  163. package/presets/cursor/ios-swift/skills/unit-testing/SKILL.md +32 -0
  164. package/presets/cursor/ios-swift/skills/xcuitest-e2e/SKILL.md +33 -0
  165. package/presets/cursor/ios-swift/team/README.md +27 -0
  166. package/presets/cursor/ios-swift/team/fixtures/bugfix-standard.json +33 -0
  167. package/presets/cursor/ios-swift/team/fixtures/feature-full.json +48 -0
  168. package/presets/cursor/ios-swift/team/fixtures/feature-light.json +36 -0
  169. package/presets/cursor/next/AGENTS.md +1 -1
  170. package/presets/cursor/next/BUGBOT.md +0 -2
  171. package/presets/cursor/next/agents/README.md +6 -0
  172. package/presets/cursor/next/agents/accessibility-reviewer.md +1 -1
  173. package/presets/cursor/next/agents/api-contract-reviewer.md +1 -1
  174. package/presets/cursor/next/agents/build-verifier.md +2 -2
  175. package/presets/cursor/next/agents/code-reviewer.md +1 -1
  176. package/presets/cursor/next/agents/feature-developer.md +1 -0
  177. package/presets/cursor/next/agents/migration-specialist.md +2 -2
  178. package/presets/cursor/next/agents/performance-auditor.md +1 -1
  179. package/presets/cursor/next/agents/playwright-test-generator.md +1 -0
  180. package/presets/cursor/next/agents/playwright-test-healer.md +1 -0
  181. package/presets/cursor/next/agents/qa-tester.md +1 -0
  182. package/presets/cursor/next/agents/security-reviewer.md +1 -1
  183. package/presets/cursor/next/agents/solution-architect.md +1 -1
  184. package/presets/cursor/next/agents/task-analyst.md +1 -1
  185. package/presets/cursor/next/agents/task-router.md +2 -2
  186. package/presets/cursor/next/agents/tech-writer.md +1 -1
  187. package/presets/cursor/next/agents/unit-test-planner.md +2 -2
  188. package/presets/cursor/next/rules/README.md +6 -6
  189. package/presets/cursor/next/rules/agent-team-orchestrator.mdc +25 -23
  190. package/presets/cursor/next/rules/next-app-core.mdc +1 -1
  191. package/presets/cursor/next/rules/post-change-lint.mdc +4 -2
  192. package/presets/cursor/next/skills/feature-delivery/SKILL.md +1 -1
  193. package/CONTRIBUTING.md +0 -102
  194. package/fragments/BUGBOT.md +0 -23
  195. package/presets/claude/next/BUGBOT.md +0 -16
  196. package/presets/claude/next/rules/architecture/api-public-imports.md +0 -8
  197. package/presets/claude/next/rules/architecture/types-public-imports.md +0 -8
  198. package/presets/cursor/next/rules/api-public-imports.mdc +0 -8
  199. package/presets/cursor/next/rules/no-cross-component-styles-import.mdc +0 -8
  200. package/presets/cursor/next/rules/types-public-imports.mdc +0 -8
  201. package/scripts/README.md +0 -84
  202. package/scripts/golden-prompts.json +0 -276
  203. package/scripts/preset-manifest.json +0 -72
  204. package/scripts/regression-results/.gitkeep +0 -0
  205. package/scripts/validate-preset.sh +0 -484
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env bash
2
+ # Lightweight shell guard for Cursor projects using this preset.
3
+ # iOS: do NOT blanket-block xcodebuild / simctl / xcrun / swiftlint / swiftformat.
4
+ # Package-manager mismatch checks apply only when a JS lockfile/package.json exists.
5
+
6
+ set -euo pipefail
7
+
8
+ input=$(cat)
9
+
10
+ INPUT="$input" node <<'NODE'
11
+ const fs = require('fs');
12
+
13
+ const raw = process.env.INPUT || '';
14
+ let event;
15
+ try {
16
+ event = JSON.parse(raw);
17
+ } catch {
18
+ process.stdout.write('{ "permission": "allow" }');
19
+ process.exit(0);
20
+ }
21
+
22
+ const command = String(event.command || event.input?.command || '');
23
+ if (!command.trim()) {
24
+ process.stdout.write('{ "permission": "allow" }');
25
+ process.exit(0);
26
+ }
27
+
28
+ function out(permission, userMessage, agentMessage) {
29
+ process.stdout.write(JSON.stringify({
30
+ permission,
31
+ user_message: userMessage,
32
+ agent_message: agentMessage || userMessage,
33
+ }));
34
+ }
35
+
36
+ const dangerousGit = /\bgit\s+(reset\s+--hard|clean\s+-[^\n]*f|push\s+--force|push\s+-f|checkout\s+--\s+)/;
37
+ if (dangerousGit.test(command)) {
38
+ out(
39
+ 'ask',
40
+ 'This command looks destructive for git state. Review it before continuing.',
41
+ 'A project hook flagged a destructive git command. Ask the user before running it.',
42
+ );
43
+ process.exit(0);
44
+ }
45
+
46
+ const managerByFile = [
47
+ ['yarn.lock', 'yarn'],
48
+ ['pnpm-lock.yaml', 'pnpm'],
49
+ ['package-lock.json', 'npm'],
50
+ ].find(([file]) => fs.existsSync(file));
51
+
52
+ let expected = managerByFile?.[1];
53
+ if (!expected && fs.existsSync('package.json')) {
54
+ try {
55
+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
56
+ const pm = typeof pkg.packageManager === 'string' ? pkg.packageManager : '';
57
+ expected = pm.split('@')[0] || undefined;
58
+ } catch {
59
+ // Ignore invalid package.json in the hook; the agent can diagnose it later.
60
+ }
61
+ }
62
+
63
+ if (!expected) {
64
+ process.stdout.write('{ "permission": "allow" }');
65
+ process.exit(0);
66
+ }
67
+
68
+ const used = command.match(/(^|[;&|]\s*)(npm|yarn|pnpm)\s+/)?.[2];
69
+ if (used && used !== expected) {
70
+ out(
71
+ 'ask',
72
+ `This repository appears to use ${expected}, but the command uses ${used}. Confirm before continuing.`,
73
+ `Use ${expected} for package scripts and installs unless the user explicitly approves ${used}.`,
74
+ );
75
+ process.exit(0);
76
+ }
77
+
78
+ process.stdout.write('{ "permission": "allow" }');
79
+ NODE
@@ -3,13 +3,13 @@
3
3
  "hooks": {
4
4
  "beforeShellExecution": [
5
5
  {
6
- "command": ".claude/hooks/guard-shell-command.sh",
6
+ "command": ".cursor/hooks/guard-shell-command.sh",
7
7
  "failClosed": true
8
8
  }
9
9
  ],
10
10
  "subagentStop": [
11
11
  {
12
- "command": ".claude/hooks/chain-team-phases.sh",
12
+ "command": ".cursor/hooks/chain-team-phases.sh",
13
13
  "loop_limit": 15
14
14
  }
15
15
  ]
@@ -0,0 +1,65 @@
1
+ ### Разница .mdc и .md в .cursor/rules
2
+
3
+ #### .md
4
+ Обычный markdown‑файл. Cursor видит его как документацию/контент, но не как правило, которое нужно автоматически применять.
5
+
6
+ #### .mdc
7
+ Специальный формат Cursor Rule:
8
+ - сверху обязателен YAML‑frontmatter с полями вроде description, globs, alwaysApply;
9
+ - файл лежит в .cursor/rules/;
10
+ - Cursor интерпретирует его как конфигурацию поведения ассистента для этого репо (автоматически подмешивает содержимое в контекст, когда правило подходит).
11
+
12
+ - То есть .mdc = “markdown + config для Cursor”, .md = просто текст без управляющего смысла для ассистента.
13
+
14
+ ### Пресет ios-swift — карта правил
15
+
16
+ **alwaysApply budget:** **≤3** always-on правила и **≤120** строк тела (после YAML) суммарно (stretch ≤100). Новые alwaysApply только вместе с сокращением существующего бюджета.
17
+
18
+ | Файл | Скоуп | Тема |
19
+ |------|--------|------|
20
+ | `ios-app-core.mdc` | **always** | Стек, структура, tips (+ pointers на tooling/build) |
21
+ | `architecture-boundaries.mdc` | **always** | Границы Presentation / Domain / Data, DI |
22
+ | `code-quality-and-refactoring.mdc` | **always** | Качество и лёгкий refactor |
23
+ | `xcode-tooling.mdc` | requestable | Схемы, xcodebuild, SwiftLint/Format |
24
+ | `post-change-build.mdc` | requestable | Сборка/lint после Swift edits (**обязателен** после code edits) |
25
+ | `agent-team-intake.mdc` | requestable | Подсказка `/task` |
26
+ | `agent-team-orchestrator.mdc` | requestable | Pipeline, gates, build-verifier |
27
+ | `feature-delivery-workflow.mdc` | requestable | Чеклист доставки фичи |
28
+ | `code-review-mr.mdc` | requestable | Ревью MR/diff |
29
+ | `reference-features.mdc` | globs Features/** | Эталоны Feature + dogfood |
30
+ | `technical-retro.mdc` | requestable | Alias → `/technical-retro` |
31
+ | `swiftui-ui.mdc` | Presentation, DesignSystem | SwiftUI, a11y |
32
+ | `navigation-coordinators.mdc` | Navigation / App | NavigationStack, deep links |
33
+ | `networking-services.mdc` | Data, Network | API, DTO, mappers (HTTP only) |
34
+ | `persistence-data.mdc` | Persistence, Keychain | SwiftData/Core Data/Keychain |
35
+ | `security-ios.mdc` | Auth, Keychain, Info.plist | ATS, PII, secrets |
36
+ | `module-public-api.mdc` | Package.swift, Sources | SPM public API |
37
+ | `state-and-viewmodels.mdc` | ViewModels | State, use cases |
38
+ | `swift-conventions.mdc` | `**/*.swift` | Swift style |
39
+ | `tests-unit.mdc` | `*Tests` | Unit |
40
+ | `tests-ui.mdc` | `*UITests` | XCUITest (+ pointer to xcuitest agents/skill) |
41
+
42
+ **Всего topic `.mdc`:** 21 (без README).
43
+
44
+ **Twin depth (Cursor↔Claude):** domain rules ≥15 body lines. Thin requestable **aliases** (`agent-team-intake`, `technical-retro`) могут быть короче — как в next (soft AC-19).
45
+
46
+ ### Presentation edit bundle
47
+
48
+ При правке `**/Presentation/**` или `**/DesignSystem/**`: грузить `swiftui-ui` + `state-and-viewmodels` (+ `navigation-coordinators` при правке навигации). Не подмешивать orchestrator.
49
+
50
+ ### Loading strategy
51
+
52
+ ```text
53
+ alwaysApply (3)
54
+ └─ ios-app-core + architecture-boundaries + code-quality
55
+
56
+ requestable
57
+ └─ orchestrator, intake, feature-delivery, code-review-mr,
58
+ post-change-build, xcode-tooling, reference-features, technical-retro
59
+
60
+ globs
61
+ └─ swiftui, navigation, viewmodels, networking, persistence,
62
+ security, modules, conventions, tests-*
63
+ ```
64
+
65
+ Установка: `npx @bonesofspring/ai-rules init cursor --preset ios-swift`
@@ -0,0 +1,16 @@
1
+ ---
2
+ description: Use when user posts a work request without /task — suggest or use /task to run the agent team router. Lightweight intake hint only.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Agent team intake
7
+
8
+ When the user message looks like a **work request** (implement, add, fix, refactor, review MR, write tests, spike) — not a question about how code works:
9
+
10
+ 1. Prefer **`/task <their request>`** or invoke **task-router** first.
11
+ 2. Do not jump straight to coding without router + pipeline when scope is non-trivial.
12
+ 3. Pure questions («как работает X», «объясни») — answer normally, no `/task`.
13
+
14
+ Exceptions: user explicitly says «без pipeline», «просто сделай», or continues an active slug.
15
+
16
+ Scope: iOS/Swift Feature modules (`Features/`, Presentation/Domain/Data) — not `app/src` / Playwright.
@@ -0,0 +1,80 @@
1
+ ---
2
+ description: Orchestrates the agent team via task-router and pipeline.json. Use for /task, /task-continue, /feature-start, task decomposition, or when the user describes a feature, bug, or review request.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Agent team orchestrator
7
+
8
+ Parent agent = **manager**. Router plans; specialists execute. Artifacts: `.cursor/team/tasks/<slug>/`.
9
+
10
+ Work request без `/task` — см. **`agent-team-intake.mdc`**.
11
+
12
+ ## Entry points
13
+
14
+ | Command | When |
15
+ |---------|------|
16
+ | **`/task <desc>`** | **Preferred** — router → dynamic pipeline → first agent |
17
+ | `/task-continue <slug>` | After human gate or pause |
18
+ | `/feature-start <desc>` | Legacy: analyst-only start (no router) |
19
+ | `/feature-continue <slug>` | Alias of task-continue |
20
+ | `/technical-retro [slug]` | Retro with agent team block |
21
+
22
+ ## Roles (iOS)
23
+
24
+ | Agent | Prod writes | Typical intent |
25
+ |-------|-------------|----------------|
26
+ | `task-router` | no (team) | Every `/task` |
27
+ | `task-analyst` | no | feature, refactor, test-only, a11y, docs, migration |
28
+ | `solution-architect` | no | spike, cross-layer Feature |
29
+ | `migration-specialist` | no | Xcode/SPM/iOS upgrades |
30
+ | `api-contract-reviewer` | no | OpenAPI / Swift codegen contracts |
31
+ | `debugger` | minimal | bugfix |
32
+ | `ci-investigator` | minimal CI | ci-fix |
33
+ | `feature-developer` | yes | feature, bugfix, refactor, migration, a11y |
34
+ | `build-verifier` | no | xcodebuild + SwiftLint/Format + unit smoke |
35
+ | `accessibility-reviewer` | no | VoiceOver / Dynamic Type |
36
+ | `performance-auditor` | no | launch / Instruments |
37
+ | `code-reviewer` | no | most pipelines, review-only |
38
+ | `security-reviewer` | no | Keychain, ATS, PII |
39
+ | `qa-tester` | tests | feature, bugfix, test-only |
40
+ | `unit-test-planner` / `generator` / `healer` | tests | unit-only |
41
+ | `xcuitest-test-planner` / `generator` / `healer` | UI tests | e2e-only (XCUITest) |
42
+ | `tech-writer` | docs | docs-only |
43
+
44
+ **Never use Playwright stems** in this preset — substitute XCUITest trio. Document Playwright skips when copying next templates.
45
+
46
+ **Cursor frontmatter:** all team agents use `readonly: false` (team writes). Production restrictions live in prompt bodies.
47
+
48
+ Full prompts: `.cursor/agents/*.md`. Artifacts: `.cursor/team/README.md`.
49
+
50
+ ## Dynamic pipeline
51
+
52
+ **Source of truth for order:** `pipeline.json` → `steps[]`. Never hardcode analyst → dev → review → QA when `pipeline.json` exists.
53
+
54
+ ## status.json (pipeline mode)
55
+
56
+ | state | Meaning |
57
+ |-------|---------|
58
+ | `in_progress` | Current step running |
59
+ | `completed` | Current step done; hook advances |
60
+ | `awaiting_approval` | Human gate; wait for `/task-continue` |
61
+ | `changes_requested` | Reviewer blocked; re-run developer |
62
+ | `validation_failed` | build-verifier failed; re-run developer then verifier |
63
+
64
+ ## Rules (strict)
65
+
66
+ 1. **`/task` always starts with task-router** (unless user skips with documented pipeline).
67
+ 2. Read `pipeline.json` before every subagent invocation.
68
+ 3. One role per Task call — except parallel steps.
69
+ 4. **Never** skip `humanGates` without `/task-continue` or explicit approval.
70
+ 5. Persist handoffs to disk under `.cursor/team/tasks/<slug>/`.
71
+ 6. On `changes_requested`: developer → same reviewer.
72
+ 7. On `validation_failed`: developer → build-verifier.
73
+ 8. When all steps complete, suggest `/technical-retro <slug>`.
74
+ 9. If `autoChain: false`, do not rely on hook.
75
+
76
+ ## Skip pipeline when
77
+
78
+ - Pure questions; typo / one-file trivial fix; user «без pipeline»; single-line docs-only.
79
+
80
+ Borderline — **`agent-team-intake.mdc`**.
@@ -0,0 +1,34 @@
1
+ ---
2
+ description: Архитектурные границы и правила зависимостей iOS приложения
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Границы между слоями
7
+
8
+ - **Presentation** (Views, ViewModels, DesignSystem):
9
+ - Может: Domain (entities, use case protocols), DesignSystem, Core (без UI).
10
+ - Не должен: импортировать Data (репозитории, DTO, API-клиенты); знать HTTP/Codable/эндпоинты; маппить DTO → domain.
11
+ - **Domain**:
12
+ - Может: Core (базовые типы, протоколы).
13
+ - Не должен: импортировать SwiftUI, UIKit, сеть; знать конкретные реализации репозиториев.
14
+ - **Data**:
15
+ - Может: Domain (протоколы, entities), Core.
16
+ - Не должен: импортировать SwiftUI/UIKit; зависеть от View/ViewModel.
17
+
18
+ # Зависимости и модули
19
+
20
+ - Направление: **Presentation → Domain ← Data**.
21
+ - Переиспользуемое — в Core / DesignSystem; к другой фиче — только **public API** (протокол, facade, coordinator), не deep-import.
22
+ - SPM: Domain не линкуется с Data; реализации Data подключаются через DI в `App/`.
23
+ - Раскладка фичи — как в `ios-app-core.mdc` / соседних `Features/*` репо (Presentation / Domain / Data + тесты).
24
+
25
+ # DI и composition root
26
+
27
+ - Сборка графа — в `App/` (или `DI/` / CompositionRoot), не во View.
28
+ - ViewModel получает **протоколы** (use case / repository), не конкретные Data-типы.
29
+ - Preview и тесты — mock/stub реализаций.
30
+
31
+ # Требование к агенту
32
+
33
+ - Файлы — в соответствующих слоях; протоколы репозиториев в Domain, реализации в Data.
34
+ - Не «коротить» слои (API из View «ради скорости»).
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Поддержка и улучшение качества кода и архитектуры iOS
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Поддержка существующего стиля
7
+
8
+ - Новые изменения должны:
9
+ - следовать существующим паттернам (имена, структура, DI, error handling);
10
+ - минимизировать «стилистический шум» (лишний reformat, rename без нужды).
11
+ - Перед новым решением:
12
+ - искать аналог в коде и **повторять подход**;
13
+ - проверять DesignSystem и существующие компоненты перед новым UI-контролом;
14
+ - обращаться к другим фичам только через public API (протоколы, facades).
15
+
16
+ # Рефакторинг при изменениях
17
+
18
+ - Допустим лёгкий refactor, если он:
19
+ - уменьшает дублирование;
20
+ - повышает читаемость;
21
+ - не ломает публичные контракты.
22
+ - Примеры:
23
+ - вынести дублирующийся mapper или validation;
24
+ - заменить force unwrap на безопасные конструкции;
25
+ - разбить перегруженный ViewModel на use cases;
26
+ - заменить magic numbers/colors на design tokens;
27
+ - убрать прямую зависимость View от Data в пользу протокола.
28
+
29
+ # Ограничения
30
+
31
+ - Не делать «большой» рефакторинг при точечной задаче:
32
+ - не менять структуру модулей/таргетов;
33
+ - не переименовывать public API без запроса.
34
+ - Крупные изменения — минимальными шагами, код остаётся компилируемым.
35
+
36
+ # Требование к агенту
37
+
38
+ - **Boy scout rule:** оставлять модуль чуть лучше (безопасность optional, typed errors, tests).
39
+ - Не жертвовать слоями ради краткости.
@@ -0,0 +1,43 @@
1
+ ---
2
+ description: Требования к code review для iOS merge requests. Use when reviewing MR/diff/PR, evaluating a branch, or when the user asks for code review.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Code review merge requests
7
+
8
+ On-demand правило для review-потоков (не always-on).
9
+
10
+ - **Когда применять**
11
+ - Запросы: «проведи ревью», «оцени MR/ветку/дифф», «посмотри изменения».
12
+ - Опираться на локальный репозиторий: ветка, `git diff`, открытые файлы.
13
+
14
+ - **Что обязан проверить агент**
15
+ - **Архитектура и слои** (`architecture-boundaries.mdc`, `ios-app-core.mdc`):
16
+ - View не вызывает API и не знает DTO.
17
+ - ViewModel не зависит от Data-реализаций напрямую.
18
+ - Domain не импортирует SwiftUI/UIKit.
19
+ - Data не тянет Presentation.
20
+ - **Зависимости и модули**:
21
+ - DI через протоколы; composition root в App.
22
+ - Нет deep-import между фичами.
23
+ - Файлы в правильных слоях (`Presentation`, `Domain`, `Data`, `DesignSystem`).
24
+ - **Swift и concurrency** (`swift-conventions.mdc`):
25
+ - `@MainActor` на UI; нет необоснованных force unwrap.
26
+ - Typed errors; корректная отмена Task где нужно.
27
+ - **UI** (`swiftui-ui.mdc`):
28
+ - Тонкие Views; Design System tokens; accessibility identifiers для тестируемых элементов.
29
+ - **Сеть и data** (`networking-services.mdc`):
30
+ - DTO отделены от domain; mappers покрывают edge cases.
31
+ - **Тесты**:
32
+ - Нетривиальная логика — unit (`tests-unit.mdc`); пользовательские потоки — UI (`tests-ui.mdc`).
33
+ - Указать, какие тесты добавить или обновить.
34
+
35
+ - **Глубина и формат**
36
+ - Фокус на **диффе MR**, не на всём проекте.
37
+ - Сначала обзор (цель MR, риски), затем конкретные комментарии с файлом и предложением fix по паттернам репо.
38
+ - Без «больших рефакторингов» без запроса (`code-quality-and-refactoring.mdc`).
39
+
40
+ - **Ограничения**
41
+ - Не выдумывать метаданные CI/MR с хостинга без локальных данных.
42
+ - Boy scout rule в рамках MR.
43
+ - BUGBOT automated review — см. корневой `BUGBOT.md` (Cursor).
@@ -0,0 +1,61 @@
1
+ ---
2
+ description: Сквозной чеклист доставки iOS-фичи и матрица «зона → правило». Use when implementing features, adding screens/API, or extending existing iOS flows.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Доставка фичи (iOS)
7
+
8
+ Типичная фича с данными и UI. Детали слоёв — `architecture-boundaries.mdc`, `ios-app-core.mdc`.
9
+
10
+ ## Чеклист (порядок работ)
11
+
12
+ 1. **Domain** — entities, value types, протоколы репозиториев / use cases (`Features/**/Domain/**`).
13
+ 2. **Data** — DTO (`Codable`), mappers Domain ↔ DTO, реализации репозиториев, API-клиент (`networking-services.mdc`).
14
+ 3. **ViewModel** — состояние, вызовы use case / протоколов; DI из App; без DTO и URL (`state-and-viewmodels.mdc`).
15
+ 4. **View / navigation** — тонкие SwiftUI Views, Design System; навигация как в репо (`swiftui-ui.mdc`).
16
+ 5. **Тесты** — unit на mappers / use cases / VM (`tests-unit.mdc`); UI-потоки — XCUITest (`tests-ui.mdc`).
17
+ 6. **Завершение** — **вызвать** `post-change-build.mdc` (+ `xcode-tooling.mdc` для схем/команд): сборка затронутых таргетов + lint/format по конфигу репо.
18
+
19
+ ## Поток данных (ориентир)
20
+
21
+ ```mermaid
22
+ flowchart LR
23
+ DTO[DTO] --> Mappers[Mappers]
24
+ Mappers --> Domain[Domain]
25
+ Domain --> Repo[Repository protocol]
26
+ Repo --> VM[ViewModel]
27
+ VM --> View[SwiftUI View]
28
+ DataImpl[Data impl] -.-> Repo
29
+ ```
30
+
31
+ ## Частичные сценарии
32
+
33
+ | Задача | Минимум |
34
+ |--------|---------|
35
+ | Только API / модель | Domain + DTO + mapper + repo impl; unit на mapper. |
36
+ | Только VM / логика | Протоколы Domain; mock в тестах; без HTTP во View. |
37
+ | Только UI | View + существующий VM/state; без DTO. |
38
+ | Только тесты | Specs по конвенции репо; не менять production без нужды. |
39
+
40
+ ## Антипаттерны
41
+
42
+ - DTO / `Codable` transport-типы во View или ViewModel.
43
+ - `URLSession` / конкретный API-клиент в ViewModel или View.
44
+ - Domain импортирует SwiftUI / UIKit.
45
+ - Deep-import внутренних файлов другой фичи.
46
+ - Сборка DI внутри View.
47
+
48
+ ## Матрица: зона → правила
49
+
50
+ | Зона | Правила |
51
+ |------|---------|
52
+ | `Features/**/Domain/**`, `Core/Domain/**` | `architecture-boundaries.mdc`, `ios-app-core.mdc` |
53
+ | `Features/**/Data/**`, `**/Network*/**` | `networking-services.mdc`, `architecture-boundaries.mdc` |
54
+ | `*ViewModel*.swift`, Presentation state | `state-and-viewmodels.mdc` |
55
+ | `Presentation/**`, `DesignSystem/**` | `swiftui-ui.mdc`, `architecture-boundaries.mdc` |
56
+ | `**/*.swift` (стиль) | `swift-conventions.mdc` |
57
+ | `*Tests/**` | `tests-unit.mdc` |
58
+ | `*UITests/**` | `tests-ui.mdc` |
59
+ | После правок Swift | `post-change-build.mdc` |
60
+
61
+ При добавлении или расширении фичи **пройти чеклист** и правила из таблицы для затронутых зон.
@@ -0,0 +1,44 @@
1
+ ---
2
+ description: Базовые принципы, стек и структура iOS приложения на Swift (preset)
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Стек и окружение
7
+
8
+ Версии Swift, iOS SDK, зависимостей и инструментов — **из Xcode-проекта, Package.swift и конфигов целевого репозитория**. Рамка preset:
9
+
10
+ - **Язык / платформа:** Swift, iOS (min — из таргета).
11
+ - **UI:** SwiftUI — приоритет для нового кода; UIKit — где уже принято в репо.
12
+ - **Сборка:** Xcode; SPM и/или CocoaPods — как в репозитории.
13
+ - **Concurrency:** `async`/`await`, `Task`, `Actor`; UI — `@MainActor`.
14
+ - **Тесты:** XCTest или Swift Testing; UI — XCUITest.
15
+ - **Сеть:** `URLSession` или клиент репо; DTO через `Codable`.
16
+ - **Дизайн-система:** токены/примитивы из `DesignSystem/` (или аналога); без «магических» значений.
17
+ - **Наблюдаемость:** только если уже в проекте — централизованно.
18
+
19
+ # Структура проекта
20
+
21
+ Ориентир — **feature-first + слои внутри фичи** или **слои на верхнем уровне** (как в репо):
22
+
23
+ - `App/` — `@main`, composition root, DI, навигация верхнего уровня.
24
+ - `Features/<FeatureName>/` — `Presentation/` (Views, ViewModels), `Domain/` (entities, use cases, протоколы), `Data/` (repos, API, DTO, mappers).
25
+ - `Core/` — общие утилиты, extensions, базовые ошибки.
26
+ - `DesignSystem/` — UI-примитивы без бизнес-логики.
27
+ - `Tests/` / `*Tests/` — unit и UI по конвенции Xcode.
28
+
29
+ Новые файлы — в том же слое/модуле, что и аналогичная функциональность.
30
+
31
+ Границы зависимостей и DI — **`architecture-boundaries.mdc`**.
32
+
33
+ # Swift и качество
34
+
35
+ - Swift API Design Guidelines + SwiftLint/SwiftFormat репо (если есть).
36
+ - Избегать `!` / `try!` в production; `guard` / `if let` / typed errors.
37
+ - Копировать существующие паттерны фичи/слоя.
38
+
39
+ # Работа агента
40
+
41
+ - Определить слой (Presentation / Domain / Data / DesignSystem / Tests); повторить паттерн соседних файлов.
42
+ - Не тянуть `URLSession` во View и DTO во ViewModel — детали в `architecture-boundaries.mdc`.
43
+ - Доставка фичи — `feature-delivery-workflow.mdc`; после правок Swift — **вызвать** `post-change-build.mdc` (requestable).
44
+ - Toolchain перед сборкой — `xcode-tooling.mdc` (requestable).
@@ -0,0 +1,26 @@
1
+ ---
2
+ description: SPM / модули — public API, access control, запрет deep-import internals
3
+ globs:
4
+ - "**/Package.swift"
5
+ - "**/*Public*.swift"
6
+ - "**/Sources/**/*.swift"
7
+ alwaysApply: false
8
+ ---
9
+
10
+ # Module public API (SPM)
11
+
12
+ ## Рамка
13
+
14
+ - Потребители модуля импортируют **только public/open** API; `internal`/`fileprivate` — для реализации.
15
+ - Deep-import чужих internal файлов — повод вынести символ в public API или рефакторить границы.
16
+
17
+ ## Правила
18
+
19
+ - Новый публичный тип/функция — явный `public` + документация/пример использования при необходимости.
20
+ - Barrel-стиль: один входной модуль / umbrella, если так заведено в репо.
21
+ - Не экспортировать DTO сети из Presentation-facing модулей.
22
+ - Версионирование breaking API — осознанно (SemVer пакета / release notes).
23
+
24
+ ## Требование к агенту
25
+
26
+ Перед `public` на тип — проверить, нужен ли он снаружи. Следовать access control соседних модулей.
@@ -0,0 +1,29 @@
1
+ ---
2
+ description: NavigationStack, координаторы, deep links — границы Presentation
3
+ globs:
4
+ - "**/Presentation/**/*Navigator*.swift"
5
+ - "**/Presentation/**/*Coordinator*.swift"
6
+ - "**/Presentation/**/*Router*.swift"
7
+ - "**/App/**/*App*.swift"
8
+ - "**/*Navigation*.swift"
9
+ alwaysApply: false
10
+ ---
11
+
12
+ # Навигация (iOS)
13
+
14
+ ## Рамка
15
+
16
+ - **SwiftUI-first:** `NavigationStack` / `navigationDestination` / sheet / fullScreenCover — как в репо.
17
+ - UIKit / coordinator — только если уже принят в модуле; не смешивать два стиля в одном Feature без причины.
18
+ - Маршруты и deep links — **Presentation** (или App shell); Domain не знает о `NavigationPath`.
19
+
20
+ ## Правила
21
+
22
+ - Один Feature — один явный «вход» навигации (root view / coordinator), не размазывать `NavigationLink` по Data.
23
+ - Параметры экрана — typed (enum route / struct), не «магические» строки без реестра.
24
+ - Deep link → route mapping централизован (App или Navigation hub); ViewModel не парсит URL напрямую.
25
+ - Модалки: владелец presentation state — родительский VM/coordinator, не глобальный singleton без нужды.
26
+
27
+ ## Требование к агенту
28
+
29
+ Копировать паттерн ближайшего Feature из `reference-features.mdc`. Не тащить networking в навигационный слой.
@@ -0,0 +1,49 @@
1
+ ---
2
+ description: Конвенции сетевого слоя, API-клиентов и mappers
3
+ globs: "**/{Data,Network,Networking}/**/*.swift"
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Роль Data / Network слоя
8
+
9
+ - Инкапсулировать:
10
+ - HTTP-запросы (`URLSession` или клиент проекта),
11
+ - URL, headers, status codes,
12
+ - Codable DTO (транспорт).
13
+ - Локальное хранение / Keychain — **`persistence-data.mdc`**, не смешивать с HTTP-клиентом без фасада-репозитория.
14
+ - Наружу (Domain, ViewModel через repository) отдавать **доменные типы**, не DTO.
15
+
16
+ # Структура модулей
17
+
18
+ - На доменную область — каталог в `Features/<Feature>/Data/` или `Core/Network/<Service>/`.
19
+ - Внутри:
20
+ - `*APIClient.swift` / `*Service.swift` — вызовы эндпоинтов;
21
+ - `*DTO.swift` — транспортные модели (`Codable`);
22
+ - `*Mapper.swift` — DTO ↔ domain;
23
+ - `*RepositoryImpl.swift` — реализация протокола из Domain.
24
+ - Public surface — протоколы репозиториев в Domain; Data-классы не экспортируются во View.
25
+
26
+ # DTO, mappers и типы
27
+
28
+ - DTO **точно** отражают контракт backend (`CodingKeys` при расхождении имён).
29
+ - Доменные entity — в Domain; mapper — **чистые функции** без side effects.
30
+ - В mapper выполнять вычисления (флаги, форматирование, агрегаты), чтобы ViewModel получал готовую модель.
31
+ - Optional и отсутствующие поля обрабатывать явно; не прокидывать «сырой» optional cascade в UI.
32
+
33
+ # Async, errors и retries
34
+
35
+ - Сетевые методы — `async throws` с **typed errors** (`NetworkError`, `APIError`) по конвенции репо.
36
+ - Не глотать ошибки; пробрасывать или маппить в domain errors для ViewModel.
37
+ - Retry, auth refresh, logging — централизованно (interceptor, middleware, `URLProtocol`), не в каждом методе.
38
+
39
+ # Codable и versioning
40
+
41
+ - Избегать `[String: Any]`; для полиморфизма — enum + associated values или явные DTO.
42
+ - `@MainActor` не ставить на Data-типы без необходимости.
43
+
44
+ # Требование к агенту
45
+
46
+ При добавлении/изменении API:
47
+ - Следовать существующим клиентам и mappers как эталону.
48
+ - Добавить/обновить mapper tests для нетривиальных преобразований.
49
+ - ViewModel и View не должны импортировать DTO-файлы.
@@ -0,0 +1,31 @@
1
+ ---
2
+ description: Persistence — SwiftData / Core Data / файлы / Keychain (не HTTP)
3
+ globs:
4
+ - "**/Persistence/**/*.swift"
5
+ - "**/Keychain/**/*.swift"
6
+ - "**/*Storage*.swift"
7
+ - "**/*Cache*.swift"
8
+ - "**/*SwiftData*.swift"
9
+ alwaysApply: false
10
+ ---
11
+
12
+ # Persistence (Data)
13
+
14
+ Отделить от HTTP (`networking-services.mdc`): здесь локальное хранение и секреты на диске/Keychain.
15
+
16
+ ## Рамка
17
+
18
+ - Выбор стека (**SwiftData / Core Data / UserDefaults / files**) — **как в репо**; не внедрять второй persistence-стек без задачи.
19
+ - Public API — протоколы в Domain (`…Repository` / `…Store`); реализации в Data.
20
+ - **Keychain** — только для credentials/токенов; не класть PII «для удобства» в UserDefaults.
21
+
22
+ ## Правила
23
+
24
+ - DTO/Entity persistence ≠ network DTO; маппинг явный.
25
+ - Миграции схемы — по принятому в репо процессу; не ломать silently.
26
+ - `@MainActor` на store — только если UI-facing; тяжёлый I/O — off-main + hop обратно.
27
+ - Ошибки — typed; не глотать `try?` на критичном persist.
28
+
29
+ ## Требование к агенту
30
+
31
+ Не смешивать URLSession и persistence в одном типе без фасада-репозитория. Тесты — in-memory / fake store.