@ericrisco/rsc 0.1.43 → 0.1.45

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 (97) hide show
  1. package/README.md +1 -1
  2. package/manifest.json +110 -86
  3. package/package.json +1 -1
  4. package/scripts/lib/domains.js +1 -1
  5. package/scripts/skill-migration-brief.md +104 -0
  6. package/skills/ab-testing/SKILL.md +9 -41
  7. package/skills/accessibility/SKILL.md +5 -7
  8. package/skills/ads/SKILL.md +9 -24
  9. package/skills/agent-eval/SKILL.md +7 -33
  10. package/skills/agent-safety/SKILL.md +7 -14
  11. package/skills/ai-media/SKILL.md +4 -20
  12. package/skills/analytics/SKILL.md +8 -30
  13. package/skills/analyze/SKILL.md +24 -59
  14. package/skills/angular/SKILL.md +12 -25
  15. package/skills/api-connector-builder/SKILL.md +10 -27
  16. package/skills/api-design/SKILL.md +7 -14
  17. package/skills/article-writing/SKILL.md +1 -18
  18. package/skills/astro/SKILL.md +36 -54
  19. package/skills/author-skill/SKILL.md +41 -74
  20. package/skills/author-skill/evals/README.md +5 -5
  21. package/skills/author-skill/evals/cases.yaml +8 -8
  22. package/skills/author-skill/references/description-recipe.md +25 -26
  23. package/skills/author-skill/references/eval-authoring.md +1 -1
  24. package/skills/author-skill/references/rsc-conventions.md +1 -1
  25. package/skills/automation-flows/SKILL.md +6 -16
  26. package/skills/automation-strategy/SKILL.md +1 -9
  27. package/skills/aws-essentials/SKILL.md +6 -23
  28. package/skills/backups/SKILL.md +1 -7
  29. package/skills/bash-scripting/SKILL.md +5 -9
  30. package/skills/bookkeeping/SKILL.md +2 -10
  31. package/skills/brand-identity/SKILL.md +18 -44
  32. package/skills/brand-voice/SKILL.md +4 -31
  33. package/skills/building-agents/SKILL.md +20 -103
  34. package/skills/business-intelligence/SKILL.md +9 -23
  35. package/skills/calendar-scheduling/SKILL.md +11 -27
  36. package/skills/case-studies/SKILL.md +3 -8
  37. package/skills/chatbot/SKILL.md +6 -23
  38. package/skills/chrome-extension/SKILL.md +2 -2
  39. package/skills/clarify/SKILL.md +31 -72
  40. package/skills/clickhouse-analytics/SKILL.md +2 -8
  41. package/skills/client-onboarding/SKILL.md +17 -19
  42. package/skills/cloudflare/SKILL.md +3 -8
  43. package/skills/code-review/SKILL.md +10 -23
  44. package/skills/codebase-onboarding/SKILL.md +2 -7
  45. package/skills/cold-outreach/SKILL.md +9 -30
  46. package/skills/community/SKILL.md +4 -31
  47. package/skills/competitor-watch/SKILL.md +20 -35
  48. package/skills/compliance/SKILL.md +10 -37
  49. package/skills/compose-multiplatform/SKILL.md +1 -1
  50. package/skills/constitution/SKILL.md +8 -35
  51. package/skills/content-engine/SKILL.md +4 -16
  52. package/skills/context-budget/SKILL.md +3 -21
  53. package/skills/continuous-learning/SKILL.md +10 -40
  54. package/skills/contracts/SKILL.md +6 -17
  55. package/skills/coolify/SKILL.md +8 -14
  56. package/skills/cost-tracking/SKILL.md +3 -11
  57. package/skills/course-builder/SKILL.md +17 -45
  58. package/skills/course-storytelling/SKILL.md +26 -94
  59. package/skills/cpp/SKILL.md +26 -71
  60. package/skills/csharp-dotnet/SKILL.md +19 -38
  61. package/skills/customer-support/SKILL.md +14 -37
  62. package/skills/dashboard/SKILL.md +6 -26
  63. package/skills/data-cleaning/SKILL.md +37 -63
  64. package/skills/data-policy/SKILL.md +8 -21
  65. package/skills/data-scraper/SKILL.md +1 -7
  66. package/skills/debug/SKILL.md +10 -49
  67. package/skills/deployment/SKILL.md +38 -101
  68. package/skills/design/SKILL.md +34 -116
  69. package/skills/fable-operator/SKILL.md +1 -4
  70. package/skills/fastapi/SKILL.md +50 -82
  71. package/skills/flutter/SKILL.md +41 -89
  72. package/skills/go/SKILL.md +57 -105
  73. package/skills/harness/SKILL.md +52 -68
  74. package/skills/implement/SKILL.md +1 -1
  75. package/skills/init/SKILL.md +152 -168
  76. package/skills/marketing/SKILL.md +30 -80
  77. package/skills/nextjs/SKILL.md +42 -116
  78. package/skills/orient/SKILL.md +25 -20
  79. package/skills/parallel/SKILL.md +9 -75
  80. package/skills/plan/SKILL.md +92 -165
  81. package/skills/postgresdb/SKILL.md +52 -72
  82. package/skills/presentations/SKILL.md +49 -87
  83. package/skills/python/SKILL.md +23 -72
  84. package/skills/react/SKILL.md +19 -67
  85. package/skills/review/SKILL.md +22 -52
  86. package/skills/rust/SKILL.md +40 -115
  87. package/skills/sdd-init/SKILL.md +9 -14
  88. package/skills/secure-coding/SKILL.md +80 -109
  89. package/skills/ship/SKILL.md +25 -55
  90. package/skills/tasks/SKILL.md +37 -61
  91. package/skills/typescript/SKILL.md +22 -55
  92. package/skills/verify/SKILL.md +8 -32
  93. package/skills/viral-score/SKILL.md +122 -0
  94. package/skills/viral-score/evals/README.md +16 -0
  95. package/skills/viral-score/evals/cases.yaml +50 -0
  96. package/skills/vue-nuxt/SKILL.md +45 -106
  97. package/skills/worktrees/SKILL.md +24 -69
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: fastapi
3
- description: "Use when building, reviewing, testing, securing or deploying a FastAPI / async Python service. Triggers: creating endpoints/routers, Pydantic v2 models (Create/Update/Response), dependency injection, async SQLAlchemy 2.0 + Alembic, OAuth2/JWT auth + RBAC, pytest + httpx ASGITransport tests, CORS / rate limiting / secret handling, uvicorn/gunicorn + structured logging + healthchecks + graceful shutdown, pyproject + ruff + mypy strict + uv. Any .py file importing fastapi, pydantic, sqlalchemy, starlette, or a pyproject.toml declaring those."
3
+ description: "Use when building, reviewing, testing, securing or shipping a FastAPI / async Python service — routers, Pydantic v2 schemas, dependency injection, async SQLAlchemy 2.0, OAuth2/JWT, ASGITransport tests, production wiring. NOT language-level Python or packaging (that is `python`), NOT engine-level SQL (that is `postgresdb`), NOT framework-agnostic REST contracts (that is `api-design`)."
4
4
  tags: [python, api, async, backend, rest]
5
5
  recommends: [postgresdb, secure-coding, deployment]
6
6
  origin: risco
@@ -20,25 +20,16 @@ pytest 8 + pytest-asyncio 1.0+ (`asyncio_mode=auto`), ruff 0.7+, mypy 1.13+ stri
20
20
  uv 0.5+, uvicorn 0.32+ / gunicorn 23+ + uvicorn-worker 0.3+, PyJWT 2.10+, argon2-cffi 23+,
21
21
  pip-audit 2.7+, PostgreSQL 16. (All lower bounds; install the latest in each line.)
22
22
 
23
- ## When to use
24
-
25
23
  > **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
26
24
 
27
- - Writing or reviewing any FastAPI route, router, dependency, schema, or app factory.
28
- - Designing async DB access (SQLAlchemy 2.0), migrations (Alembic), or eager-loading.
29
- - Adding auth (OAuth2 password flow + JWT), RBAC, password hashing.
30
- - Writing pytest suites for an async API (ASGITransport, `dependency_overrides`, transactional DB).
31
- - Hardening (CORS, rate limit, secrets, log redaction, dependency audit) or productionizing.
32
- - Setting up `pyproject.toml`, ruff + mypy strict, uv/pip-tools dependency management.
33
-
34
- ## When NOT to use
35
-
36
- - Django / Flask / DRF apps → not this skill.
37
- - Sync WSGI services, data-science notebooks, CLI-only scripts with no HTTP surface.
38
- - Pure REST contract questions (status codes, URL naming, versioning, cursor vs offset) → general REST-design territory (this skill covers the FastAPI *implementation* of those contracts).
39
- - Frontend/Next.js, Go, Flutter work → their own skills.
40
- - Generic secure-coding rules not specific to Python/FastAPI → **See Also `secure-coding`**.
41
- - Container/Compose/CI deploy mechanics → **See Also `deployment`** (this skill keeps only a Docker *note*).
25
+ Out of scope, and where it goes instead: [`django`](../django/SKILL.md) for Django; Flask / sync WSGI,
26
+ notebooks and CLI-only scripts (no skill); language-level Python, typing and packaging →
27
+ [`python`](../python/SKILL.md); framework-agnostic REST contracts — status codes, URL naming, versioning,
28
+ cursor vs offset → [`api-design`](../api-design/SKILL.md) (this skill covers their FastAPI *implementation*);
29
+ engine-level schema, indexing, EXPLAIN, zero-downtime migrations, PgBouncer →
30
+ [`postgresdb`](../postgresdb/SKILL.md); language-agnostic injection / secret / authz theory →
31
+ [`secure-coding`](../secure-coding/SKILL.md); Dockerfile, Compose and CI/CD mechanics →
32
+ [`deployment`](../deployment/SKILL.md) (this skill keeps only a Docker *note*).
42
33
 
43
34
  ## Decision rules
44
35
 
@@ -140,11 +131,11 @@ app = create_app()
140
131
  Accepting an optional `settings` argument lets tests build the app with overridden config
141
132
  without touching the `get_settings` cache. **Bad** = `allow_origins=["*"]` with
142
133
  `allow_credentials=True` — browsers reject it and Starlette refuses to echo `*` for
143
- credentialed requests. `→ references/production.md` for proxy headers / logging wiring at
134
+ credentialed requests. → [`references/production.md`](references/production.md) for proxy headers / logging wiring at
144
135
  startup.
145
136
 
146
137
  To inject servers / security schemes / a logo into the generated OpenAPI doc, assign a
147
- custom builder to `app.openapi` inside `create_app()`. `→ references/production.md`
138
+ custom builder to `app.openapi` inside `create_app()`. → [`references/production.md`](references/production.md)
148
139
  (Customizing the OpenAPI schema).
149
140
 
150
141
  ## Configuration (pydantic-settings)
@@ -229,7 +220,7 @@ v2 migration cheats: use `.model_dump()` not `.dict()`; `.model_validate(obj)` n
229
220
  `field_validator`/`model_validator` not `@validator`/`@root_validator`.
230
221
 
231
222
  **Bad** = a response model with `hashed_password: str` (leaks the hash). **Good** = the
232
- `UserResponse` above (no secret fields). `→ references/security.md`.
223
+ `UserResponse` above (no secret fields). → [`references/security.md`](references/security.md).
233
224
 
234
225
  ## Dependency injection
235
226
 
@@ -275,7 +266,7 @@ def get_pagination(
275
266
  PageParams = Annotated[Pagination, Depends(get_pagination)]
276
267
  ```
277
268
 
278
- `→ references/database.md` for `async_session_factory` wiring; `→ references/security.md`
269
+ → [`references/database.md`](references/database.md) for `async_session_factory` wiring; → [`references/security.md`](references/security.md)
279
270
  for `get_current_user` and `require_roles`.
280
271
 
281
272
  ## Routers & endpoints
@@ -361,8 +352,9 @@ def register_exception_handlers(app: FastAPI) -> None:
361
352
  Keep this envelope identical across every handler — one `code`/`message`/`details` shape so
362
353
  clients parse errors once. Subclass `AppError` per failure (each fixes a `code` + status):
363
354
  `NotFoundError` (404), `ConflictError` (409), `Unauthorized` (401), `Forbidden` (403) — full
364
- hierarchy in `→ references/production.md` (AppError subclasses). **See Also `secure-coding`**
365
- for why error responses must never leak internals (stack traces, SQL, secrets).
355
+ hierarchy in → [`references/production.md`](references/production.md) (AppError subclasses).
356
+ [`secure-coding`](../secure-coding/SKILL.md) has the why: error responses must never leak internals
357
+ (stack traces, SQL, secrets).
366
358
 
367
359
  ## Async SQLAlchemy 2.0 (essentials)
368
360
 
@@ -401,7 +393,9 @@ async def list_users(db: AsyncSession, limit: int, offset: int) -> list[User]:
401
393
  return list(result.scalars().all())
402
394
  ```
403
395
 
404
- `→ references/database.md` for relationships, N+1 / eager loading, repository, Alembic, pooling.
396
+ Fetch by PK with `await db.get(Model, pk)`, by unique key with `.scalar_one_or_none()`; eager-load with
397
+ `selectinload` (collections) / `joinedload` (many-to-one).
398
+ → [`references/database.md`](references/database.md) for relationships, N+1 / eager loading, repository, Alembic, pooling.
405
399
 
406
400
  ## Background tasks vs real queues
407
401
 
@@ -428,74 +422,48 @@ a transactional fixture — so every test rolls back. Use `pytest-asyncio` with
428
422
  `asyncio_mode = "auto"` (no `@pytest.mark.asyncio`), and assert secrets never serialize (e.g.
429
423
  `assert "hashed_password" not in resp.json()`). TDD red→green→refactor. Full fixtures
430
424
  (transactional `begin_nested`, auth overrides, respx, coverage gate) in
431
- `→ references/testing.md`.
425
+ → [`references/testing.md`](references/testing.md).
432
426
 
433
427
  ## Security
434
428
 
435
429
  Full hardening playbook — argon2 hashing, OAuth2 + JWT (claims validated, `algorithms`
436
430
  pinned), `get_current_user`/`require_roles` RBAC, CORS, shared-store rate limiting, injection,
437
431
  `SecretStr` + log redaction, security headers, `pip-audit` — lives in
438
- `→ references/security.md`. The non-negotiables also appear in the anti-patterns table below.
439
- **See Also `secure-coding`** for the language-agnostic theory.
432
+ → [`references/security.md`](references/security.md) — including the exact `argon2.PasswordHasher().hash(pw)` and
433
+ `jwt.decode(t, key, algorithms=[...], audience=..., issuer=...)` calls. See
434
+ [`secure-coding`](../secure-coding/SKILL.md) for the language-agnostic theory.
440
435
 
441
436
  ## Production
442
437
 
443
438
  ASGI/worker math, structured JSON logging + request-id, liveness vs readiness probes, graceful
444
439
  shutdown, keyset pagination, caching, `ORJSONResponse` and proxy headers all live in
445
- `→ references/production.md`. **See Also `deployment`** for the Dockerfile and CI/CD pipeline.
440
+ → [`references/production.md`](references/production.md). See [`deployment`](../deployment/SKILL.md) for the
441
+ Dockerfile and CI/CD pipeline.
446
442
 
447
- ## Anti-patterns / rationalizations → STOP
443
+ ## Anti-patterns
448
444
 
449
- | Rationalization | Reality → STOP |
450
- |---|---|
451
- | "I'll just call `requests` in this async route, it's one call" | Blocks the event loop → use `httpx.AsyncClient`. |
452
- | "`.dict()` still works" | Pydantic v2: use `.model_dump()`; `.dict()`/`from_orm` are deprecated. |
453
- | "Return the ORM object directly, FastAPI will handle it" | Leaks columns + lazy-loads in serializer → declare `response_model`. |
454
- | "`allow_origins=['*']` + credentials is fine for now" | Browser rejects it; Starlette blocks it. Pin origins. |
455
- | "I'll decode the JWT without checking `exp`/`aud`" | Forged/replayed tokens. Validate exp/iss/aud + pin alg. |
456
- | "Build the WHERE with an f-string, it's internal" | SQLi. Bound params / SQLAlchemy expressions only. |
457
- | "One global session for the whole app is simpler" | Cross-request data bleed + concurrency bugs. One session per request. |
458
- | "Catch `Exception` and return the message to the client" | Leaks internals. Log it, return generic 500. |
459
- | "`BackgroundTasks` is good enough for the payment webhook retry" | No durability/retry. Use a real broker. |
460
- | "mypy strict is too noisy, I'll skip it" | Strict catches the bugs FastAPI's runtime won't. Keep it. |
461
- | "Commit inside the handler so I control it" | Let `get_db` own commit/rollback; handlers stay thin. |
462
- | "Default-mutable arg / module-level engine at import is fine" | Mutable defaults bite; engine must live in lifespan. |
463
-
464
- ## Quick reference
465
-
466
- | Task | Idiom |
445
+ | Anti-pattern | Why it breaks → do this |
467
446
  |---|---|
468
- | Async route doing I/O | `async def` + `httpx.AsyncClient` / asyncpg |
469
- | Request DB session | `db: Annotated[AsyncSession, Depends(get_db)]` |
470
- | Run a query / get rows | `await db.execute(select(Model)...)` → `result.scalars().all()` / `.scalar_one_or_none()` |
471
- | Get by PK | `await db.get(Model, pk)` |
472
- | Eager-load | `selectinload(Model.items)` (collection) / `joinedload(Model.parent)` (many-to-one) |
473
- | Settings | `Annotated[Settings, Depends(get_settings)]` |
474
- | Serialize ORM → schema | `model_config = ConfigDict(from_attributes=True)` |
475
- | Created response | `status_code=201` + `Location` header |
476
- | Test client | `AsyncClient(transport=ASGITransport(app=app))` + `app.dependency_overrides[dep] = fake` |
477
- | Hash password / verify JWT | `argon2.PasswordHasher().hash(pw)` / `jwt.decode(t, key, algorithms=[...], audience=..., issuer=...)` |
478
-
479
- ## Project grounding (02-DOCS + CLAUDE.md)
480
-
481
- When this skill runs in a project with a `02-DOCS/` layer (the
482
- [`harness`](../harness/SKILL.md) Karpathy wiki), record this project's API decisions in
483
- `02-DOCS/wiki/stack/fastapi.md` and index it in `02-DOCS/wiki/index.md` (the Knowledge map index; root
484
- `CLAUDE.md` points to it), so the next agent inherits the conventions instead of re-deriving them.
485
-
486
- - **Read it first** on every use and stay consistent; bump its `Updated` date when a
487
- convention changes.
488
- - **Create/update it** with the project's real choices — auth model (JWT/OAuth2 provider,
489
- token TTLs), DB session + migration tool, error-envelope shape, settings/secrets approach,
490
- deployment target — indexing it in `02-DOCS/wiki/index.md` (the Knowledge map; root `CLAUDE.md` keeps only a short pointer to it) if absent.
491
-
492
- No `02-DOCS/` layer? Skip silently (optionally suggest `harness`). Technical conventions are
493
- *recorded, not gated* — never block the task on this.
494
-
495
- ## See Also
496
-
497
- - [`secure-coding`](../secure-coding/SKILL.md) — language-agnostic injection / secret / authz hardening behind this skill's security rules.
498
- - [`postgresdb`](../postgresdb/SKILL.md) — engine-level schema design, indexing, EXPLAIN, zero-downtime migrations, PgBouncer (below the SQLAlchemy layer this skill drives).
499
- - [`deployment`](../deployment/SKILL.md) — Dockerfile, Compose, CI/CD, container runtime (this skill keeps only a Docker note).
500
- - References: [`references/testing.md`](references/testing.md), [`references/database.md`](references/database.md), [`references/security.md`](references/security.md), [`references/production.md`](references/production.md).
501
- - Verify gate: [`scripts/verify.sh`](scripts/verify.sh).
447
+ | `requests` (or any blocking call) inside an `async def` route | Blocks the event loop → use `httpx.AsyncClient`. |
448
+ | `.dict()` / `from_orm()` on a model | Pydantic v2: use `.model_dump()`; `.dict()`/`from_orm` are deprecated. |
449
+ | Returning the ORM object with no `response_model` | Leaks columns + lazy-loads in serializer → declare `response_model`. |
450
+ | `allow_origins=['*']` together with credentials | Browser rejects it; Starlette blocks it. Pin origins. |
451
+ | Decoding a JWT without checking `exp`/`aud` | Forged/replayed tokens. Validate exp/iss/aud + pin alg. |
452
+ | Building the WHERE clause with an f-string | SQLi. Bound params / SQLAlchemy expressions only. |
453
+ | One global session shared by the whole app | Cross-request data bleed + concurrency bugs. One session per request. |
454
+ | Catching `Exception` and returning its message | Leaks internals. Log it, return generic 500. |
455
+ | `BackgroundTasks` for a payment-webhook retry | No durability/retry. Use a real broker. |
456
+ | Skipping `mypy --strict` because it is noisy | Strict catches the bugs FastAPI's runtime won't. Keep it. |
457
+ | Committing inside the handler | Let `get_db` own commit/rollback; handlers stay thin. |
458
+ | Default-mutable arg / engine built at import time | Mutable defaults bite; engine must live in lifespan. |
459
+
460
+ ## Project grounding
461
+
462
+ In a project with a `02-DOCS/` layer ([`harness`](../harness/SKILL.md)), read
463
+ `02-DOCS/wiki/stack/fastapi.md` first and stay consistent with it; create or update it with this
464
+ project's real choices — auth model (JWT/OAuth2 provider, token TTLs), DB session + migration tool,
465
+ error-envelope shape, settings/secrets approach, deployment target — bump its `Updated` date, and index
466
+ it in `02-DOCS/wiki/index.md`. No `02-DOCS/`? Skip silently. Conventions are *recorded, not gated* —
467
+ never block the task on this.
468
+
469
+ Verify gate: [`scripts/verify.sh`](scripts/verify.sh).
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: flutter
3
- description: "Use when building, structuring, testing or optimizing a Flutter app (Dart 3, Riverpod 3 / Bloc, go_router, Material 3, freezed, widget & golden tests). Triggers: creating a Flutter feature, choosing state management, wiring navigation/auth guards, modeling async/error state, JSON/dio data layer, killing widget rebuilds/jank, or writing widget/golden/integration tests. Stack: Flutter 3.44 / Dart 3.12."
3
+ description: "Use when building, structuring, testing or optimizing a Flutter app — feature-first layering, Riverpod 3 or Bloc, typed go_router, freezed models, a dio data layer, Material 3, jank hunting, widget/golden tests. Targets Flutter 3.44 / Dart 3.12. NOT React Native (that is `react-native`), NOT Compose Multiplatform (that is `compose-multiplatform`)."
4
4
  tags: [flutter, dart, mobile, app, ios, android]
5
5
  recommends: [design, deployment]
6
6
  origin: risco
@@ -8,35 +8,28 @@ origin: risco
8
8
 
9
9
  # Flutter & Dart app architecture
10
10
 
11
- ## What this skill is
11
+ The opinionated default stack for a production Flutter app: **feature-first + layered** folders,
12
+ **Riverpod 3** with codegen for shared/async state, a **typed go_router**, **freezed** immutable
13
+ models, a **dio** data layer, and explicit `Result<T, Failure>` error modeling — all on **Material 3**.
14
+ Escape hatches are first-class: **Bloc/Cubit** instead of Riverpod when the team already runs Bloc,
15
+ and raw `http`/`get_it` are allowed — but **pick one of each per app, never mix two**. Pinned versions
16
+ this skill targets: **Flutter 3.44 / Dart 3.12**, **Riverpod 3.0**, **go_router 17.2.x**
17
+ (+ `go_router_builder 4.3.x`), **freezed 3.x** / `json_serializable`, **dio 5.x**, **mocktail 1.x**.
12
18
 
13
- The opinionated default stack for a production Flutter app: **feature-first + layered**
14
- folders, **Riverpod 3** with codegen for shared/async state, a **typed go_router**, **freezed**
15
- immutable models, a **dio** data layer, and explicit `Result<T, Failure>` error modeling — all on
16
- **Material 3**. Escape hatches exist and are first-class: use **Bloc/Cubit** instead of Riverpod when
17
- the team already runs Bloc, and raw `http`/`get_it` are allowed — but **pick one of each per app, never
18
- mix two**. Pinned versions this skill targets: **Flutter 3.44 / Dart 3.12**, **Riverpod 3.0**,
19
- **go_router 17.2.x** (+ `go_router_builder 4.3.x`), **freezed 3.x** / `json_serializable`, **dio 5.x**,
20
- **mocktail 1.x**. When you load this skill inside the user's repo, it touches only the `pubspec.yaml`
21
- subproject — never the FastAPI/Go/Next.js siblings.
22
-
23
- ## When to use / When NOT to use
19
+ ## Boundaries
24
20
 
25
21
  > **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
26
22
 
27
- **Use when:**
28
-
29
- - Building a new Flutter feature or screen, or choosing/refactoring state management.
30
- - Setting up routing, DI, theming, or the data layer; reviewing Dart for null-safety, sealed/pattern
31
- matching, immutability, async-gap discipline, or rebuild hygiene.
32
- - Investigating performance/jank, wiring build flavors, or scaffolding unit/widget/golden/integration tests.
23
+ This skill owns the `pubspec.yaml` subproject and nothing else in the repo. Hand off when the UI is
24
+ Compose Multiplatform (`compose-multiplatform`), SwiftUI/native iOS (`swift-ios`) or React Native
25
+ (`react-native`); when the work is on a FastAPI/Go/Next.js sibling in the same monorepo (use that
26
+ skill). For a pure Dart **server/CLI** with no widget tree, general Dart applies but skip the
27
+ UI/nav/perf references. For a single-file throwaway sample, say architecture is overkill and do not
28
+ impose layering.
33
29
 
34
- **Do NOT use when:**
35
-
36
- - The UI is Compose Multiplatform, native Android-Kotlin, or SwiftUI — use the Compose/native skill.
37
- - It is a pure Dart **server/CLI** with no widget tree — general Dart applies, but skip the UI/nav/perf references.
38
- - The work is on a FastAPI/Go/Next.js sibling in the same monorepo — use that skill; this one only owns the Flutter subproject.
39
- - It is a single-file throwaway sample — note that architecture is overkill, do not impose layering.
30
+ Around the edges: `harness` owns the workspace `01-TOOLS`/`02-DOCS` layer and flavor secrets; `fastapi`,
31
+ `go` and `nextjs` build the backends this app talks to; `secure-coding` reviews token handling and
32
+ deep-link validation; `deployment` handles store/CI release; `design` owns the Material 3 token system.
40
33
 
41
34
  ## Decision rules
42
35
 
@@ -379,70 +372,29 @@ encapsulation → `references/i18n-and-dependencies.md`.
379
372
  - Dependency hygiene: `pubspec.lock` committed for apps, `flutter pub outdated` audited on a cadence,
380
373
  dependencies vetted by pub points before adding.
381
374
  - No `print()` → `dart:developer` `log()`.
375
+ - Gate the branch with `scripts/verify.sh`, run inside the Flutter project (format / codegen / analyze / tests).
382
376
 
383
- ## Anti-patterns → STOP
377
+ ## Anti-patterns
384
378
 
385
- | Rationalization | Reality |
379
+ | Anti-pattern | Why it fails / do instead |
386
380
  |---|---|
387
- | "I'll just `user!` here" | bang crashes in prod; use `?.`/`??` or an if-case pattern. |
388
- | "`_buildHeader()` is fine" | extract to a `const` widget class — enables element reuse + const propagation. |
389
- | "`bool isLoading` + `bool isError` is simpler" | allows impossible states; use `AsyncValue`/sealed. |
390
- | "I'll `setState` at the top of the page" | rebuilds the whole subtree; scope it or `.select()`. |
391
- | "global provider for this checkbox" | ephemeral UI state = local `setState`/`ValueNotifier`. |
392
- | "mix `Navigator.push` with go_router for one screen" | one router; mixing breaks deep links + back stack. |
393
- | "use `context` after `await`, it's fine" | guard `context.mounted` / `ref.mounted`; stale context crashes. |
394
- | "hardcode `Colors.blue` just here" | use `colorScheme`; breaks dark mode + theming. |
395
- | "`ListView(children: [...])` for the feed" | use `.builder`; the concrete form builds all children eagerly. |
396
- | "`catch (e)` everything" | use `on`-typed clauses; never catch `Error` (it is a bug). |
397
- | "ship raw `DioException.toString()` to the user" | map to a `Failure` with a localized message. |
398
- | "`print()` for logging" | use `dart:developer` `log()` — has levels and can be filtered. |
399
- | "use legacy `StateProvider`" | Riverpod 3 `Notifier`; legacy is `package:riverpod/legacy.dart` only. |
400
- | "`pumpAndSettle` will fix the flaky test" | hangs on infinite animations; use explicit `pump(Duration)`. |
401
-
402
- ## Quick reference
403
-
404
- | Concern | Default API | Reference |
405
- |---|---|---|
406
- | model | `@freezed` | `references/architecture-and-state.md` |
407
- | sync state | `Notifier` / `Cubit` | `references/architecture-and-state.md` |
408
- | async state | `AsyncNotifier` / `AsyncValue` | `references/architecture-and-state.md` |
409
- | DI | `@riverpod` providers / `get_it` | `references/architecture-and-state.md` |
410
- | routing | typed `go_router` | `references/ui-and-navigation.md` |
411
- | errors | `Result` / sealed | `references/architecture-and-state.md` |
412
- | http | `dio` + interceptor | `references/architecture-and-state.md` |
413
- | long list | `ListView.builder` | `references/performance.md` |
414
- | off-thread | `Isolate.run` | `references/performance.md` |
415
- | unit test | `ProviderContainer.test()` | `references/testing.md` |
416
- | widget test | `ProviderScope` override | `references/testing.md` |
417
- | golden | `matchesGoldenFile` | `references/testing.md` |
418
- | l10n | ARB + `gen_l10n` + `intl` | `references/i18n-and-dependencies.md` |
419
- | deps | `flutter pub outdated` / `melos` | `references/i18n-and-dependencies.md` |
420
- | verify | `scripts/verify.sh` | `scripts/verify.sh` |
421
-
422
- ## Project grounding (02-DOCS + CLAUDE.md)
423
-
424
- When this skill runs in a project with a `02-DOCS/` layer (the
425
- [`harness`](../harness/SKILL.md) Karpathy wiki), record this
426
- project's app decisions there and index them in `02-DOCS/wiki/index.md`, so the next
427
- agent inherits the conventions instead of re-deriving them.
428
-
429
- 1. **Find the article** `02-DOCS/wiki/stack/flutter.md`, indexed in `02-DOCS/wiki/index.md` (the Knowledge map index; root `CLAUDE.md` points to it).
430
- 2. **If missing or stale**, create/update it with the project's real choices — the state-management choice (Riverpod/Bloc), the architecture layers, routing, the Material 3 token system, and codegen setup —
431
- then index it in `02-DOCS/wiki/index.md` (the Knowledge map; root `CLAUDE.md` keeps only a short pointer to it).
432
- 3. **Read it first on every use** and stay consistent; when a convention changes, update the
433
- article (bump its `Updated` date) in the same change.
434
-
435
- No `02-DOCS/` layer? Skip silently (optionally suggest `harness`). Unlike the
436
- brand study, technical conventions are *recorded, not gated* — never block the task on this.
437
-
438
- ## See Also
439
-
440
- - `references/architecture-and-state.md` — layering, DI, Result/Failure, Riverpod 3 & Bloc deep dives.
441
- - `references/ui-and-navigation.md` — widgets, Material 3 tokens, responsive, typed go_router, a11y.
442
- - `references/testing.md` — unit/widget/golden/integration + coverage.
443
- - `references/performance.md` — rebuilds, paint, jank, isolates, build flavors.
444
- - `references/i18n-and-dependencies.md` — ARB/ICU l10n, RTL, locale-aware formatting, pub points, `melos`.
445
- - `scripts/verify.sh` — run inside your Flutter project to gate format/codegen/analyze/tests.
446
- - Sibling skills: `harness` (workspace `01-TOOLS`/`02-DOCS`, flavor secrets); `fastapi`,
447
- `go` and `nextjs` for the backends this app talks to; `secure-coding` for token handling and deep-link
448
- validation; `deployment` for store/CI release; `design` for the Material 3 token system.
381
+ | `user!` to unwrap | bang crashes in prod; use `?.`/`??` or an if-case pattern. |
382
+ | `_buildHeader()` helper methods | extract to a `const` widget class — enables element reuse + const propagation. |
383
+ | `setState` at the top of the page | rebuilds the whole subtree; scope it or `.select()`. |
384
+ | `Navigator.push` mixed into go_router for one screen | one router; mixing breaks deep links + back stack. |
385
+ | `context` used after an `await` | guard `context.mounted` / `ref.mounted`; a stale context crashes. |
386
+ | hardcoded `Colors.blue` | use `colorScheme`; hardcoding breaks dark mode + theming. |
387
+ | `ListView(children: [...])` for a feed | use `.builder`; the concrete form builds all children eagerly. |
388
+ | `catch (e)` on everything | use `on`-typed clauses; never catch `Error` (it is a bug). |
389
+ | raw `DioException.toString()` shown to the user | map to a `Failure` with a localized message. |
390
+ | `print()` for logging | use `dart:developer` `log()` — has levels and can be filtered. |
391
+
392
+ ## Project grounding (02-DOCS)
393
+
394
+ In a project with a `02-DOCS/` layer (the [`harness`](../harness/SKILL.md) wiki), this app's decisions
395
+ live in `02-DOCS/wiki/stack/flutter.md`, indexed in `02-DOCS/wiki/index.md`. Read it first and stay
396
+ consistent. Missing or stale? Write the real choices there — state management (Riverpod/Bloc), the
397
+ architecture layers, routing, the Material 3 token system, codegen setup — index it, and bump its
398
+ `Updated` date in the same change a convention changes, so the next agent inherits it instead of
399
+ re-deriving it. No `02-DOCS/` layer? Skip silently: technical conventions are *recorded, not gated*,
400
+ so never block the task on this.