argos-harness 0.1.0

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 (217) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/assets/agents/auditor.md +140 -0
  4. package/assets/agents/commit-pr-pilot.md +154 -0
  5. package/assets/agents/explorer.md +93 -0
  6. package/assets/agents/implementer.md +117 -0
  7. package/assets/agents/leader.md +149 -0
  8. package/assets/agents/researcher.md +89 -0
  9. package/assets/agents/review-readability.md +87 -0
  10. package/assets/agents/review-reliability.md +100 -0
  11. package/assets/agents/review-resilience.md +87 -0
  12. package/assets/agents/review-risk.md +87 -0
  13. package/assets/agents/reviewer.md +167 -0
  14. package/assets/agents/ticket-audit.md +129 -0
  15. package/assets/hooks/argos-guard-destructive.sh +127 -0
  16. package/assets/hooks/argos-quality-gate.sh +129 -0
  17. package/assets/managed/aterrizaje.md +24 -0
  18. package/assets/managed/formato-respuesta.md +21 -0
  19. package/assets/managed/identidad.md +48 -0
  20. package/assets/managed/operaciones-seguras.md +14 -0
  21. package/assets/managed/orquestacion.md +169 -0
  22. package/assets/output-styles/argos.md +71 -0
  23. package/assets/skills/ai-sdk-5/SKILL.md +230 -0
  24. package/assets/skills/angular/SKILL.md +19 -0
  25. package/assets/skills/angular/references/architecture.md +137 -0
  26. package/assets/skills/angular/references/core.md +197 -0
  27. package/assets/skills/angular/references/forms.md +115 -0
  28. package/assets/skills/angular/references/performance.md +124 -0
  29. package/assets/skills/apollo-client/SKILL.md +61 -0
  30. package/assets/skills/app-blueprint/SKILL.md +45 -0
  31. package/assets/skills/app-blueprint/assets/module-template.md +48 -0
  32. package/assets/skills/app-blueprint/assets/system-template.md +38 -0
  33. package/assets/skills/app-blueprint/references/workflow.md +101 -0
  34. package/assets/skills/app-builder/SKILL.md +43 -0
  35. package/assets/skills/app-builder/phases/0-product.md +58 -0
  36. package/assets/skills/app-builder/phases/1-scaffold.md +33 -0
  37. package/assets/skills/app-builder/phases/10-store.md +40 -0
  38. package/assets/skills/app-builder/phases/2-data.md +34 -0
  39. package/assets/skills/app-builder/phases/3-domain.md +33 -0
  40. package/assets/skills/app-builder/phases/4-ui-nav.md +32 -0
  41. package/assets/skills/app-builder/phases/5-identity.md +30 -0
  42. package/assets/skills/app-builder/phases/6-polish.md +34 -0
  43. package/assets/skills/app-builder/phases/7-brand.md +31 -0
  44. package/assets/skills/app-builder/phases/8-web.md +30 -0
  45. package/assets/skills/app-builder/phases/9-docs.md +31 -0
  46. package/assets/skills/app-ia/SKILL.md +54 -0
  47. package/assets/skills/astro/SKILL.md +39 -0
  48. package/assets/skills/axios/SKILL.md +61 -0
  49. package/assets/skills/branch-pr/SKILL.md +200 -0
  50. package/assets/skills/bullmq/SKILL.md +55 -0
  51. package/assets/skills/chained-pr/SKILL.md +48 -0
  52. package/assets/skills/chained-pr/references/chaining-details.md +99 -0
  53. package/assets/skills/cognitive-doc-design/SKILL.md +81 -0
  54. package/assets/skills/comment-writer/SKILL.md +74 -0
  55. package/assets/skills/dashboard-ia/SKILL.md +54 -0
  56. package/assets/skills/django-drf/SKILL.md +180 -0
  57. package/assets/skills/go-testing/SKILL.md +47 -0
  58. package/assets/skills/go-testing/references/examples.md +89 -0
  59. package/assets/skills/issue-creation/SKILL.md +223 -0
  60. package/assets/skills/jira-epic/SKILL.md +306 -0
  61. package/assets/skills/jira-task/SKILL.md +382 -0
  62. package/assets/skills/judgment-day/SKILL.md +52 -0
  63. package/assets/skills/judgment-day/references/prompts-and-formats.md +98 -0
  64. package/assets/skills/lightsail-deploy/SKILL.md +44 -0
  65. package/assets/skills/lightsail-deploy/references/runbook.md +102 -0
  66. package/assets/skills/loop-back-debug/SKILL.md +102 -0
  67. package/assets/skills/mantine-form/SKILL.md +57 -0
  68. package/assets/skills/mongoose/SKILL.md +66 -0
  69. package/assets/skills/nextjs-15/SKILL.md +144 -0
  70. package/assets/skills/not-boring-mobile/SKILL.md +43 -0
  71. package/assets/skills/not-boring-mobile/references/not-boring-playbook.md +65 -0
  72. package/assets/skills/playwright/SKILL.md +315 -0
  73. package/assets/skills/pr-comments/SKILL.md +93 -0
  74. package/assets/skills/pr-create/SKILL.md +64 -0
  75. package/assets/skills/promo-video/SKILL.md +52 -0
  76. package/assets/skills/promo-video/assets/package.template.json +22 -0
  77. package/assets/skills/promo-video/assets/promo.template.tsx +469 -0
  78. package/assets/skills/promo-video/assets/theme.template.ts +27 -0
  79. package/assets/skills/promo-video/references/pipeline.md +119 -0
  80. package/assets/skills/promo-video-web/SKILL.md +51 -0
  81. package/assets/skills/promo-video-web/assets/browser-promo.template.tsx +385 -0
  82. package/assets/skills/promo-video-web/assets/capture.template.ts +70 -0
  83. package/assets/skills/promo-video-web/assets/package.template.json +26 -0
  84. package/assets/skills/promo-video-web/references/pipeline.md +84 -0
  85. package/assets/skills/pytest/SKILL.md +180 -0
  86. package/assets/skills/react-19/SKILL.md +118 -0
  87. package/assets/skills/react-hook-form/SKILL.md +59 -0
  88. package/assets/skills/react-router/SKILL.md +60 -0
  89. package/assets/skills/redux-toolkit/SKILL.md +60 -0
  90. package/assets/skills/review-diff/SKILL.md +101 -0
  91. package/assets/skills/ship-docs/SKILL.md +45 -0
  92. package/assets/skills/ship-docs/references/ship-docs-playbook.md +31 -0
  93. package/assets/skills/skill-creator/SKILL.md +97 -0
  94. package/assets/skills/skill-creator/assets/SKILL-TEMPLATE.md +68 -0
  95. package/assets/skills/skill-creator/references/skill-style-guide.md +79 -0
  96. package/assets/skills/skill-improver/SKILL.md +50 -0
  97. package/assets/skills/skill-improver/references/skill-style-guide.md +79 -0
  98. package/assets/skills/socketio/SKILL.md +58 -0
  99. package/assets/skills/spec-bootstrap/SKILL.md +62 -0
  100. package/assets/skills/store-ship/SKILL.md +52 -0
  101. package/assets/skills/store-ship/assets/android-supply.template.md +22 -0
  102. package/assets/skills/store-ship/assets/eas.template.json +32 -0
  103. package/assets/skills/store-ship/assets/maestro-flow.template.yaml +27 -0
  104. package/assets/skills/store-ship/assets/store.config.template.json +28 -0
  105. package/assets/skills/store-ship/references/pipeline.md +198 -0
  106. package/assets/skills/stripe/SKILL.md +83 -0
  107. package/assets/skills/tailwind-4/SKILL.md +193 -0
  108. package/assets/skills/tamagui/SKILL.md +60 -0
  109. package/assets/skills/tanstack-query/SKILL.md +58 -0
  110. package/assets/skills/ticket-intake/SKILL.md +55 -0
  111. package/assets/skills/typescript/SKILL.md +134 -0
  112. package/assets/skills/verify-before-done/SKILL.md +111 -0
  113. package/assets/skills/webapp-rebuilder/SKILL.md +48 -0
  114. package/assets/skills/webapp-rebuilder/assets/charter-template.md +46 -0
  115. package/assets/skills/webapp-rebuilder/references/workflow.md +47 -0
  116. package/assets/skills/winston-logging/SKILL.md +61 -0
  117. package/assets/skills/work-unit-commits/SKILL.md +84 -0
  118. package/assets/skills/zod-4/SKILL.md +210 -0
  119. package/assets/skills/zustand-5/SKILL.md +216 -0
  120. package/bin/argos.js +6 -0
  121. package/dist/commands/adopt.d.ts +35 -0
  122. package/dist/commands/adopt.d.ts.map +1 -0
  123. package/dist/commands/adopt.js +347 -0
  124. package/dist/commands/adopt.js.map +1 -0
  125. package/dist/commands/doctor.d.ts +20 -0
  126. package/dist/commands/doctor.d.ts.map +1 -0
  127. package/dist/commands/doctor.js +478 -0
  128. package/dist/commands/doctor.js.map +1 -0
  129. package/dist/commands/init.d.ts +32 -0
  130. package/dist/commands/init.d.ts.map +1 -0
  131. package/dist/commands/init.js +358 -0
  132. package/dist/commands/init.js.map +1 -0
  133. package/dist/commands/remove.d.ts +62 -0
  134. package/dist/commands/remove.d.ts.map +1 -0
  135. package/dist/commands/remove.js +487 -0
  136. package/dist/commands/remove.js.map +1 -0
  137. package/dist/commands/workspace.d.ts +73 -0
  138. package/dist/commands/workspace.d.ts.map +1 -0
  139. package/dist/commands/workspace.js +354 -0
  140. package/dist/commands/workspace.js.map +1 -0
  141. package/dist/index.d.ts +2 -0
  142. package/dist/index.d.ts.map +1 -0
  143. package/dist/index.js +24 -0
  144. package/dist/index.js.map +1 -0
  145. package/dist/lib/assets.d.ts +29 -0
  146. package/dist/lib/assets.d.ts.map +1 -0
  147. package/dist/lib/assets.js +57 -0
  148. package/dist/lib/assets.js.map +1 -0
  149. package/dist/lib/atomic-write.d.ts +17 -0
  150. package/dist/lib/atomic-write.d.ts.map +1 -0
  151. package/dist/lib/atomic-write.js +41 -0
  152. package/dist/lib/atomic-write.js.map +1 -0
  153. package/dist/lib/backup.d.ts +11 -0
  154. package/dist/lib/backup.d.ts.map +1 -0
  155. package/dist/lib/backup.js +42 -0
  156. package/dist/lib/backup.js.map +1 -0
  157. package/dist/lib/config.d.ts +36 -0
  158. package/dist/lib/config.d.ts.map +1 -0
  159. package/dist/lib/config.js +52 -0
  160. package/dist/lib/config.js.map +1 -0
  161. package/dist/lib/detect.d.ts +58 -0
  162. package/dist/lib/detect.d.ts.map +1 -0
  163. package/dist/lib/detect.js +330 -0
  164. package/dist/lib/detect.js.map +1 -0
  165. package/dist/lib/ficha.d.ts +10 -0
  166. package/dist/lib/ficha.d.ts.map +1 -0
  167. package/dist/lib/ficha.js +38 -0
  168. package/dist/lib/ficha.js.map +1 -0
  169. package/dist/lib/git.d.ts +27 -0
  170. package/dist/lib/git.d.ts.map +1 -0
  171. package/dist/lib/git.js +79 -0
  172. package/dist/lib/git.js.map +1 -0
  173. package/dist/lib/managed-files.d.ts +35 -0
  174. package/dist/lib/managed-files.d.ts.map +1 -0
  175. package/dist/lib/managed-files.js +97 -0
  176. package/dist/lib/managed-files.js.map +1 -0
  177. package/dist/lib/markers.d.ts +64 -0
  178. package/dist/lib/markers.d.ts.map +1 -0
  179. package/dist/lib/markers.js +157 -0
  180. package/dist/lib/markers.js.map +1 -0
  181. package/dist/lib/navori-import.d.ts +42 -0
  182. package/dist/lib/navori-import.d.ts.map +1 -0
  183. package/dist/lib/navori-import.js +65 -0
  184. package/dist/lib/navori-import.js.map +1 -0
  185. package/dist/lib/openclaw-agents.d.ts +53 -0
  186. package/dist/lib/openclaw-agents.d.ts.map +1 -0
  187. package/dist/lib/openclaw-agents.js +118 -0
  188. package/dist/lib/openclaw-agents.js.map +1 -0
  189. package/dist/lib/package-root.d.ts +11 -0
  190. package/dist/lib/package-root.d.ts.map +1 -0
  191. package/dist/lib/package-root.js +23 -0
  192. package/dist/lib/package-root.js.map +1 -0
  193. package/dist/lib/paths.d.ts +11 -0
  194. package/dist/lib/paths.d.ts.map +1 -0
  195. package/dist/lib/paths.js +16 -0
  196. package/dist/lib/paths.js.map +1 -0
  197. package/dist/lib/settings-merge.d.ts +125 -0
  198. package/dist/lib/settings-merge.d.ts.map +1 -0
  199. package/dist/lib/settings-merge.js +373 -0
  200. package/dist/lib/settings-merge.js.map +1 -0
  201. package/dist/lib/version.d.ts +3 -0
  202. package/dist/lib/version.d.ts.map +1 -0
  203. package/dist/lib/version.js +13 -0
  204. package/dist/lib/version.js.map +1 -0
  205. package/dist/lib/which.d.ts +8 -0
  206. package/dist/lib/which.d.ts.map +1 -0
  207. package/dist/lib/which.js +30 -0
  208. package/dist/lib/which.js.map +1 -0
  209. package/dist/lib/workspaces.d.ts +133 -0
  210. package/dist/lib/workspaces.d.ts.map +1 -0
  211. package/dist/lib/workspaces.js +241 -0
  212. package/dist/lib/workspaces.js.map +1 -0
  213. package/dist/lib/zod-messages.d.ts +4 -0
  214. package/dist/lib/zod-messages.d.ts.map +1 -0
  215. package/dist/lib/zod-messages.js +28 -0
  216. package/dist/lib/zod-messages.js.map +1 -0
  217. package/package.json +44 -0
@@ -0,0 +1,180 @@
1
+ ---
2
+ name: pytest
3
+ description: Pytest testing patterns for Python. Trigger: When writing Python tests - fixtures, mocking, markers.
4
+ ---
5
+
6
+ ## Basic Test Structure
7
+
8
+ ```python
9
+ import pytest
10
+
11
+ class TestUserService:
12
+ def test_create_user_success(self):
13
+ user = create_user(name="John", email="john@test.com")
14
+ assert user.name == "John"
15
+ assert user.email == "john@test.com"
16
+
17
+ def test_create_user_invalid_email_fails(self):
18
+ with pytest.raises(ValueError, match="Invalid email"):
19
+ create_user(name="John", email="invalid")
20
+ ```
21
+
22
+ ## Fixtures
23
+
24
+ ```python
25
+ import pytest
26
+
27
+ @pytest.fixture
28
+ def user():
29
+ """Create a test user."""
30
+ return User(name="Test User", email="test@example.com")
31
+
32
+ @pytest.fixture
33
+ def authenticated_client(client, user):
34
+ """Client with authenticated user."""
35
+ client.force_login(user)
36
+ return client
37
+
38
+ # Fixture with teardown
39
+ @pytest.fixture
40
+ def temp_file():
41
+ path = Path("/tmp/test_file.txt")
42
+ path.write_text("test content")
43
+ yield path # Test runs here
44
+ path.unlink() # Cleanup after test
45
+
46
+ # Fixture scopes
47
+ @pytest.fixture(scope="module") # Once per module
48
+ @pytest.fixture(scope="class") # Once per class
49
+ @pytest.fixture(scope="session") # Once per test session
50
+ ```
51
+
52
+ ## conftest.py
53
+
54
+ ```python
55
+ # tests/conftest.py - Shared fixtures
56
+ import pytest
57
+
58
+ @pytest.fixture
59
+ def db_session():
60
+ session = create_session()
61
+ yield session
62
+ session.rollback()
63
+
64
+ @pytest.fixture
65
+ def api_client():
66
+ return TestClient(app)
67
+ ```
68
+
69
+ ## Mocking
70
+
71
+ ```python
72
+ from unittest.mock import patch, MagicMock
73
+
74
+ class TestPaymentService:
75
+ def test_process_payment_success(self):
76
+ with patch("services.payment.stripe_client") as mock_stripe:
77
+ mock_stripe.charge.return_value = {"id": "ch_123", "status": "succeeded"}
78
+
79
+ result = process_payment(amount=100)
80
+
81
+ assert result["status"] == "succeeded"
82
+ mock_stripe.charge.assert_called_once_with(amount=100)
83
+
84
+ def test_process_payment_failure(self):
85
+ with patch("services.payment.stripe_client") as mock_stripe:
86
+ mock_stripe.charge.side_effect = PaymentError("Card declined")
87
+
88
+ with pytest.raises(PaymentError):
89
+ process_payment(amount=100)
90
+
91
+ # MagicMock for complex objects
92
+ def test_with_mock_object():
93
+ mock_user = MagicMock()
94
+ mock_user.id = "user-123"
95
+ mock_user.name = "Test User"
96
+ mock_user.is_active = True
97
+
98
+ result = get_user_info(mock_user)
99
+ assert result["name"] == "Test User"
100
+ ```
101
+
102
+ ## Parametrize
103
+
104
+ ```python
105
+ @pytest.mark.parametrize("input,expected", [
106
+ ("hello", "HELLO"),
107
+ ("world", "WORLD"),
108
+ ("pytest", "PYTEST"),
109
+ ])
110
+ def test_uppercase(input, expected):
111
+ assert input.upper() == expected
112
+
113
+ @pytest.mark.parametrize("email,is_valid", [
114
+ ("user@example.com", True),
115
+ ("invalid-email", False),
116
+ ("", False),
117
+ ("user@.com", False),
118
+ ])
119
+ def test_email_validation(email, is_valid):
120
+ assert validate_email(email) == is_valid
121
+ ```
122
+
123
+ ## Markers
124
+
125
+ ```python
126
+ # pytest.ini or pyproject.toml
127
+ [tool.pytest.ini_options]
128
+ markers = [
129
+ "slow: marks tests as slow",
130
+ "integration: marks integration tests",
131
+ ]
132
+
133
+ # Usage
134
+ @pytest.mark.slow
135
+ def test_large_data_processing():
136
+ ...
137
+
138
+ @pytest.mark.integration
139
+ def test_database_connection():
140
+ ...
141
+
142
+ @pytest.mark.skip(reason="Not implemented yet")
143
+ def test_future_feature():
144
+ ...
145
+
146
+ @pytest.mark.skipif(sys.platform == "win32", reason="Unix only")
147
+ def test_unix_specific():
148
+ ...
149
+
150
+ # Run specific markers
151
+ # pytest -m "not slow"
152
+ # pytest -m "integration"
153
+ ```
154
+
155
+ ## Async Tests
156
+
157
+ ```python
158
+ import pytest
159
+
160
+ @pytest.mark.asyncio
161
+ async def test_async_function():
162
+ result = await async_fetch_data()
163
+ assert result is not None
164
+ ```
165
+
166
+ ## Commands
167
+
168
+ ```bash
169
+ pytest # Run all tests
170
+ pytest -v # Verbose output
171
+ pytest -x # Stop on first failure
172
+ pytest -k "test_user" # Filter by name
173
+ pytest -m "not slow" # Filter by marker
174
+ pytest --cov=src # With coverage
175
+ pytest -n auto # Parallel (pytest-xdist)
176
+ pytest --tb=short # Short traceback
177
+ ```
178
+
179
+ ## Keywords
180
+ pytest, python, testing, fixtures, mocking, parametrize, markers
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: react-19
3
+ description: React 19 patterns with React Compiler. Trigger: When writing React components - no useMemo/useCallback needed.
4
+ ---
5
+
6
+ ## No Manual Memoization (REQUIRED)
7
+
8
+ ```typescript
9
+ // ✅ React Compiler handles optimization automatically
10
+ function Component({ items }) {
11
+ const filtered = items.filter(x => x.active);
12
+ const sorted = filtered.sort((a, b) => a.name.localeCompare(b.name));
13
+
14
+ const handleClick = (id) => {
15
+ console.log(id);
16
+ };
17
+
18
+ return <List items={sorted} onClick={handleClick} />;
19
+ }
20
+
21
+ // ❌ NEVER: Manual memoization
22
+ const filtered = useMemo(() => items.filter(x => x.active), [items]);
23
+ const handleClick = useCallback((id) => console.log(id), []);
24
+ ```
25
+
26
+ ## Imports (REQUIRED)
27
+
28
+ ```typescript
29
+ // ✅ ALWAYS: Named imports
30
+ import { useState, useEffect, useRef } from "react";
31
+
32
+ // ❌ NEVER
33
+ import React from "react";
34
+ import * as React from "react";
35
+ ```
36
+
37
+ ## Server Components First
38
+
39
+ ```typescript
40
+ // ✅ Server Component (default) - no directive
41
+ export default async function Page() {
42
+ const data = await fetchData();
43
+ return <ClientComponent data={data} />;
44
+ }
45
+
46
+ // ✅ Client Component - only when needed
47
+ "use client";
48
+ export function Interactive() {
49
+ const [state, setState] = useState(false);
50
+ return <button onClick={() => setState(!state)}>Toggle</button>;
51
+ }
52
+ ```
53
+
54
+ ## When to use "use client"
55
+
56
+ - useState, useEffect, useRef, useContext
57
+ - Event handlers (onClick, onChange)
58
+ - Browser APIs (window, localStorage)
59
+
60
+ ## use() Hook
61
+
62
+ ```typescript
63
+ import { use } from "react";
64
+
65
+ // Read promises (suspends until resolved)
66
+ function Comments({ promise }) {
67
+ const comments = use(promise);
68
+ return comments.map(c => <div key={c.id}>{c.text}</div>);
69
+ }
70
+
71
+ // Conditional context (not possible with useContext!)
72
+ function Theme({ showTheme }) {
73
+ if (showTheme) {
74
+ const theme = use(ThemeContext);
75
+ return <div style={{ color: theme.primary }}>Themed</div>;
76
+ }
77
+ return <div>Plain</div>;
78
+ }
79
+ ```
80
+
81
+ ## Actions & useActionState
82
+
83
+ ```typescript
84
+ "use server";
85
+ async function submitForm(formData: FormData) {
86
+ await saveToDatabase(formData);
87
+ revalidatePath("/");
88
+ }
89
+
90
+ // With pending state
91
+ import { useActionState } from "react";
92
+
93
+ function Form() {
94
+ const [state, action, isPending] = useActionState(submitForm, null);
95
+ return (
96
+ <form action={action}>
97
+ <button disabled={isPending}>
98
+ {isPending ? "Saving..." : "Save"}
99
+ </button>
100
+ </form>
101
+ );
102
+ }
103
+ ```
104
+
105
+ ## ref as Prop (No forwardRef)
106
+
107
+ ```typescript
108
+ // ✅ React 19: ref is just a prop
109
+ function Input({ ref, ...props }) {
110
+ return <input ref={ref} {...props} />;
111
+ }
112
+
113
+ // ❌ Old way (unnecessary now)
114
+ const Input = forwardRef((props, ref) => <input ref={ref} {...props} />);
115
+ ```
116
+
117
+ ## Keywords
118
+ react, react 19, compiler, useMemo, useCallback, server components, use hook
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: react-hook-form
3
+ description: Patrones de React Hook Form en React+TS — register vs Controller, zodResolver, errores por campo, re-renders. Trigger: al crear o tocar formularios con RHF.
4
+ ---
5
+
6
+ # React Hook Form — convenciones
7
+
8
+ ## Cuándo usar este skill
9
+
10
+ Al crear o tocar un formulario con RHF: validación con Zod, submit, errores, o cablear inputs de una lib controlada (Mantine/MUI `Select`, `DatePicker`). RHF es la fuente de verdad del form — no dupliques sus valores en `useState`. Ventaja sobre Formik: los inputs nativos van **uncontrolled** (vía refs), así que teclear no re-renderiza el form entero.
11
+
12
+ ## El patrón
13
+
14
+ Uncontrolled por defecto + Zod como schema + `Controller` **solo** donde el input no emite un evento DOM nativo.
15
+
16
+ ```tsx
17
+ const schema = z.object({ email: z.string().email(), role: z.enum(['coach', 'coachee']) });
18
+ type FormValues = z.infer<typeof schema>;
19
+
20
+ const { register, control, handleSubmit, formState: { errors, isSubmitting } } =
21
+ useForm<FormValues>({ resolver: zodResolver(schema), defaultValues: { email: '', role: 'coachee' } });
22
+
23
+ <TextInput error={errors.email?.message} {...register('email')} /> // nativo → register
24
+ // Select de Mantine (onChange da el valor, no un event) → Controller:
25
+ <Controller control={control} name="role" render={({ field, fieldState }) => (
26
+ <Select data={['coach','coachee']} error={fieldState.error?.message} {...field} />
27
+ )} />
28
+ ```
29
+
30
+ ## Gotchas que muerden
31
+
32
+ - **`register` por defecto; `Controller` es la excepción.** Un input que reenvía `ref` y dispara `onChange` con un evento DOM (texto, textarea, checkbox nativo, `<TextInput>` de Mantine) va con `{...register('campo')}`. Envolverlo en `Controller` re-introduce el re-render por tecla que RHF existe para evitar.
33
+ - **Cuándo SÍ va `Controller`:** componentes cuyo `onChange` entrega el **valor directo** — Mantine `Select`/`MultiSelect`/`NumberInput`/`DateInput`, todo MUI, `react-select`. Cablea `field.value`/`onChange`/`onBlur`/`ref`; el error sale de `fieldState.error?.message`.
34
+ - **`defaultValues` no es opcional.** Sin él, un campo arranca `undefined` → warning "uncontrolled to controlled" (`Controller` con `undefined` es inválido: usa `null`/`''`). Para edición async usa `reset(data)` en un `useEffect`, no valores a mano en cada render.
35
+ - **`watch()` re-renderiza todo.** Para leer en submit usa `getValues('campo')`; para que un hijo dependa de un campo, `useWatch({ control, name })` en ese hijo. `watch()` global en un form grande es anti-patrón.
36
+ - **Números: `register('age', { valueAsNumber: true })`.** Sin esto un `type="number"` entrega **string** y tu `z.number()` falla. Corre antes del resolver, así validas con `z.number()` directo.
37
+ - **`useFieldArray` con `key={field.id}`, nunca el índice** (corrompe el estado al reordenar). Error de servidor con `setError('root.server', …)`, no en un campo.
38
+
39
+ ## Reglas duras
40
+
41
+ 1. Validación en schema Zod vía `zodResolver`; tipo por `z.infer`. Nada de `rules` inline ni tipos paralelos.
42
+ 2. `register` por defecto; `Controller` solo para inputs sin evento DOM nativo.
43
+ 3. `defaultValues` siempre; edición async con `reset(data)`, sin `useState` espejo.
44
+ 4. `getValues`/`useWatch` para leer sin re-render; `isSubmitting` deshabilita el botón.
45
+
46
+ ## Tabla rápida
47
+
48
+ | Input | Cómo cablear |
49
+ |---|---|
50
+ | Texto / textarea / checkbox nativo | `{...register('campo')}` |
51
+ | Número | `register('n', { valueAsNumber: true })` |
52
+ | Select / Date / Number de Mantine/MUI | `<Controller>` + `{...field}` |
53
+ | Lista dinámica | `useFieldArray` + `key={field.id}` |
54
+
55
+ ## Antes de declarar listo
56
+
57
+ - Zod + `zodResolver`, tipo por `z.infer`; `Controller` para inputs controlados, `register` para texto; sin `useState` espejo.
58
+ - `defaultValues` seteado; sin warnings "uncontrolled to controlled". Submit con `handleSubmit` + `isSubmitting`.
59
+ - El quality gate del repo (`qualityGate.fast` en `argos.config.json`) en verde.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: react-router
3
+ description: Patrones de React Router (v6/v7) — rutas anidadas, loaders, navegación, params y guards. Trigger: al crear rutas, leer params, redirigir o proteger vistas.
4
+ ---
5
+
6
+ # React Router — convenciones
7
+
8
+ ## Cuándo usar este skill
9
+
10
+ Al tocar navegación: declarar una ruta, leer un param, redirigir, proteger una vista por rol, o cablear links. React Router es la fuente de verdad de **en qué URL estás y a dónde vas** — no dupliques la ruta en estado propio ni parsees `window.location` a mano.
11
+
12
+ ## El patrón
13
+
14
+ Rutas anidadas con layout compartido vía `<Outlet />`; navegación por hooks, no por mutar `window.location`:
15
+
16
+ ```tsx
17
+ const router = createBrowserRouter([
18
+ {
19
+ path: '/',
20
+ element: <AppLayout />, // renderiza <Outlet /> para los hijos
21
+ children: [
22
+ { index: true, element: <Home /> },
23
+ { path: 'sessions/:id', element: <SessionDetail /> },
24
+ { path: '*', element: <NotFound /> },
25
+ ],
26
+ },
27
+ ]);
28
+
29
+ function SessionDetail() {
30
+ const { id } = useParams(); // string | undefined, siempre
31
+ const navigate = useNavigate();
32
+ const [params, setParams] = useSearchParams();
33
+ // ...
34
+ navigate('/sessions', { replace: true }); // no <a href> manual
35
+ }
36
+ ```
37
+
38
+ ## Gotchas que muerden
39
+
40
+ - **`useParams()` siempre da `string | undefined`.** Nunca `number`. Convierte y valida (`Number(id)`, guard) antes de usarlo como id; una ruta mal tecleada no lanza, solo llega `undefined`.
41
+ - **Navegar imperativo con `useNavigate`, no `window.location`.** `window.location.href = …` recarga toda la SPA y tira el estado. Para volver: `navigate(-1)`; para redirigir sin dejar historial: `{ replace: true }`.
42
+ - **`<NavLink>` para tabs/menús, `<Link>` para el resto.** `NavLink` expone `isActive` en `className`/`style`/children; no reimplementes "está activo" comparando `pathname` a mano.
43
+ - **Search params son la URL, no `useState`.** Filtros/paginación viven en `useSearchParams` para que la vista sea linkeable y sobreviva al refresh. `setParams` reemplaza TODO el query — clona lo actual si solo cambias una clave.
44
+ - **Ruta protegida = un wrapper con `<Navigate>`, no un `if` suelto.** `if (!user) return <Navigate to="/login" replace />;` dentro de un guard/layout. Redirigir desde un `useEffect` parpadea la vista privada un frame.
45
+ - **Rutas relativas anidan; un `/` inicial las hace absolutas.** Dentro de `sessions/:id`, `navigate('edit')` va a `sessions/:id/edit`; `navigate('/edit')` va a la raíz. Es el error #1 al mover un componente de nivel.
46
+
47
+ ## Reglas duras
48
+
49
+ 1. Navegación por `useNavigate`/`<Link>`/`<NavLink>`; nunca `window.location` ni `<a href>` interno.
50
+ 2. `useParams` se valida antes de usar (puede ser `undefined`); ids numéricos se convierten explícito.
51
+ 3. Estado de filtros/paginación en `useSearchParams`, no en `useState` espejo.
52
+ 4. Vistas protegidas por un guard con `<Navigate replace>`, no por `if` + efecto.
53
+ 5. Layouts compartidos con rutas anidadas + `<Outlet />`; nada de repetir el chrome por página.
54
+
55
+ ## Antes de declarar listo
56
+
57
+ - Sin `window.location`/`<a href>` para navegación interna; links con `<Link>`/`<NavLink>`.
58
+ - Params validados; el estado de la URL (filtros, tab) vive en search params.
59
+ - Rutas protegidas redirigen con `<Navigate replace>`; sin parpadeo de la vista privada.
60
+ - El quality gate del repo (`qualityGate.fast` en `argos.config.json`) en verde.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: redux-toolkit
3
+ description: Patrones de Redux Toolkit en React+TS — slices, store tipado, hooks tipados, async thunks, selectores. Trigger: al tocar estado global, slices o el store.
4
+ ---
5
+
6
+ # Redux Toolkit — convenciones
7
+
8
+ ## Cuándo usar este skill
9
+
10
+ Al crear o tocar un slice, el store, async thunks, o leer/escribir estado global. RTK es el estándar — nada de `createStore` pelado, action types a mano, ni `connect`. Estado de servidor (fetch/cache) NO va aquí: eso es TanStack Query. Redux es para estado de cliente compartido (sesión, UI cross-página, carrito).
11
+
12
+ ## El patrón
13
+
14
+ ```ts
15
+ const slice = createSlice({
16
+ name: 'session',
17
+ initialState,
18
+ reducers: {
19
+ setActive(state, action: PayloadAction<Session>) {
20
+ state.active = action.payload; // Immer: "mutas" un draft, no el real
21
+ },
22
+ },
23
+ extraReducers: (b) => {
24
+ b.addCase(loadSession.fulfilled, (s, a) => { s.active = a.payload; });
25
+ },
26
+ });
27
+ export const { setActive } = slice.actions;
28
+ ```
29
+
30
+ Store + hooks tipados una sola vez, y se usan en toda la app:
31
+
32
+ ```ts
33
+ export const useAppDispatch = useDispatch.withTypes<AppDispatch>(); // patrón vigente (RTK 2 / react-redux 9)
34
+ export const useAppSelector = useSelector.withTypes<RootState>(); // no el viejo TypedUseSelectorHook
35
+ ```
36
+
37
+ ## Gotchas que muerden
38
+
39
+ - **Immer solo dentro de `createSlice`.** Ahí "mutas" el draft; fuera de un reducer, mutar el state es un bug. No retornes Y mutes en el mismo reducer.
40
+ - **Selectores memoizados** con `createSelector` cuando derivan/transforman — un selector que crea un array/objeto nuevo en cada llamada re-renderiza siempre.
41
+ - **`useSelector` devuelve la referencia**: selecciona lo mínimo, no el slice entero. Si necesitas varios campos, envuelve con `useShallow(...)` (react-redux 9) para comparar superficial y no re-renderizar de más.
42
+ - **Efectos reactivos → `createListenerMiddleware`**, no un `useEffect` espiando el store ni sagas. Reacciona a una acción/cambio de estado desde el middleware.
43
+ - **Colecciones por id → `createEntityAdapter`**: `selectAll`/`selectById` memoizados gratis, CRUD normalizado, sin arreglos a mano.
44
+ - **Async**: `createAsyncThunk` simple; si es data de API que cacheas/invalidas, evalúa RTK Query. `extraReducers` con builder callback (`(b) => b.addCase(...)`), la forma-objeto se eliminó en RTK 2.
45
+ - **No-serializables** (Date, Map, funciones) fuera del store; rompen devtools y persistencia.
46
+
47
+ ## Reglas duras
48
+
49
+ 1. Estado global solo vía slices de RTK; nada de Context improvisado para lo mismo.
50
+ 2. Hooks `useAppDispatch`/`useAppSelector` tipados, nunca los crudos sin tipo.
51
+ 3. Selecciona lo mínimo y memoiza los derivados con `createSelector`.
52
+ 4. Estado de servidor no vive en Redux — eso es cache de queries.
53
+ 5. Solo valores serializables en el store.
54
+
55
+ ## Antes de declarar listo
56
+
57
+ - El slice nuevo expone acciones tipadas y se consume con los hooks tipados.
58
+ - Los selectores derivados están memoizados; los componentes seleccionan lo mínimo.
59
+ - Nada de data de API duplicada en el store si ya hay capa de queries.
60
+ - El quality gate del repo (`qualityGate.fast` en `argos.config.json`) en verde.
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: review-diff
3
+ description: Checklist de code review por dimensiones agnósticas al stack (tipos, capa de datos, errores, seguridad, hardcode, naming, dead code, quality gate) con severidades CRÍTICO/ALTO/MEDIO. Trigger: revisar un diff staged, una branch contra su rama base, o un PR puntual.
4
+ ---
5
+
6
+ # Code review — checklist de un diff
7
+
8
+ Aplica esta checklist a un diff (staged, branch vs la rama base del repo, o un PR puntual). El esqueleto es agnóstico al stack. Las reglas bespoke de un repo (patrones de su UI lib, convenciones de su capa de datos, anti-patterns propios) no se editan en este skill — viven en la ficha del repo (CLAUDE.md delgado) o en `argos.config.json`, y se leen en runtime.
9
+
10
+ ## Cómo reportar
11
+
12
+ Una línea por hallazgo, ordenadas CRÍTICO → ALTO → MEDIO:
13
+
14
+ ```
15
+ [CRÍTICO] <archivo>:<línea> — <descripción concreta y verificable>
16
+ [ALTO] <archivo>:<línea> — <descripción>
17
+ [MEDIO] <archivo>:<línea> — <descripción>
18
+ ```
19
+
20
+ - **CRÍTICO** — rompe build, corrompe data, agujero de seguridad, contrato que no compila. *Bloquea el merge.*
21
+ - **ALTO** — bug funcional probable, regresión, error no manejado visible al usuario, violación dura de una convención del repo. *Bloquea el merge.*
22
+ - **MEDIO** — legibilidad, naming, doc faltante, hardcode menor, dead code. *No bloquea; se lista.*
23
+
24
+ Si no llega a MEDIO, no lo reportes. Nada de "nitpick" ni "consider also". (Mapea al `reviewer`: CRÍTICO/ALTO = confidence ≥80, bloquean; MEDIO = observación informativa 50-79.)
25
+
26
+ ## 0. Pre-pasada (antes de leer línea por línea)
27
+
28
+ - ¿El diff toca infra/config (`tsconfig*`, config de lint/build, `.env*`, CI, `settings.json`)? Flag → validar que el cambio es intencional.
29
+ - ¿Borra archivos? Verifica que no queden imports residuales (`grep -rn "<archivo>"`).
30
+ - ¿Mezcla cambios no relacionados (feature + refactor + format-only)? → MEDIO, pide separar.
31
+
32
+ ## 1. Tipos y contratos
33
+
34
+ - `any` explícito en código nuevo sin justificación (`// any justificado: <razón>`) → ALTO.
35
+ - Cast (`as Foo`) sin razón documentada → MEDIO; cast que oculta un tipo que en realidad no calza → CRÍTICO.
36
+ - Tipo/interface desactualizado vs lo que el código consume (accede a un campo que el tipo no declara) → CRÍTICO.
37
+ - Datos externos (respuesta de red, input de usuario, env) consumidos sin validar ni normalizar → ALTO.
38
+
39
+ ## 2. Capa de datos / lógica
40
+
41
+ - Defaults explícitos para nullables que el consumidor usa directo (`?? …`) → ALTO si falta.
42
+ - Funciones que deberían ser puras (transformadores/adapters) con side-effects (I/O, estado global) → CRÍTICO.
43
+ - Valor de fuente externa (status/enum desconocido) asignado crudo a un tipo cerrado → ALTO.
44
+
45
+ ## 3. Manejo de errores
46
+
47
+ - `catch` que se traga el error sin propagar ni reportar → ALTO.
48
+ - Operación que puede fallar (red, parse, IO) sin manejo, con el fallo visible al usuario → ALTO.
49
+ - Loading/spinner que nunca se apaga en el path de error → ALTO.
50
+
51
+ ## 4. Seguridad y autorización
52
+
53
+ - Secretos/tokens/credenciales en código (no en config/env) → CRÍTICO.
54
+ - Decisión de autorización solo en el cliente, sin validación del backend → ALTO.
55
+ - Datos sensibles en storage del cliente más allá de lo necesario → ALTO.
56
+
57
+ ## 5. Sin hardcode
58
+
59
+ - URLs de API / endpoints literales en vez del canal de config del repo → CRÍTICO.
60
+ - Strings de estado/rol o listas de opciones duplicadas en vez de derivarlas de una fuente única → MEDIO.
61
+ - Fechas/formatos armados a mano en vez del util del repo → MEDIO.
62
+
63
+ ## 6. Naming y estructura
64
+
65
+ - Archivo en la carpeta equivocada según la convención del repo (componente compartido en `pages/`, etc.) → ALTO.
66
+ - Casing/sufijos que rompen la convención del repo → MEDIO.
67
+ - Convención de migración rota (cuando conviven código nuevo y legacy y hay un sufijo/carpeta esperado) → ALTO.
68
+
69
+ ## 7. Dead code y debug
70
+
71
+ - `console.log` / print de debug sin guard en código que se mergea → MEDIO (en código nuevo: ALTO).
72
+ - Imports o variables sin usar → MEDIO.
73
+ - Código comentado entero / `if (false)` / `// TODO: borrar` sin issue → MEDIO.
74
+
75
+ ## 8. Quality gate (corrido en este turno, no asumido)
76
+
77
+ - El quality gate fast del repo pasa → CRÍTICO si falla. El comando concreto no vive en este skill: resuélvelo leyendo `qualityGate.fast` en el `argos.config.json` del repo o su ficha (CLAUDE.md delgado).
78
+ - Cero errores/warnings nuevos vs baseline → ALTO si el diff los agrega.
79
+
80
+ ## 9. Commit y PR
81
+
82
+ - Commits siguen la convención del repo → MEDIO si rompe.
83
+ - Cambios a manifest/lockfile sin razón clara en la descripción → ALTO.
84
+
85
+ ## Áreas críticas
86
+
87
+ Presta atención extra si el diff toca las áreas críticas que declara el repo (`project.criticalAreas` en su `argos.config.json`, resuelto también en la ficha). Un hallazgo en esas zonas sube un nivel de severidad.
88
+
89
+ ## Output
90
+
91
+ 1. Lista plana con severidades, ordenada CRÍTICO → ALTO → MEDIO. Cada línea con `archivo:línea`.
92
+ 2. Si no hay hallazgos: `Sin observaciones.`
93
+ 3. Nada de resumen, "good job", ni sugerencias fuera del checklist.
94
+ 4. Si encuentras un patrón de bug nuevo que no está aquí, guárdalo (memoria / nota) para próximas reviews.
95
+
96
+ ## Conexión con el harness
97
+
98
+ - `reviewer`: aplica este skill en la Pasada 2 (code quality). CRÍTICO/ALTO mapean a issues con confidence ≥80 (bloquean APPROVED); MEDIO a observaciones informativas (50-79).
99
+ - `verify-before-done`: el quality gate del §8 se corre en este turno, no se asume del informe del implementer.
100
+
101
+ Este skill vive una sola vez en el motor global y aplica a cualquier repo con `argos.config.json`. Las reglas bespoke de un stack/dominio concreto (componentes prohibidos de una UI lib, headers obligatorios de un cliente HTTP, reglas de forms propias, anti-patterns auto-CRÍTICO del repo) no se agregan a este archivo: van en la ficha del repo o en la config, y se leen en runtime al revisar ese repo específico.
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: ship-docs
3
+ description: Generate repo-grounded README.md + DEPLOYMENT.md for a built app. Trigger: README, deployment guide, deploy docs, ship docs, runbook, how to deploy, documentar despliegue, handoff docs.
4
+ ---
5
+
6
+ ## Activation Contract
7
+
8
+ Activate when a built app needs handoff/ship documentation — a README and a deployment runbook — or the user asks for deploy docs. This is the FINAL documentation layer (app-builder's closing phase). Do NOT activate for inline code comments, API reference generation, or a design doc for unbuilt work.
9
+
10
+ ## Hard Rules
11
+
12
+ - Ground EVERYTHING in the real repo. Before writing a line, read: root + workspace `package.json` (name, scripts, deps → real stack), the monorepo layout, `app.json`/`app.config`, migrations dir, `.env.example` / env usage, CI config. Never emit generic boilerplate or invented commands.
13
+ - Every command in the docs MUST exist (a real npm script, a real CLI the repo uses). Verify; if a step needs a tool the repo lacks, say so explicitly, don't fabricate.
14
+ - Two documents, never merged: README (clone → run locally) and DEPLOYMENT.md (ship → production runbook). Mixing buries both.
15
+ - Secrets never appear in docs or git. Reference env vars by name; point to `.env.example`; call out where real secrets live (host dashboard, EAS secrets).
16
+ - Write for a teammate who just cloned and knows nothing. Apply cognitive-doc-design: scannable headers, one concept per section, copy-pasteable ordered steps, prerequisites before actions.
17
+ - DEPLOYMENT.md is a RUNBOOK: ordered, numbered, each step's command + expected result + how to verify. Include rollback and a post-deploy checklist.
18
+
19
+ ## Decision Gates
20
+
21
+ | Repo shape | Deploy sections to include |
22
+ |---|---|
23
+ | Backend (Supabase/DB/API) present | Backend deploy: create project, apply migrations, seed, email/template + auth config, env vars |
24
+ | Web app present | Web deploy: host (Vercel/Netlify/…), build command, env vars, custom domain |
25
+ | Mobile (Expo/RN) present | Mobile: EAS build/submit, store (App Store Connect / Play), TestFlight, required public URLs |
26
+ | Only one of the above | Include only that section; do not template absent stacks |
27
+
28
+ ## Execution Steps
29
+
30
+ 1. Read `references/ship-docs-playbook.md` for the section checklists.
31
+ 2. Harvest repo facts (scripts, layout, stack, migrations, app config, env keys). Derive, don't assume.
32
+ 3. Write `README.md`: one-line what + why; architecture (shared packages / the "brain"); repo layout; prerequisites (versions); local setup as ordered steps (backend up, env, install, run each app); scripts table; testing; troubleshooting for the repo's known gotchas.
33
+ 4. Write `DEPLOYMENT.md`: env-var reference table (name · where used · where the real value lives); then a numbered runbook per present stack (gate table above); post-deploy checklist; rollback.
34
+ 5. Ensure `.env.example` lists every env key the code reads (add missing keys). Never commit real `.env`.
35
+ 6. Verify: every referenced script/command exists; links resolve; no secret literals.
36
+
37
+ ## Output Contract
38
+
39
+ Return: files created (README.md, DEPLOYMENT.md, .env.example changes); which stacks were detected and documented; any command/tool the repo lacks that a deploy step needs (flagged, not faked); repo style guide vs inline fallback used.
40
+
41
+ ## References
42
+
43
+ - `references/ship-docs-playbook.md` — per-stack section checklists (backend / web / mobile), env-table shape, runbook and rollback patterns.
44
+
45
+ _Adapted from a skill originally authored by ricardomarin._
@@ -0,0 +1,31 @@
1
+ # Ship Docs Playbook
2
+
3
+ Section checklists for README.md + DEPLOYMENT.md. Every item is repo-derived — read the files, don't assume.
4
+
5
+ ## README.md skeleton
6
+
7
+ 1. **Title + one-liner** — what the app is and who it's for, one sentence.
8
+ 2. **Architecture** — the shared "brain" (domain/data/token packages), what's platform-specific, why it's structured this way. One paragraph + a layout tree.
9
+ 3. **Repo layout** — `apps/*`, `packages/*`, backend dir, with a one-line purpose each.
10
+ 4. **Prerequisites** — exact versions/tools the repo needs (Node, package manager, Xcode/Android SDK if mobile, backend CLI, Docker if used). Read `engines`, lockfile, config.
11
+ 5. **Local setup — ordered steps**: (a) start the backend/local stack, (b) copy `.env.example` → `.env` per app and where to get values, (c) install, (d) run each app (the real scripts), (e) first-run notes (seed, migrations, test login).
12
+ 6. **Scripts** — a table of the actual root/workspace scripts and what each does.
13
+ 7. **Testing** — how to run the real test targets; what they cover.
14
+ 8. **Troubleshooting** — the repo's KNOWN gotchas (monorepo symlink/postinstall quirks, native-module version pins, cache-clear flags). Pull from the project's own notes.
15
+
16
+ ## DEPLOYMENT.md skeleton (runbook)
17
+
18
+ 1. **Overview** — the deploy targets (backend, web, mobile) and their order of dependency.
19
+ 2. **Environment variables** — a table: `NAME | consumed by (app) | where the real value lives`. Split public (client) vs secret (server/build). Never inline values.
20
+ 3. **Backend** (if present) — create the cloud project; link CLI; push migrations (real command); seed if applicable; auth/email templates & redirect URLs to replicate from local config; obtain prod URL + anon key; note service-role stays server-only.
21
+ 4. **Web** (if present) — host, framework preset, build command + output dir (from the real build script), env vars to set in the host, SPA rewrite/routing config, custom domain, the public URLs the app must expose (e.g. privacy/support).
22
+ 5. **Mobile** (if present) — bundle IDs; EAS setup (`eas build:configure`); EAS secrets for env; `eas build` per platform; `eas submit`; App Store Connect / Play listing needs (privacy URL, support URL — point at the web deploy); TestFlight/internal track for the pilot.
23
+ 6. **Post-deploy checklist** — smoke each surface against prod; verify auth end-to-end; confirm the recovery/email flows work with prod templates; check the public URLs resolve.
24
+ 7. **Rollback** — how to revert each surface (redeploy previous, migration-down caveats, store rollback limits).
25
+
26
+ ## Rules of thumb
27
+
28
+ - If the repo has a local backend config (e.g. `config.toml`, email templates), the deploy doc must say "replicate this in the cloud project" and point at the exact file — otherwise prod silently diverges (e.g. OTP email showing a link instead of a code).
29
+ - Prefer linking a real `.env.example` over listing keys twice.
30
+ - Flag every place a human decision is required (choose host, buy domain, Apple account) as a **[you decide]** callout — don't pretend it's automatic.
31
+ - Keep commands copy-pasteable: one command per line, real flags, expected output noted.