@mmerterden/multi-agent-pipeline 20.36.0 → 20.37.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.
Files changed (222) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/docs/facts.json +2 -2
  3. package/docs/features.md +1 -1
  4. package/docs/recovery-guide.md +1 -1
  5. package/install/catalog-history.json +1 -1
  6. package/manifest.json +225 -148
  7. package/package.json +1 -1
  8. package/pipeline/commands/multi-agent/SKILL.md +33 -154
  9. package/pipeline/commands/multi-agent/analysis/SKILL.md +14 -68
  10. package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +5 -8
  11. package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +38 -109
  12. package/pipeline/commands/multi-agent/channels/SKILL.md +38 -167
  13. package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +37 -144
  14. package/pipeline/commands/multi-agent/design-check/SKILL.md +27 -131
  15. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +22 -48
  16. package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +37 -180
  17. package/pipeline/commands/multi-agent/jira/SKILL.md +16 -46
  18. package/pipeline/commands/multi-agent/manual-test/SKILL.md +12 -7
  19. package/pipeline/commands/multi-agent/refactor/SKILL.md +23 -184
  20. package/pipeline/commands/multi-agent/resume/SKILL.md +30 -136
  21. package/pipeline/commands/multi-agent/review/SKILL.md +24 -199
  22. package/pipeline/commands/multi-agent/setup/SKILL.md +25 -181
  23. package/pipeline/commands/multi-agent/stack/SKILL.md +9 -53
  24. package/pipeline/commands/multi-agent/status/SKILL.md +13 -2
  25. package/pipeline/commands/multi-agent/store-ready/SKILL.md +27 -226
  26. package/pipeline/commands/multi-agent/sync/SKILL.md +35 -164
  27. package/pipeline/commands/multi-agent/test-gen/SKILL.md +2 -4
  28. package/pipeline/commands/multi-agent/update/SKILL.md +18 -60
  29. package/pipeline/contract/CHANGELOG.md +9 -0
  30. package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
  31. package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
  32. package/pipeline/contract/fixtures/error-unsigned.json +1 -1
  33. package/pipeline/contract/fixtures/runs-awaiting-question.json +1 -1
  34. package/pipeline/contract/fixtures/runs-empty.json +1 -1
  35. package/pipeline/contract/fixtures/runs-failed.json +1 -1
  36. package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +1 -1
  37. package/pipeline/contract/fixtures/runs-pr-opened.json +1 -1
  38. package/pipeline/contract/fixtures/runs-running.json +1 -1
  39. package/pipeline/contract/manifest.json +5 -5
  40. package/pipeline/contract/types/index.d.ts +3 -2
  41. package/pipeline/multi-agent-refs/audit-guide.md +20 -0
  42. package/pipeline/multi-agent-refs/autopilot-on/details.md +148 -0
  43. package/pipeline/multi-agent-refs/channels/generator.md +14 -0
  44. package/pipeline/multi-agent-refs/channels/preview.md +13 -0
  45. package/pipeline/multi-agent-refs/channels/reference.md +46 -0
  46. package/pipeline/multi-agent-refs/complaint-analysis/phases.md +159 -0
  47. package/pipeline/multi-agent-refs/design-check/export.md +1 -0
  48. package/pipeline/multi-agent-refs/design-check/init-inventory.md +1 -1
  49. package/pipeline/multi-agent-refs/design-check/scope-and-ledger.md +64 -0
  50. package/pipeline/multi-agent-refs/features/analysis-command-notes.md +53 -0
  51. package/pipeline/multi-agent-refs/features/commit-multi-repo.md +63 -0
  52. package/pipeline/multi-agent-refs/features/dev-multi-repo.md +51 -0
  53. package/pipeline/multi-agent-refs/features/test-gap.md +40 -0
  54. package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
  55. package/pipeline/multi-agent-refs/garbage-collect/phases.md +60 -0
  56. package/pipeline/multi-agent-refs/ios-coding-standard/plan.md +71 -0
  57. package/pipeline/multi-agent-refs/ios-coding-standard/resolve-and-scan.md +135 -0
  58. package/pipeline/multi-agent-refs/jira/picker-detail.md +71 -0
  59. package/pipeline/multi-agent-refs/orchestrator/copilot-pipeline.md +88 -0
  60. package/pipeline/multi-agent-refs/orchestrator/dispatcher.md +96 -1
  61. package/pipeline/multi-agent-refs/orchestrator/phase-3-user-test.md +12 -9
  62. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +4 -4
  63. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +8 -47
  64. package/pipeline/multi-agent-refs/phases/phase-3-review.md +21 -65
  65. package/pipeline/multi-agent-refs/phases/phase-4-commit.md +9 -59
  66. package/pipeline/multi-agent-refs/phases/phase-5-report.md +0 -31
  67. package/pipeline/multi-agent-refs/refactor/sweep.md +190 -0
  68. package/pipeline/multi-agent-refs/resume/details.md +115 -2
  69. package/pipeline/multi-agent-refs/review/inputs.md +33 -1
  70. package/pipeline/multi-agent-refs/review/module-guides.md +9 -1
  71. package/pipeline/multi-agent-refs/review/panel.md +75 -0
  72. package/pipeline/multi-agent-refs/review/valven.md +5 -1
  73. package/pipeline/multi-agent-refs/rules.md +1 -1
  74. package/pipeline/multi-agent-refs/setup/hooks-and-plugins.md +4 -0
  75. package/pipeline/multi-agent-refs/setup/token-save-flow.md +13 -0
  76. package/pipeline/multi-agent-refs/stack/background.md +72 -0
  77. package/pipeline/multi-agent-refs/store-ready/gates.md +139 -0
  78. package/pipeline/multi-agent-refs/store-ready/report.md +40 -2
  79. package/pipeline/multi-agent-refs/sync/office.md +10 -0
  80. package/pipeline/multi-agent-refs/sync/overview.md +61 -0
  81. package/pipeline/multi-agent-refs/sync/repo.md +91 -0
  82. package/pipeline/multi-agent-refs/update/details.md +83 -0
  83. package/pipeline/office/index.html +6 -3
  84. package/pipeline/office/toolkit.json +1 -1
  85. package/pipeline/rules/figma-pipeline.md +6 -3
  86. package/pipeline/schemas/prefs.schema.json +1 -1
  87. package/pipeline/schemas/runs-index.schema.json +2 -1
  88. package/pipeline/scripts/_memory-policy.mjs +27 -5
  89. package/pipeline/scripts/checkpoint-fold.sh +59 -0
  90. package/pipeline/scripts/contract-server.mjs +1 -1
  91. package/pipeline/scripts/gate-ledger.mjs +1 -1
  92. package/pipeline/scripts/office-control.mjs +41 -15
  93. package/pipeline/scripts/offload-ref.sh +1 -1
  94. package/pipeline/scripts/rework-rulings.mjs +5 -3
  95. package/pipeline/scripts/runs-index.mjs +34 -7
  96. package/pipeline/scripts/scope-check-gate.mjs +15 -2
  97. package/pipeline/scripts/status-overview.mjs +401 -0
  98. package/pipeline/scripts/user-test-handoff.sh +203 -0
  99. package/pipeline/scripts/validate-planning.mjs +5 -3
  100. package/pipeline/scripts/validate-triage.mjs +2 -1
  101. package/pipeline/scripts/write-state.mjs +13 -4
  102. package/pipeline/skills/.skill-manifest.json +64 -64
  103. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +7 -70
  104. package/pipeline/skills/shared/core/apple-archive-compliance/references/examples.md +67 -0
  105. package/pipeline/skills/shared/core/apple-archive-compliance/references/version-history.md +8 -0
  106. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +10 -72
  107. package/pipeline/skills/shared/core/google-play-compliance/references/examples.md +69 -0
  108. package/pipeline/skills/shared/core/google-play-compliance/references/notes.md +7 -0
  109. package/pipeline/skills/shared/core/google-play-compliance/references/version-history.md +5 -0
  110. package/pipeline/skills/shared/core/multi-agent/SKILL.md +39 -262
  111. package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +35 -73
  112. package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +37 -337
  113. package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +27 -122
  114. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +8 -340
  115. package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +37 -180
  116. package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +12 -7
  117. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +23 -184
  118. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +14 -82
  119. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +25 -277
  120. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +13 -2
  121. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +73 -217
  122. package/pipeline/skills/shared/external/alarmkit/SKILL.md +11 -162
  123. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-code.md +257 -0
  124. package/pipeline/skills/shared/external/android-architecture/SKILL.md +7 -58
  125. package/pipeline/skills/shared/external/android-architecture/references/code-examples.md +68 -0
  126. package/pipeline/skills/shared/external/app-intents/SKILL.md +3 -45
  127. package/pipeline/skills/shared/external/app-intents/references/code-examples.md +54 -0
  128. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +5 -81
  129. package/pipeline/skills/shared/external/app-store-optimization/references/engagement-and-localization.md +96 -0
  130. package/pipeline/skills/shared/external/app-store-review/SKILL.md +6 -112
  131. package/pipeline/skills/shared/external/app-store-review/references/monetization-and-submission.md +138 -0
  132. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +10 -117
  133. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models-code.md +186 -0
  134. package/pipeline/skills/shared/external/authentication/SKILL.md +3 -50
  135. package/pipeline/skills/shared/external/authentication/references/code-examples.md +59 -0
  136. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +3 -84
  137. package/pipeline/skills/shared/external/callkit-voip/references/code-examples.md +93 -0
  138. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +7 -263
  139. package/pipeline/skills/shared/external/ci-cd-pipelines/references/pipeline-examples.md +281 -0
  140. package/pipeline/skills/shared/external/clean-code/SKILL.md +8 -41
  141. package/pipeline/skills/shared/external/clean-code/references/code-examples.md +56 -0
  142. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +8 -146
  143. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-code.md +214 -0
  144. package/pipeline/skills/shared/external/compose-components/SKILL.md +6 -80
  145. package/pipeline/skills/shared/external/compose-components/references/code-examples.md +89 -0
  146. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +5 -64
  147. package/pipeline/skills/shared/external/compose-navigation/references/code-examples.md +70 -0
  148. package/pipeline/skills/shared/external/core-data/SKILL.md +9 -157
  149. package/pipeline/skills/shared/external/core-data/references/core-data-code.md +221 -0
  150. package/pipeline/skills/shared/external/core-nfc/SKILL.md +3 -89
  151. package/pipeline/skills/shared/external/core-nfc/references/code-examples.md +98 -0
  152. package/pipeline/skills/shared/external/coreml/SKILL.md +17 -133
  153. package/pipeline/skills/shared/external/coreml/references/coreml-code.md +208 -0
  154. package/pipeline/skills/shared/external/css-modern/SKILL.md +8 -131
  155. package/pipeline/skills/shared/external/css-modern/references/code-examples.md +142 -0
  156. package/pipeline/skills/shared/external/database-patterns/SKILL.md +6 -103
  157. package/pipeline/skills/shared/external/database-patterns/references/orm-examples.md +112 -0
  158. package/pipeline/skills/shared/external/html-semantic/SKILL.md +7 -48
  159. package/pipeline/skills/shared/external/html-semantic/references/code-examples.md +54 -0
  160. package/pipeline/skills/shared/external/humanizer/SKILL.md +6 -19
  161. package/pipeline/skills/shared/external/humanizer/references/voice.md +24 -0
  162. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +13 -170
  163. package/pipeline/skills/shared/external/ios-accessibility/references/assistive-tech-review.md +224 -0
  164. package/pipeline/skills/shared/external/ios-localization/SKILL.md +2 -24
  165. package/pipeline/skills/shared/external/ios-localization/references/code-examples.md +30 -0
  166. package/pipeline/skills/shared/external/ios-networking/SKILL.md +3 -58
  167. package/pipeline/skills/shared/external/ios-networking/references/code-examples.md +67 -0
  168. package/pipeline/skills/shared/external/ios-security/SKILL.md +4 -64
  169. package/pipeline/skills/shared/external/ios-security/references/code-examples.md +74 -0
  170. package/pipeline/skills/shared/external/live-activities/SKILL.md +4 -90
  171. package/pipeline/skills/shared/external/live-activities/references/code-examples.md +108 -0
  172. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +9 -23
  173. package/pipeline/skills/shared/external/localization-reuse-map/references/project-settings.md +22 -0
  174. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +5 -95
  175. package/pipeline/skills/shared/external/mapkit-location/references/code-examples.md +117 -0
  176. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +7 -106
  177. package/pipeline/skills/shared/external/nextjs-app-router/references/app-router-examples.md +124 -0
  178. package/pipeline/skills/shared/external/permissionkit/SKILL.md +2 -31
  179. package/pipeline/skills/shared/external/permissionkit/references/code-examples.md +37 -0
  180. package/pipeline/skills/shared/external/play-store-review/SKILL.md +6 -74
  181. package/pipeline/skills/shared/external/play-store-review/references/signing-and-policies.md +83 -0
  182. package/pipeline/skills/shared/external/push-notifications/SKILL.md +8 -125
  183. package/pipeline/skills/shared/external/push-notifications/references/notification-code.md +176 -0
  184. package/pipeline/skills/shared/external/python-patterns/SKILL.md +7 -158
  185. package/pipeline/skills/shared/external/python-patterns/references/python-examples.md +176 -0
  186. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +7 -157
  187. package/pipeline/skills/shared/external/rest-api-design/references/api-examples.md +175 -0
  188. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +11 -230
  189. package/pipeline/skills/shared/external/swift-architecture/references/pattern-examples.md +295 -0
  190. package/pipeline/skills/shared/external/swift-codable/SKILL.md +17 -149
  191. package/pipeline/skills/shared/external/swift-codable/references/codable-recipes.md +207 -0
  192. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +12 -99
  193. package/pipeline/skills/shared/external/swift-concurrency/references/code-examples.md +100 -0
  194. package/pipeline/skills/shared/external/swift-concurrency/references/swift-6-2-additions.md +18 -0
  195. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +9 -78
  196. package/pipeline/skills/shared/external/swift-formatstyle/references/formatstyle-examples.md +113 -0
  197. package/pipeline/skills/shared/external/swift-language/SKILL.md +3 -56
  198. package/pipeline/skills/shared/external/swift-language/references/code-examples.md +65 -0
  199. package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +1 -0
  200. package/pipeline/skills/shared/external/swiftdata/SKILL.md +6 -122
  201. package/pipeline/skills/shared/external/swiftdata/references/code-examples.md +140 -0
  202. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +12 -139
  203. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/interop-code.md +198 -0
  204. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +9 -81
  205. package/pipeline/skills/shared/external/tailwind-css/references/code-examples.md +91 -0
  206. package/pipeline/skills/shared/external/testing-backend/SKILL.md +7 -207
  207. package/pipeline/skills/shared/external/testing-backend/references/testing-examples.md +225 -0
  208. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +8 -89
  209. package/pipeline/skills/shared/external/typescript-patterns/references/code-examples.md +100 -0
  210. package/pipeline/skills/shared/external/vision-framework/SKILL.md +2 -20
  211. package/pipeline/skills/shared/external/vision-framework/references/code-examples.md +26 -0
  212. package/pipeline/skills/shared/external/vue-composition/SKILL.md +7 -169
  213. package/pipeline/skills/shared/external/vue-composition/references/vue-examples.md +187 -0
  214. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +7 -174
  215. package/pipeline/skills/shared/external/web-accessibility/references/a11y-examples.md +192 -0
  216. package/pipeline/skills/shared/external/web-performance/SKILL.md +8 -66
  217. package/pipeline/skills/shared/external/web-performance/references/code-examples.md +77 -0
  218. package/pipeline/skills/shared/external/web-testing/SKILL.md +11 -186
  219. package/pipeline/skills/shared/external/web-testing/references/testing-examples.md +213 -0
  220. /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/format-and-output.md +0 -0
  221. /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/publish-and-snapshot.md +0 -0
  222. /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/sources-and-recipes.md +0 -0
@@ -0,0 +1,176 @@
1
+ # Python pattern examples
2
+
3
+ <!-- toc -->
4
+ - [Pydantic v2](#pydantic-v2)
5
+ - [Async/Await with asyncio](#asyncawait-with-asyncio)
6
+ - [Pattern Matching (match/case)](#pattern-matching-matchcase)
7
+ <!-- /toc -->
8
+
9
+ Code for Pydantic v2 models, asyncio patterns and structural pattern matching. SKILL.md keeps the principles and the rules.
10
+
11
+ ## Pydantic v2
12
+
13
+ ```python
14
+ from pydantic import BaseModel, Field, field_validator, model_validator, ConfigDict
15
+ from datetime import datetime
16
+
17
+ class CreateUserRequest(BaseModel):
18
+ model_config = ConfigDict(str_strip_whitespace=True, frozen=True)
19
+
20
+ name: str = Field(min_length=1, max_length=100)
21
+ email: str = Field(pattern=r'^[\w.-]+@[\w.-]+\.\w+$')
22
+ age: int = Field(ge=0, le=150)
23
+ role: Role = Role.USER
24
+ tags: list[str] = Field(default_factory=list, max_length=10)
25
+
26
+ @field_validator('email')
27
+ @classmethod
28
+ def normalize_email(cls, v: str) -> str:
29
+ return v.lower()
30
+
31
+ @model_validator(mode='after')
32
+ def validate_admin_age(self) -> 'CreateUserRequest':
33
+ if self.role == Role.ADMIN and self.age < 18:
34
+ raise ValueError("Admin must be 18 or older")
35
+ return self
36
+
37
+ class UserResponse(BaseModel):
38
+ id: str
39
+ name: str
40
+ email: str
41
+ role: Role
42
+ created_at: datetime
43
+
44
+ model_config = ConfigDict(from_attributes=True)
45
+
46
+ # Validation
47
+ try:
48
+ user = CreateUserRequest(name="Alice", email="ALICE@example.com", age=25)
49
+ print(user.email) # "alice@example.com" (normalized)
50
+ except ValidationError as e:
51
+ print(e.errors())
52
+
53
+ # Serialization
54
+ user_dict = user.model_dump()
55
+ user_json = user.model_dump_json()
56
+
57
+ # From ORM object
58
+ db_user = db.query(UserModel).first()
59
+ response = UserResponse.model_validate(db_user)
60
+ ```
61
+
62
+ ## Async/Await with asyncio
63
+
64
+ ```python
65
+ import asyncio
66
+ from collections.abc import AsyncIterator
67
+ import httpx
68
+
69
+ # Async function
70
+ async def fetch_user(user_id: str) -> dict:
71
+ async with httpx.AsyncClient() as client:
72
+ response = await client.get(f"https://api.example.com/users/{user_id}")
73
+ response.raise_for_status()
74
+ return response.json()
75
+
76
+ # Parallel execution
77
+ async def fetch_all_users(user_ids: list[str]) -> list[dict]:
78
+ async with httpx.AsyncClient() as client:
79
+ tasks = [
80
+ client.get(f"https://api.example.com/users/{uid}")
81
+ for uid in user_ids
82
+ ]
83
+ responses = await asyncio.gather(*tasks, return_exceptions=True)
84
+ return [
85
+ r.json() for r in responses
86
+ if not isinstance(r, Exception) and r.status_code == 200
87
+ ]
88
+
89
+ # Async context manager
90
+ from contextlib import asynccontextmanager
91
+
92
+ @asynccontextmanager
93
+ async def get_db_session() -> AsyncIterator[AsyncSession]:
94
+ session = AsyncSession(engine)
95
+ try:
96
+ yield session
97
+ await session.commit()
98
+ except Exception:
99
+ await session.rollback()
100
+ raise
101
+ finally:
102
+ await session.close()
103
+
104
+ # Async generator
105
+ async def stream_events(url: str) -> AsyncIterator[dict]:
106
+ async with httpx.AsyncClient() as client:
107
+ async with client.stream("GET", url) as response:
108
+ async for line in response.aiter_lines():
109
+ if line.startswith("data: "):
110
+ yield json.loads(line[6:])
111
+
112
+ # Semaphore for rate limiting
113
+ async def fetch_with_limit(urls: list[str], max_concurrent: int = 10) -> list[str]:
114
+ semaphore = asyncio.Semaphore(max_concurrent)
115
+
116
+ async def fetch_one(url: str) -> str:
117
+ async with semaphore:
118
+ async with httpx.AsyncClient() as client:
119
+ resp = await client.get(url)
120
+ return resp.text
121
+
122
+ return await asyncio.gather(*[fetch_one(url) for url in urls])
123
+ ```
124
+
125
+ ## Pattern Matching (match/case)
126
+
127
+ ```python
128
+ from dataclasses import dataclass
129
+
130
+ @dataclass
131
+ class Point:
132
+ x: float
133
+ y: float
134
+
135
+ def describe_point(point: Point) -> str:
136
+ match point:
137
+ case Point(x=0, y=0):
138
+ return "origin"
139
+ case Point(x=0, y=y):
140
+ return f"on y-axis at y={y}"
141
+ case Point(x=x, y=0):
142
+ return f"on x-axis at x={x}"
143
+ case Point(x=x, y=y) if x == y:
144
+ return f"on diagonal at {x}"
145
+ case _:
146
+ return f"at ({point.x}, {point.y})"
147
+
148
+ # Matching on type and structure
149
+ def handle_response(response: dict) -> str:
150
+ match response:
151
+ case {"status": 200, "data": data}:
152
+ return f"Success: {data}"
153
+ case {"status": 404}:
154
+ return "Not found"
155
+ case {"status": status} if 500 <= status < 600:
156
+ return f"Server error: {status}"
157
+ case {"error": str(message)}:
158
+ return f"Error: {message}"
159
+ case _:
160
+ return "Unknown response"
161
+
162
+ # Matching sequences
163
+ def process_command(command: list[str]) -> None:
164
+ match command:
165
+ case ["quit" | "exit"]:
166
+ sys.exit(0)
167
+ case ["go", direction]:
168
+ move(direction)
169
+ case ["pick", "up", item]:
170
+ pick_up(item)
171
+ case ["drop", *items] if items:
172
+ for item in items:
173
+ drop(item)
174
+ case _:
175
+ print(f"Unknown command: {' '.join(command)}")
176
+ ```
@@ -82,93 +82,13 @@ GET /api/v1/posts?fields=id,title,slug # Sparse fieldsets
82
82
 
83
83
  ## Response Envelope
84
84
 
85
- ```typescript
86
- // Consistent response shape
87
-
88
- // Success: single resource
89
- {
90
- "data": {
91
- "id": "user_abc123",
92
- "type": "user",
93
- "attributes": {
94
- "name": "Alice Johnson",
95
- "email": "alice@example.com",
96
- "role": "admin",
97
- "created_at": "2025-01-15T10:30:00Z"
98
- }
99
- }
100
- }
101
-
102
- // Success: collection
103
- {
104
- "data": [
105
- { "id": "post_1", "type": "post", "attributes": { ... } },
106
- { "id": "post_2", "type": "post", "attributes": { ... } }
107
- ],
108
- "meta": {
109
- "total": 150,
110
- "page": 1,
111
- "per_page": 20,
112
- "has_next": true
113
- }
114
- }
115
-
116
- // Error response
117
- {
118
- "error": {
119
- "code": "VALIDATION_ERROR",
120
- "message": "Request validation failed",
121
- "details": [
122
- { "field": "email", "message": "Must be a valid email address" },
123
- { "field": "age", "message": "Must be between 0 and 150" }
124
- ],
125
- "request_id": "req_xyz789"
126
- }
127
- }
128
- ```
85
+ Code for this section: [REST API examples](references/api-examples.md).
129
86
 
130
87
  ## Pagination
131
88
 
132
89
  ### Cursor-Based (Recommended)
133
90
 
134
- ```typescript
135
- // Request
136
- // GET /api/v1/posts?limit=20&after=eyJpZCI6InBvc3RfMTAwIn0
137
-
138
- // Response
139
- {
140
- "data": [ ... ],
141
- "pagination": {
142
- "has_next": true,
143
- "has_prev": false,
144
- "next_cursor": "eyJpZCI6InBvc3RfMTIwIn0",
145
- "prev_cursor": null
146
- }
147
- }
148
-
149
- // Server implementation (Node.js / Express)
150
- async function listPosts(req: Request, res: Response) {
151
- const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);
152
- const cursor = req.query.after ? decodeCursor(req.query.after as string) : null;
153
-
154
- const posts = await db.post.findMany({
155
- where: cursor ? { id: { gt: cursor.id } } : undefined,
156
- orderBy: { id: 'asc' },
157
- take: limit + 1, // Fetch one extra to check has_next
158
- });
159
-
160
- const hasNext = posts.length > limit;
161
- if (hasNext) posts.pop();
162
-
163
- res.json({
164
- data: posts,
165
- pagination: {
166
- has_next: hasNext,
167
- next_cursor: hasNext ? encodeCursor({ id: posts[posts.length - 1].id }) : null,
168
- },
169
- });
170
- }
171
- ```
91
+ Code for this section: [REST API examples](references/api-examples.md).
172
92
 
173
93
  ### Offset-Based (Simple, for small datasets)
174
94
 
@@ -279,81 +199,7 @@ app.get('/api/v1/posts/:id', async (req, res) => {
279
199
 
280
200
  ## OpenAPI / Swagger Documentation
281
201
 
282
- ```yaml
283
- # openapi.yaml
284
- openapi: 3.1.0
285
- info:
286
- title: My API
287
- version: 1.0.0
288
- description: Production REST API
289
-
290
- servers:
291
- - url: https://api.example.com/v1
292
-
293
- paths:
294
- /users:
295
- get:
296
- summary: List users
297
- tags: [Users]
298
- parameters:
299
- - name: page
300
- in: query
301
- schema: { type: integer, minimum: 1, default: 1 }
302
- - name: per_page
303
- in: query
304
- schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
305
- responses:
306
- '200':
307
- description: List of users
308
- content:
309
- application/json:
310
- schema:
311
- type: object
312
- properties:
313
- data:
314
- type: array
315
- items: { $ref: '#/components/schemas/User' }
316
- meta:
317
- $ref: '#/components/schemas/PaginationMeta'
318
-
319
- post:
320
- summary: Create user
321
- tags: [Users]
322
- requestBody:
323
- required: true
324
- content:
325
- application/json:
326
- schema: { $ref: '#/components/schemas/CreateUserRequest' }
327
- responses:
328
- '201':
329
- description: User created
330
- headers:
331
- Location:
332
- schema: { type: string }
333
- content:
334
- application/json:
335
- schema:
336
- type: object
337
- properties:
338
- data: { $ref: '#/components/schemas/User' }
339
- '422':
340
- description: Validation error
341
- content:
342
- application/json:
343
- schema: { $ref: '#/components/schemas/ErrorResponse' }
344
-
345
- components:
346
- schemas:
347
- User:
348
- type: object
349
- required: [id, name, email, role, created_at]
350
- properties:
351
- id: { type: string, format: uuid }
352
- name: { type: string }
353
- email: { type: string, format: email }
354
- role: { type: string, enum: [admin, user, viewer] }
355
- created_at: { type: string, format: date-time }
356
- ```
202
+ Code for this section: [REST API examples](references/api-examples.md).
357
203
 
358
204
  ## Do's
359
205
 
@@ -387,3 +233,7 @@ components:
387
233
  | CORS errors | Missing headers on OPTIONS response | Configure CORS middleware with allowed origins |
388
234
  | Stale cache | No cache invalidation strategy | Use ETag + conditional requests, short max-age |
389
235
  | Breaking clients | Schema change without versioning | Add new version, deprecate old with Sunset header |
236
+
237
+ ## References
238
+
239
+ - [REST API examples](references/api-examples.md): open when shaping response envelopes, implementing cursor pagination or writing an OpenAPI spec.
@@ -0,0 +1,175 @@
1
+ # REST API examples
2
+
3
+ <!-- toc -->
4
+ - [Response Envelope](#response-envelope)
5
+ - [Cursor-Based (Recommended)](#cursor-based-recommended)
6
+ - [OpenAPI / Swagger Documentation](#openapi-swagger-documentation)
7
+ <!-- /toc -->
8
+
9
+ Response envelope shapes, cursor pagination code and an OpenAPI document. SKILL.md keeps the URL, method, status, versioning, rate limiting and caching rules.
10
+
11
+ ## Response Envelope
12
+
13
+ ```typescript
14
+ // Consistent response shape
15
+
16
+ // Success: single resource
17
+ {
18
+ "data": {
19
+ "id": "user_abc123",
20
+ "type": "user",
21
+ "attributes": {
22
+ "name": "Alice Johnson",
23
+ "email": "alice@example.com",
24
+ "role": "admin",
25
+ "created_at": "2025-01-15T10:30:00Z"
26
+ }
27
+ }
28
+ }
29
+
30
+ // Success: collection
31
+ {
32
+ "data": [
33
+ { "id": "post_1", "type": "post", "attributes": { ... } },
34
+ { "id": "post_2", "type": "post", "attributes": { ... } }
35
+ ],
36
+ "meta": {
37
+ "total": 150,
38
+ "page": 1,
39
+ "per_page": 20,
40
+ "has_next": true
41
+ }
42
+ }
43
+
44
+ // Error response
45
+ {
46
+ "error": {
47
+ "code": "VALIDATION_ERROR",
48
+ "message": "Request validation failed",
49
+ "details": [
50
+ { "field": "email", "message": "Must be a valid email address" },
51
+ { "field": "age", "message": "Must be between 0 and 150" }
52
+ ],
53
+ "request_id": "req_xyz789"
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### Cursor-Based (Recommended)
59
+
60
+ ```typescript
61
+ // Request
62
+ // GET /api/v1/posts?limit=20&after=eyJpZCI6InBvc3RfMTAwIn0
63
+
64
+ // Response
65
+ {
66
+ "data": [ ... ],
67
+ "pagination": {
68
+ "has_next": true,
69
+ "has_prev": false,
70
+ "next_cursor": "eyJpZCI6InBvc3RfMTIwIn0",
71
+ "prev_cursor": null
72
+ }
73
+ }
74
+
75
+ // Server implementation (Node.js / Express)
76
+ async function listPosts(req: Request, res: Response) {
77
+ const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);
78
+ const cursor = req.query.after ? decodeCursor(req.query.after as string) : null;
79
+
80
+ const posts = await db.post.findMany({
81
+ where: cursor ? { id: { gt: cursor.id } } : undefined,
82
+ orderBy: { id: 'asc' },
83
+ take: limit + 1, // Fetch one extra to check has_next
84
+ });
85
+
86
+ const hasNext = posts.length > limit;
87
+ if (hasNext) posts.pop();
88
+
89
+ res.json({
90
+ data: posts,
91
+ pagination: {
92
+ has_next: hasNext,
93
+ next_cursor: hasNext ? encodeCursor({ id: posts[posts.length - 1].id }) : null,
94
+ },
95
+ });
96
+ }
97
+ ```
98
+
99
+ ## OpenAPI / Swagger Documentation
100
+
101
+ ```yaml
102
+ # openapi.yaml
103
+ openapi: 3.1.0
104
+ info:
105
+ title: My API
106
+ version: 1.0.0
107
+ description: Production REST API
108
+
109
+ servers:
110
+ - url: https://api.example.com/v1
111
+
112
+ paths:
113
+ /users:
114
+ get:
115
+ summary: List users
116
+ tags: [Users]
117
+ parameters:
118
+ - name: page
119
+ in: query
120
+ schema: { type: integer, minimum: 1, default: 1 }
121
+ - name: per_page
122
+ in: query
123
+ schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
124
+ responses:
125
+ '200':
126
+ description: List of users
127
+ content:
128
+ application/json:
129
+ schema:
130
+ type: object
131
+ properties:
132
+ data:
133
+ type: array
134
+ items: { $ref: '#/components/schemas/User' }
135
+ meta:
136
+ $ref: '#/components/schemas/PaginationMeta'
137
+
138
+ post:
139
+ summary: Create user
140
+ tags: [Users]
141
+ requestBody:
142
+ required: true
143
+ content:
144
+ application/json:
145
+ schema: { $ref: '#/components/schemas/CreateUserRequest' }
146
+ responses:
147
+ '201':
148
+ description: User created
149
+ headers:
150
+ Location:
151
+ schema: { type: string }
152
+ content:
153
+ application/json:
154
+ schema:
155
+ type: object
156
+ properties:
157
+ data: { $ref: '#/components/schemas/User' }
158
+ '422':
159
+ description: Validation error
160
+ content:
161
+ application/json:
162
+ schema: { $ref: '#/components/schemas/ErrorResponse' }
163
+
164
+ components:
165
+ schemas:
166
+ User:
167
+ type: object
168
+ required: [id, name, email, role, created_at]
169
+ properties:
170
+ id: { type: string, format: uuid }
171
+ name: { type: string }
172
+ email: { type: string, format: email }
173
+ role: { type: string, enum: [admin, user, viewer] }
174
+ created_at: { type: string, format: date-time }
175
+ ```