@erclx/canon 5.43.0 → 5.44.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 (133) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/backlog-triage/references/apply.md +6 -6
  3. package/claude/skills/canon-cli/SKILL.md +4 -4
  4. package/claude/skills/canvas-board/REQUIREMENT.md +1 -1
  5. package/claude/skills/canvas-board/SKILL.md +1 -1
  6. package/claude/skills/context-fold/references/context.md +1 -1
  7. package/claude/skills/create-skill/REQUIREMENT.md +1 -1
  8. package/claude/skills/create-skill/SKILL.md +2 -2
  9. package/claude/skills/create-skill/references/skill-requirement.md +68 -9
  10. package/claude/skills/create-skill/references/skill.md +1 -1
  11. package/claude/skills/design-identity/REQUIREMENT.md +40 -0
  12. package/claude/skills/design-identity/SKILL.md +138 -0
  13. package/claude/skills/{draft-identity → design-identity}/references/card-route.md +2 -2
  14. package/claude/skills/design-taste/REQUIREMENT.md +4 -4
  15. package/claude/skills/design-taste/SKILL.md +2 -2
  16. package/claude/skills/design-taste/references/kinds.md +1 -1
  17. package/claude/skills/design-taste/references/preflight.md +1 -1
  18. package/claude/skills/draft-and-pick/REQUIREMENT.md +8 -69
  19. package/claude/skills/draft-and-pick/SKILL.md +3 -153
  20. package/claude/skills/draft-doc/REQUIREMENT.md +9 -30
  21. package/claude/skills/draft-doc/SKILL.md +4 -76
  22. package/claude/skills/draft-figure/REQUIREMENT.md +8 -42
  23. package/claude/skills/draft-figure/SKILL.md +3 -77
  24. package/claude/skills/draft-identity/REQUIREMENT.md +8 -23
  25. package/claude/skills/draft-identity/SKILL.md +3 -130
  26. package/claude/skills/draft-ready/REQUIREMENT.md +8 -37
  27. package/claude/skills/draft-ready/SKILL.md +3 -128
  28. package/claude/skills/draft-screencast/REQUIREMENT.md +8 -23
  29. package/claude/skills/draft-screencast/SKILL.md +3 -62
  30. package/claude/skills/draft-slides/REQUIREMENT.md +8 -27
  31. package/claude/skills/draft-slides/SKILL.md +3 -72
  32. package/claude/skills/draw-figure/REQUIREMENT.md +59 -0
  33. package/claude/skills/draw-figure/SKILL.md +85 -0
  34. package/claude/skills/{draft-figure → draw-figure}/references/architecture-set.md +2 -2
  35. package/claude/skills/{draft-figure → draw-figure}/references/hand-drawn.md +2 -2
  36. package/claude/skills/{draft-figure → draw-figure}/references/mermaid-path.md +2 -2
  37. package/claude/skills/{draft-figure → draw-figure}/references/mermaid.md +1 -1
  38. package/claude/skills/make-deck/REQUIREMENT.md +44 -0
  39. package/claude/skills/make-deck/SKILL.md +80 -0
  40. package/claude/skills/markdown-craft/REQUIREMENT.md +1 -1
  41. package/claude/skills/markdown-craft/SKILL.md +2 -2
  42. package/claude/skills/pick-by-eye/REQUIREMENT.md +86 -0
  43. package/claude/skills/pick-by-eye/SKILL.md +161 -0
  44. package/claude/skills/plan-feature/SKILL.md +2 -1
  45. package/claude/skills/plan-feature/references/plan.md +24 -10
  46. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  47. package/claude/skills/plan-intake/SKILL.md +1 -1
  48. package/claude/skills/plan-ready/REQUIREMENT.md +54 -0
  49. package/claude/skills/plan-ready/SKILL.md +136 -0
  50. package/claude/skills/{draft-ready → plan-ready}/references/assembly.md +1 -1
  51. package/claude/skills/{draft-ready → plan-ready}/references/ready.md +1 -1
  52. package/claude/skills/record-screencast/REQUIREMENT.md +3 -3
  53. package/claude/skills/record-screencast/SKILL.md +2 -2
  54. package/claude/skills/role-orchestrator/REQUIREMENT.md +1 -1
  55. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +5 -2
  56. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -2
  57. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +18 -13
  58. package/claude/skills/role-planner/SKILL.md +2 -1
  59. package/claude/skills/role-worker/SKILL.md +9 -0
  60. package/claude/skills/script-screencast/REQUIREMENT.md +40 -0
  61. package/claude/skills/script-screencast/SKILL.md +70 -0
  62. package/claude/skills/{draft-screencast → script-screencast}/references/beats-template.md +2 -2
  63. package/claude/skills/search-craft/REQUIREMENT.md +4 -4
  64. package/claude/skills/search-craft/SKILL.md +1 -1
  65. package/claude/skills/target-setup/SKILL.md +1 -0
  66. package/claude/skills/task-board/SKILL.md +11 -9
  67. package/claude/skills/task-board/references/board.md +15 -12
  68. package/claude/skills/teach-workspace/SKILL.md +1 -1
  69. package/claude/skills/teach-workspace/references/lesson-craft.md +2 -2
  70. package/claude/skills/ui-checklist/SKILL.md +2 -0
  71. package/claude/skills/write-doc/REQUIREMENT.md +46 -0
  72. package/claude/skills/write-doc/SKILL.md +83 -0
  73. package/claude/skills/{draft-doc → write-doc}/references/context.md +2 -2
  74. package/claude/skills/{draft-doc → write-doc}/references/docs.md +2 -2
  75. package/claude/skills/{draft-doc → write-doc}/references/readme.md +2 -2
  76. package/claude/skills/{draft-doc → write-doc}/references/wiki-kind.md +3 -3
  77. package/docs/agents/markdown-audit.md +4 -2
  78. package/docs/agents/migrate.md +2 -2
  79. package/docs/target/migrations.md +17 -4
  80. package/docs/target/projects.md +1 -1
  81. package/docs/workflow/parallel-features.md +3 -2
  82. package/docs/workflow/skill-map-on-request.md +18 -12
  83. package/docs/workflow/skill-map.md +13 -12
  84. package/docs/workflow/visual-design-workflow.md +2 -2
  85. package/governance/ledger/framework/astro.md +73 -0
  86. package/governance/ledger/framework/fastapi.md +76 -0
  87. package/governance/ledger/framework/nextjs.md +86 -0
  88. package/governance/ledger/framework/react.md +83 -0
  89. package/governance/ledger/framework/shadcn.md +60 -0
  90. package/governance/ledger/framework/tailwind.md +55 -0
  91. package/governance/rules/framework/astro.md +12 -14
  92. package/governance/rules/framework/fastapi.md +20 -24
  93. package/governance/rules/framework/nextjs.md +19 -27
  94. package/governance/rules/framework/react.md +22 -33
  95. package/governance/rules/framework/shadcn.md +11 -15
  96. package/governance/rules/framework/tailwind.md +12 -14
  97. package/governance/rules/writing/markdown.md +1 -1
  98. package/package.json +1 -1
  99. package/src/claude/cases/authoring.ts +15 -3
  100. package/src/claude/cases/misc.ts +12 -0
  101. package/src/claude/cases/workflow.ts +19 -1
  102. package/src/claude/skills-audit.ts +113 -1
  103. package/src/commands/claude.ts +34 -11
  104. package/src/commands/demo.ts +1 -1
  105. package/src/commands/markdown.ts +1 -1
  106. package/src/commands/migrate.ts +4 -0
  107. package/src/commands/pr.ts +30 -6
  108. package/src/commands/tasks.ts +383 -2
  109. package/src/context/audit.ts +1 -1
  110. package/src/demo/beats.ts +1 -1
  111. package/src/gov/audit.ts +3 -2
  112. package/src/markdown/scope.ts +45 -35
  113. package/src/migrate/record-layout.ts +1 -1
  114. package/src/migrate/skill-names.ts +68 -21
  115. package/src/pr/frames.ts +14 -3
  116. package/src/records/validate.ts +31 -0
  117. package/src/tasks/board.ts +854 -0
  118. package/src/tasks/record.ts +20 -1
  119. package/src/tasks/validate.ts +206 -9
  120. package/tooling/astro/configs/card-src/pages/og-card.astro +1 -1
  121. package/tooling/astro/reference.md +2 -2
  122. package/tooling/claude/seeds/.claude/hooks/board-validate.sh +65 -0
  123. package/tooling/claude/seeds/.claude/settings.json +4 -0
  124. /package/claude/skills/{draft-figure → draw-figure}/references/figures.md +0 -0
  125. /package/claude/skills/{draft-slides → make-deck}/references/deck.md +0 -0
  126. /package/claude/skills/{draft-and-pick → pick-by-eye}/references/live-arms.md +0 -0
  127. /package/claude/skills/{draft-doc → write-doc}/references/readme/agent-facing.md +0 -0
  128. /package/claude/skills/{draft-doc → write-doc}/references/readme/application.md +0 -0
  129. /package/claude/skills/{draft-doc → write-doc}/references/readme/cli.md +0 -0
  130. /package/claude/skills/{draft-doc → write-doc}/references/readme/library.md +0 -0
  131. /package/claude/skills/{draft-doc → write-doc}/references/readme/plugin.md +0 -0
  132. /package/claude/skills/{draft-doc → write-doc}/references/requirements.md +0 -0
  133. /package/claude/skills/{draft-doc → write-doc}/references/wiki.md +0 -0
@@ -10,18 +10,24 @@ These skills serve a request rather than a moment. With the [skill map](skill-ma
10
10
 
11
11
  ## Generate an artifact on demand
12
12
 
13
- | Skill | When to use |
14
- | ------------------------- | ------------------------------------------------- |
15
- | `canon:create-rule` | A project rule the toolkit does not ship |
16
- | `canon:create-skill` | A new `SKILL.md` |
17
- | `canon:draft-doc` | A new `docs/` page, context entry, or `README.md` |
18
- | `canon:draft-ready` | Finished files a worker should copy |
19
- | `canon:draft-figure` | A figure or architecture view inside a doc |
20
- | `canon:ci-workflow` | A GitHub Actions workflow file |
21
- | `canon:draft-slides` | A deck rendered to editable PowerPoint |
22
- | `canon:draft-screencast` | A recording script with beats seeded |
23
- | `canon:record-screencast` | Recording a screencast draft into a finished mp4 |
24
- | `canon:draft-identity` | A logo mark and social card |
13
+ | Skill | When to use |
14
+ | ------------------------- | ---------------------------------------------------------------------------------- |
15
+ | `canon:create-rule` | A project rule the toolkit does not ship |
16
+ | `canon:create-skill` | A new `SKILL.md` |
17
+ | `canon:write-doc` | A new `docs/` page, context entry, or `README.md` |
18
+ | `canon:draft-doc` | Never on purpose. A pointer naming `write-doc` <!-- canon-keep-retired --> |
19
+ | `canon:plan-ready` | Finished files a worker should copy |
20
+ | `canon:draft-ready` | Never on purpose. A pointer naming `plan-ready` <!-- canon-keep-retired --> |
21
+ | `canon:draw-figure` | A figure or architecture view inside a doc |
22
+ | `canon:draft-figure` | Never on purpose. A pointer naming `draw-figure` <!-- canon-keep-retired --> |
23
+ | `canon:ci-workflow` | A GitHub Actions workflow file |
24
+ | `canon:make-deck` | A deck rendered to editable PowerPoint |
25
+ | `canon:draft-slides` | Never on purpose. A pointer naming `make-deck` <!-- canon-keep-retired --> |
26
+ | `canon:script-screencast` | A recording script with beats seeded |
27
+ | `canon:draft-screencast` | Never on purpose. A pointer naming `script-screencast` <!-- canon-keep-retired --> |
28
+ | `canon:record-screencast` | Recording a screencast draft into a finished mp4 |
29
+ | `canon:design-identity` | A logo mark and social card |
30
+ | `canon:draft-identity` | Never on purpose. A pointer naming `design-identity` <!-- canon-keep-retired --> |
25
31
 
26
32
  ## Answer a question at any point
27
33
 
@@ -17,18 +17,19 @@ Groups run in the order a project meets them. Every name `canon claude skills li
17
17
 
18
18
  ## Decide what to build
19
19
 
20
- | Skill | When to use |
21
- | -------------------------- | -------------------------------------------------- |
22
- | `canon:plan-intake` | The input is a pile of findings |
23
- | `canon:plan-intake-answer` | An intake folder holds unread slots |
24
- | `canon:backlog-triage` | The backlog needs pruning |
25
- | `canon:plan-groundwork` | The state is unmeasured and approaches compete |
26
- | `canon:decision-escalate` | Open decisions turn on your preference |
27
- | `canon:draft-and-pick` | The call is taste, wanting candidates side by side |
28
- | `canon:canvas-board` | A direction should be drawn as editable frames |
29
- | `canon:task-board` | A decided item needs a file on the board |
30
- | `canon:plan-feature` | The approach is settled and needs a plan |
31
- | `canon:codebase-layout` | A change adds a file and needs a folder |
20
+ | Skill | When to use |
21
+ | -------------------------- | ---------------------------------------------------------------------------- |
22
+ | `canon:plan-intake` | The input is a pile of findings |
23
+ | `canon:plan-intake-answer` | An intake folder holds unread slots |
24
+ | `canon:backlog-triage` | The backlog needs pruning |
25
+ | `canon:plan-groundwork` | The state is unmeasured and approaches compete |
26
+ | `canon:decision-escalate` | Open decisions turn on your preference |
27
+ | `canon:pick-by-eye` | The call is taste, wanting candidates side by side |
28
+ | `canon:draft-and-pick` | Never on purpose. A pointer naming `pick-by-eye` <!-- canon-keep-retired --> |
29
+ | `canon:canvas-board` | A direction should be drawn as editable frames |
30
+ | `canon:task-board` | A decided item needs a file on the board |
31
+ | `canon:plan-feature` | The approach is settled and needs a plan |
32
+ | `canon:codebase-layout` | A change adds a file and needs a folder |
32
33
 
33
34
  ## Build the feature
34
35
 
@@ -19,9 +19,9 @@ The default. `canon/DESIGN.md` holds visual intent as one Overview paragraph, at
19
19
  These skills cover the tier:
20
20
 
21
21
  - `canon:ui-checklist`, `canon:ux-audit`, and `canon:ux-measure` review and measure a UI
22
- - `canon:draft-and-pick` drafts candidates as frames on the canvas and takes your pick
22
+ - `canon:pick-by-eye` drafts candidates as frames on the canvas and takes your pick
23
23
  - `canon:canvas-board` works a direction out as HTML frames you edit in the browser. Only the pick moves into `canon/DESIGN.md`.
24
- - `canon:draft-identity` drafts a logo mark and social card
24
+ - `canon:design-identity` drafts a logo mark and social card
25
25
 
26
26
  Pick tier 0 when the UI is not the core product, decisions fit in sentences, and stakeholders review code.
27
27
 
@@ -0,0 +1,73 @@
1
+ ---
2
+ title: Astro rule ledger
3
+ description: Sources for governance/rules/framework/astro.md, one row per bullet
4
+ ---
5
+
6
+ # Astro rule ledger
7
+
8
+ The field is front-end engineering, and the authority is the Astro documentation at docs.astro.build. The pages read name no current major, so most rows record the read date alone. The content rows follow the Astro 6 upgrade guide, which removed the legacy collection location.
9
+
10
+ ## Static first
11
+
12
+ | Bullet | Source | Read |
13
+ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
14
+ | `.astro` without client state | [Islands architecture](https://docs.astro.build/en/concepts/islands/): Astro components "render to static HTML with no client-side runtime" | 2026-10-18 |
15
+ | Fetch in the frontmatter | [Data fetching](https://docs.astro.build/en/guides/data-fetching/): "All Astro components have access to the global fetch() function in their component script", run "at build time" | 2026-10-18 |
16
+
17
+ ## Islands
18
+
19
+ | Bullet | Source | Read |
20
+ | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
21
+ | Directive on the component | [Template directives](https://docs.astro.build/en/reference/directives-reference/): "A client directive can only be used on a UI framework component that is directly imported into a .astro component" | 2026-10-18 |
22
+ | Pick the directive by priority | [Template directives](https://docs.astro.build/en/reference/directives-reference/): `client:load` is for "Immediately-visible UI elements", `client:idle` for "Lower-priority UI elements", `client:visible` for "below the fold" | 2026-10-18 |
23
+
24
+ ## Routing and layouts
25
+
26
+ | Bullet | Source | Read |
27
+ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
28
+ | `getStaticPaths()` for params | [Routing](https://docs.astro.build/en/guides/routing/): in static mode every parameter value needing a page comes from `getStaticPaths()`, while "In SSR mode, a page will be generated on request" | 2026-10-18 |
29
+ | Layouts with `<slot />` | [Layouts](https://docs.astro.build/en/basics/layouts/): "Layouts are Astro components used to provide a reusable UI structure", with "a slot to specify where individual page content should be injected" | 2026-10-18 |
30
+
31
+ ## Content
32
+
33
+ | Bullet | Source | Read |
34
+ | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
35
+ | `src/content.config.ts` loaders | [Content collections](https://docs.astro.build/en/guides/content-collections/): "All of your build-time content collections are defined in a special src/content.config.ts file", with "two built-in loaders (glob() and file())" | 2026-10-18, Astro 6 |
36
+ | Query through the API | [Content collections](https://docs.astro.build/en/guides/content-collections/): "getCollection() fetches an entire collection and returns an array of entries" | 2026-10-18 |
37
+
38
+ ## Styles and assets
39
+
40
+ | Bullet | Source | Read |
41
+ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
42
+ | Scoped by default | [Styles and CSS](https://docs.astro.build/en/guides/styling/): "Scoped styles should be used as often as possible" and "Global styles should be used only as-needed" | 2026-10-18 |
43
+ | Images in `src/` | [Images](https://docs.astro.build/en/guides/images/): "We recommend that local images are kept in src/ when possible so that Astro can transform, optimize, and bundle them" | 2026-10-18 |
44
+
45
+ ## Environment
46
+
47
+ | Bullet | Source | Read |
48
+ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
49
+ | `astro:env` and `PUBLIC_` | [Environment variables](https://docs.astro.build/en/guides/environment-variables/): "only environment variables prefixed with PUBLIC\_ are available in client-side code", and `astro:env` gives "a type-safe schema" | 2026-10-18 |
50
+
51
+ ## Declined
52
+
53
+ Every bullet the rewrite removed or reshaped, grouped by why.
54
+
55
+ ### Contradicted by the docs
56
+
57
+ - Replaced "content collections in `src/content/` with a `config.ts` schema". The [Astro 6 upgrade guide](https://docs.astro.build/en/guides/upgrade-to/v6/) removed that location in favor of `src/content.config.ts`.
58
+
59
+ ### Cut without a source or a bug class
60
+
61
+ - Cut "do not add a framework integration until the first island needs it" as a dependency call with no page read taking a side.
62
+ - Cut "keep islands leaf-level, never wrap layout chrome to enable nested islands", which no reviewer can check against one line.
63
+ - Cut "use `[param].astro` and `[...rest].astro`" as the file convention Claude already follows. The kept routing bullet names the `getStaticPaths()` footgun instead.
64
+
65
+ ### Merged or reworded
66
+
67
+ - Reworded the hedged "write pages and components as `.astro` unless interactivity requires an island" to a test on client state and event handlers.
68
+ - Reworded the hedged "prefer server-rendered content over client-fetched data" to where the fetch call sits.
69
+ - Reworded "apply `client:*` directives on the component boundary, not on parents" to the rule the directives reference states.
70
+ - Reworded "prefer `client:visible` or `client:idle` over `client:load`" to the priority each directive is documented for.
71
+ - Merged "access collection entries via `getCollection` and `getEntry`" into the query bullet.
72
+ - Reworded "use `is:global` only in layouts" to include `:global()`, the selector the styling page names for the same case.
73
+ - Extended "read environment variables via `import.meta.env`" with `astro:env`, the typed schema the docs now offer.
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: FastAPI rule ledger
3
+ description: Sources for governance/rules/framework/fastapi.md, one row per bullet
4
+ ---
5
+
6
+ # FastAPI rule ledger
7
+
8
+ The field is back-end Python web engineering, and the authority is the FastAPI documentation at fastapi.tiangolo.com. None of the pages read names a FastAPI major, so the rows record the read date alone.
9
+
10
+ ## Routers
11
+
12
+ | Bullet | Source | Read |
13
+ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
14
+ | One `APIRouter` per feature | [Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/): "You can think of APIRouter as a mini FastAPI class", and "With app.include_router() we can add each APIRouter" | 2026-10-18 |
15
+ | Router-level dependencies | [Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/): router `dependencies` "can be used, for example, to require authentication for a whole group of path operations" | 2026-10-18 |
16
+
17
+ ## Path operations
18
+
19
+ | Bullet | Source | Read |
20
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
21
+ | `async def` only when awaited | [Concurrency and async / await](https://fastapi.tiangolo.com/async/): a plain `def` "is run in an external threadpool that is then awaited", and "use async def unless your path operation functions use code that performs blocking I/O" | 2026-10-18 |
22
+ | Response model omits secrets | [Response Model](https://fastapi.tiangolo.com/tutorial/response-model/): FastAPI "will limit and filter the output data to what is defined in the return type" | 2026-10-18 |
23
+ | Body as a Pydantic model | [Request Body](https://fastapi.tiangolo.com/tutorial/body/): "To declare a request body, you use Pydantic models", which validate it and return "a nice and clear error" when it is invalid | 2026-10-18 |
24
+
25
+ ## Dependencies
26
+
27
+ | Bullet | Source | Read |
28
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
29
+ | `Annotated` and type aliases | [Dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/): "Prefer to use the Annotated version if possible", and the value can be stored "in a variable and use it in multiple places" | 2026-10-18 |
30
+ | Session per request via `yield` | [Dependencies with yield](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/): "you could use this to create a database session and close it after finishing" | 2026-10-18 |
31
+ | Overrides in tests | [Testing Dependencies with Overrides](https://fastapi.tiangolo.com/advanced/testing-dependencies/): "your FastAPI application has an attribute app.dependency_overrides" | 2026-10-18 |
32
+
33
+ ## Lifespan and settings
34
+
35
+ | Bullet | Source | Read |
36
+ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
37
+ | `lifespan`, not `on_event` | [Lifespan Events](https://fastapi.tiangolo.com/advanced/events/): "If you provide a lifespan parameter, startup and shutdown event handlers will no longer be called" | 2026-10-18 |
38
+ | Cached `BaseSettings` | [Settings and Environment Variables](https://fastapi.tiangolo.com/advanced/settings/): with `@lru_cache` "the Settings object will be created only once", and a dependency override replaces it during testing | 2026-10-18 |
39
+
40
+ ## Errors
41
+
42
+ | Bullet | Source | Read |
43
+ | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
44
+ | Raise `HTTPException` | [Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/): "To return HTTP responses with errors to the client you use HTTPException" | 2026-10-18 |
45
+ | One exception handler | [Handling Errors](https://fastapi.tiangolo.com/tutorial/handling-errors/): "You could add a custom exception handler with @app.exception_handler()" | 2026-10-18 |
46
+ | Safe summaries only | House choice: an exception message or traceback in a response leaks internals such as SQL, file paths, and library versions to the caller | 2026-10-18 |
47
+
48
+ ## Middleware
49
+
50
+ | Bullet | Source | Read |
51
+ | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
52
+ | Explicit CORS origins | [CORS](https://fastapi.tiangolo.com/tutorial/cors/): "None of allow_origins, allow_methods and allow_headers can be set to ['*'] if allow_credentials is set to True" | 2026-10-18 |
53
+
54
+ ## Declined
55
+
56
+ Every bullet the rewrite removed or reshaped, grouped by why.
57
+
58
+ ### Contradicted by the docs
59
+
60
+ - Reworded "define path operations as `async def` unless purely CPU-bound". The [async page](https://fastapi.tiangolo.com/async/) says "If you just don't know, use normal def", and CPU work in `async def` blocks the loop too.
61
+ - Cut "an `app_factory()` callable over a module-level `app` for testability". Every docs example uses a module-level `app` and tests through `app.dependency_overrides`, which the kept bullet names.
62
+
63
+ ### Cut without a source or a bug class
64
+
65
+ - Cut "group routers by feature under `src/<pkg>/api/`" as a layout call, which the `codebase-layout` skill owns.
66
+ - Cut "annotate path, query, and body parameters, never `**kwargs`", since FastAPI cannot read `**kwargs` and Claude already annotates them.
67
+ - Cut "configure trusted hosts and HTTPS redirects through middleware" as a deployment choice with no page read taking a side.
68
+
69
+ ### Merged or reworded
70
+
71
+ - Merged "mount routes through `APIRouter`, never directly on `FastAPI()`" into the router bullet.
72
+ - Reworded "return pydantic models and set `response_model=`" to name the filter, which is the footgun the [Response Model](https://fastapi.tiangolo.com/tutorial/response-model/) page warns about with passwords.
73
+ - Merged "express shared logic as `Depends(...)` over decorators or globals" into the `Annotated` bullet.
74
+ - Merged "do not perform blocking I/O inside `async def`" into the `async def` bullet.
75
+ - Narrowed "configure CORS through middleware, not per-route checks" to the credentials footgun the CORS page states.
76
+ - Moved "apply `dependencies=[Depends(auth)]` at the router or app level" to the routers section.
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: Next.js rule ledger
3
+ description: Sources for governance/rules/framework/nextjs.md, one row per bullet
4
+ ---
5
+
6
+ # Next.js rule ledger
7
+
8
+ The field is front-end engineering, and the authority is the Next.js documentation at nextjs.org, read against the App Router docs for Next.js 16. The rule loads on every `.ts` and `.tsx` file in a target, so the rewrite cut it from 352 words to under 250.
9
+
10
+ ## Routing
11
+
12
+ | Bullet | Source | Read |
13
+ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
14
+ | App Router, not `pages/` | House choice: a second router in one app splits layouts, data fetching, and caching across two models, so a change made in one never reaches routes in the other | 2026-10-18 |
15
+ | Await `params` | [route.js](https://nextjs.org/docs/app/api-reference/file-conventions/route): "`context.params` is now a promise" since v15, and every page example types `params: Promise<{ id: string }>` | 2026-10-18, Next.js 16 |
16
+
17
+ ## Server and client components
18
+
19
+ | Bullet | Source | Read |
20
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
21
+ | Server by default | [Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components): "By default, layouts and pages are Server Components", with Client Components for state, event handlers, lifecycle logic, and browser-only APIs | 2026-10-18, Next.js 16 |
22
+ | `'use client'` at the leaf | [Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components): "add 'use client' at the top of the files that define your interactive components instead of marking large parts of your UI as Client Components" | 2026-10-18, Next.js 16 |
23
+ | Serializable, minimal props | [Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components): props "need to be serializable", and [Data Security](https://nextjs.org/docs/app/guides/data-security) marks passing a whole row as "EXPOSED" | 2026-10-18, Next.js 16 |
24
+ | `server-only` on secret modules | [Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components): "To prevent accidental usage in Client Components, you can use the server-only package" | 2026-10-18, Next.js 16 |
25
+
26
+ ## Data and caching
27
+
28
+ | Bullet | Source | Read |
29
+ | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
30
+ | `'use cache'` with `cacheLife` | [Fetching Data](https://nextjs.org/docs/app/getting-started/fetching-data): "fetch requests are not cached by default", and [Caching](https://nextjs.org/docs/app/getting-started/caching): "We recommend pairing every cache directive with a cacheLife" | 2026-10-18, Next.js 16 |
31
+ | `<Suspense>` around runtime data | [Caching](https://nextjs.org/docs/app/getting-started/caching): "Components that access runtime APIs should be wrapped in Suspense" | 2026-10-18, Next.js 16 |
32
+ | Revalidate after a mutation | [Mutating Data](https://nextjs.org/docs/app/getting-started/mutating-data): "you can revalidate the Next.js cache and show the updated data by calling revalidatePath or revalidateTag within the Server Function" | 2026-10-18, Next.js 16 |
33
+
34
+ ## Mutations
35
+
36
+ | Bullet | Source | Read |
37
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
38
+ | Verify auth inside the action | [Mutating Data](https://nextjs.org/docs/app/getting-started/mutating-data): "Server Functions are reachable via direct POST requests, not just through your application's UI. Always verify authentication and authorization inside every Server Function." | 2026-10-18, Next.js 16 |
39
+ | Validate input, trim output | [Data Security](https://nextjs.org/docs/app/guides/data-security): "You should always validate input from client", and "Only return what the UI needs, not raw database records" | 2026-10-18, Next.js 16 |
40
+
41
+ ## Built-in primitives
42
+
43
+ | Bullet | Source | Read |
44
+ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
45
+ | `next/link` and `next/image` | [Linking and Navigating](https://nextjs.org/docs/app/getting-started/linking-and-navigating): "Next.js automatically prefetches routes linked with the Link component", and a plain anchor gets "No prefetching" | 2026-10-18, Next.js 16 |
46
+ | Image dimensions or `fill` | [Image Component](https://nextjs.org/docs/app/api-reference/components/image): "If the source image is a dynamic or a remote URL, you must provide the width and height props", and with `fill` "the parent element must be positioned" | 2026-10-18, Next.js 16 |
47
+
48
+ ## Environment
49
+
50
+ | Bullet | Source | Read |
51
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
52
+ | `NEXT_PUBLIC_` only when needed | [Environment Variables](https://nextjs.org/docs/app/guides/environment-variables): Next.js can "inline a value, at build time, into the js bundle that is delivered to the client", and the values are "frozen with the value evaluated at build time" | 2026-10-18, Next.js 16 |
53
+
54
+ ## Declined
55
+
56
+ Every bullet the rewrite removed or reshaped, grouped by why.
57
+
58
+ ### Contradicted by the docs
59
+
60
+ - Replaced "set explicit caching on every `fetch`" with the `'use cache'` bullet. New apps run Cache Components, which [Caching](https://nextjs.org/docs/app/getting-started/caching) drives through the directive.
61
+ - Cut "return `NextResponse` over raw `Response`", since the [route.js](https://nextjs.org/docs/app/api-reference/file-conventions/route) reference returns the Web `Response` throughout.
62
+ - Cut "read params from the function signature, not the request URL" as stale. The signature form holds, and the kept bullet adds the `await` the current major requires.
63
+ - Cut "return no `Response` or stream from a Server Action". No page read forbids it, and the kept bullet states what the docs do say about return values.
64
+
65
+ ### Cut without a source or a bug class
66
+
67
+ - Cut "use route segment files for their documented purpose" as a convention Claude already follows.
68
+ - Cut "place HTTP endpoints in `app/**/route.ts`, never `pages/api/`" as covered by the App Router bullet.
69
+ - Cut "export named HTTP methods" as enforced by the framework, which only routes the named exports.
70
+ - Cut "export `metadata` or `generateMetadata` over manual head tags" as a convention Claude already follows.
71
+
72
+ ### Cut for the word budget
73
+
74
+ A sourced practice cut only because the rule loads on every TypeScript file. A later pass with room can bring it back.
75
+
76
+ - Cut "use `next/font` over manual link tags", which the docs still recommend.
77
+
78
+ ### Merged or reworded
79
+
80
+ - Merged "do not fetch in client components when a server alternative exists" into the server-by-default bullet, since the docs list fetching among a Server Component's uses.
81
+ - Merged "do not introduce `pages/` in new code" into the App Router bullet.
82
+ - Merged "push the boundary as deep as possible" into the leaf bullet.
83
+ - Merged "mark Server Actions with `'use server'`", which the build requires, into the mutation bullets.
84
+ - Reworded "validate Server Action inputs with a Zod schema" to any validation, since [Data Security](https://nextjs.org/docs/app/guides/data-security) names no library.
85
+ - Reworded "use `revalidatePath` or `revalidateTag` over manual refetch loops" to the call the mutation page shows.
86
+ - Merged "never read unprefixed env vars in a client component" into the env bullet, since [Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components) says "If variables are not prefixed, Next.js replaces them with an empty string".
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: React rule ledger
3
+ description: Sources for governance/rules/framework/react.md, one row per bullet
4
+ ---
5
+
6
+ # React rule ledger
7
+
8
+ The field is front-end engineering, and the authority is the React team's documentation at react.dev. The rewrite started from groundwork spike S2's draft and reads its three unread leads.
9
+
10
+ ## Rendering
11
+
12
+ | Bullet | Source | Read |
13
+ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- |
14
+ | Pure during render | [Components and Hooks must be pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure): side effects "should not run in render, as React can render components multiple times" | 2026-10-18, React 19 |
15
+ | Never mutate props or state | [Components and Hooks must be pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure): "A component's props and state are immutable snapshots. Never mutate them directly." | 2026-10-18, React 19 |
16
+ | Stable data keys, not index | [Rendering lists](https://react.dev/learn/rendering-lists): "Index as a key often leads to subtle and confusing bugs" and "do not generate keys on the fly" | 2026-10-18, React 19 |
17
+
18
+ ## State and effects
19
+
20
+ | Bullet | Source | Read |
21
+ | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
22
+ | Derive during render | [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect): "When something can be calculated from the existing props or state, don't put it in state. Instead, calculate it during rendering." | 2026-10-18, React 19 |
23
+ | Reset with `key` | [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect): "To reset the state of an entire component tree, pass a different key to it." | 2026-10-18, React 19 |
24
+ | External store through `useSyncExternalStore` | [useSyncExternalStore](https://react.dev/reference/react/useSyncExternalStore): a browser value "can change without React's knowledge, so you should read it with useSyncExternalStore", and the server snapshot "must be the same between the client and the server" | 2026-10-18, React 19 |
25
+ | Fetching effect in a custom hook | [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect): a race "needs a cleanup function to ignore stale responses", and moving fetching "into a custom Hook will make it easier to adopt an efficient data fetching strategy later" | 2026-10-18, React 19 |
26
+
27
+ ## Memoization
28
+
29
+ | Bullet | Source | Read |
30
+ | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
31
+ | Leave it to the compiler | [React Compiler introduction](https://react.dev/learn/react-compiler/introduction): "For new code, we recommend relying on the compiler for memoization and using useMemo/useCallback where needed to achieve precise control." | 2026-10-18, React Compiler 1 |
32
+ | Without it, memoize only by need | [useMemo](https://react.dev/reference/react/useMemo): worth it for a noticeably slow calculation, "say, 1ms or more", a prop to a `memo` child, or a Hook dependency, and "There is no benefit to wrapping a calculation in useMemo in other cases" | 2026-10-18, React 19 |
33
+
34
+ ## Composition
35
+
36
+ | Bullet | Source | Read |
37
+ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
38
+ | Props, children, then context | [Passing data deeply with context](https://react.dev/learn/passing-data-deeply-with-context): "Start by passing props", then "Extract components and pass JSX as children", and "If neither of these approaches works well for you, consider context" | 2026-10-18, React 19 |
39
+
40
+ ## Error and loading boundaries
41
+
42
+ | Bullet | Source | Read |
43
+ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- |
44
+ | Error boundaries where a message makes sense | [Component](https://react.dev/reference/react/Component): "consider where it makes sense to display an error message", around the conversation list and each message, and "You don't need to wrap every component" | 2026-10-18, React 19 |
45
+ | What activates Suspense | [Suspense](https://react.dev/reference/react/Suspense): "Suspense does not detect when data is fetched inside an Effect or event handler" | 2026-10-18, React 19 |
46
+ | Boundaries follow the loading sequence | [Suspense](https://react.dev/reference/react/Suspense): "Suspense boundaries should not be more granular than the loading sequence that you want the user to experience" | 2026-10-18, React 19 |
47
+
48
+ ## Exports
49
+
50
+ | Bullet | Source | Read |
51
+ | ------------- | -------------------------------------------------------------------------------------------------------- | ---------- |
52
+ | Named exports | House choice: a default export renamed at import drifts from the component's name, so a search misses it | 2026-10-18 |
53
+
54
+ ## Declined
55
+
56
+ Every bullet the rewrite removed or reshaped, grouped by why.
57
+
58
+ ### Contradicted by the docs
59
+
60
+ - Replaced "`useMemo` for derived state over `useEffect`" with the derive bullet. The effect page says "calculate it during rendering" and keeps `useMemo` for a slow calculation.
61
+ - Cut "memoize components receiving non-primitive props" as contradicted. [memo](https://react.dev/reference/react/memo) is "completely useless if the props passed to your component are always different, such as if you pass an object".
62
+ - Cut "memoize every handler passed to a child" as contradicted. [useCallback](https://react.dev/reference/react/useCallback) says "There is no benefit to wrapping a function in useCallback in other cases" than a `memo` child or a Hook dependency.
63
+ - Cut "no passing props past two levels" as contradicted, since the context page says "it's not unusual to pass a dozen props down through a dozen components".
64
+
65
+ ### Cut without a source or a bug class
66
+
67
+ - Cut "domain logic in `src/features/`, shared UI in `src/components/`" as a layout call, which the `codebase-layout` skill owns.
68
+ - Cut "no feature components in the global components folder" as the same layout call.
69
+ - Cut "environment variables only from the validated config module", which is no React practice and which no react.dev page takes a side on.
70
+ - Cut "function declarations over arrow functions" as style with no bug class, and no react.dev page takes a side.
71
+ - Cut "props interface directly above the component" as style with no bug class.
72
+ - Cut "extract components when JSX exceeds one responsibility", which no reviewer can check against a line of code.
73
+ - Cut "compare the previous value and set state during render", since [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect) says "most components shouldn't need it either" and ranks it after a key reset.
74
+ - Cut "use `<>` unless a key is needed" as a convention Claude already follows. [Rendering lists](https://react.dev/learn/rendering-lists) says the shorthand "won't let you pass a key".
75
+
76
+ ### Merged or reworded
77
+
78
+ - Merged "no default exports" into the named-exports bullet, which states the same choice.
79
+ - Narrowed "custom hooks for all fetching and complex effects" to data fetching, since [Reusing logic with custom hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) says "you can (but don't have to) extract custom Hooks".
80
+ - Merged "no `setState` in an effect to sync derived state" into the derive bullet, the same ban. Only the `web` and `nextjs` oxlint configs error on `react/set-state-in-effect`.
81
+ - Reworded "a sentinel from asynchronously hydrating hooks" to `useSyncExternalStore` with a matching server snapshot, the API the reference names for a value React does not own.
82
+ - Reworded "error boundaries at route level", since the reference places a boundary by where a message makes sense rather than at a fixed level.
83
+ - Merged "no single root error boundary as the only net" into the placement bullet.
@@ -0,0 +1,60 @@
1
+ ---
2
+ title: shadcn/ui rule ledger
3
+ description: Sources for governance/rules/framework/shadcn.md, one row per bullet
4
+ ---
5
+
6
+ # shadcn/ui rule ledger
7
+
8
+ The field is front-end engineering, and the authority is the shadcn/ui documentation and changelog at ui.shadcn.com. The rewrite reads the July 2026 changelog, which made Base UI the default primitive library.
9
+
10
+ ## Source files
11
+
12
+ | Bullet | Source | Read |
13
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
14
+ | Edit installed code in place | [Introduction](https://ui.shadcn.com/docs): "This is not a component library. It is how you build your component library", and "Modify any part of a component to fit your design and functionality requirements" | 2026-10-18 |
15
+ | Diff before overwrite | [CLI](https://ui.shadcn.com/docs/cli): `add --overwrite` will "overwrite existing files", and `--diff` will "show diff for a file" | 2026-10-18 |
16
+ | Import through the aliases | [components.json](https://ui.shadcn.com/docs/components-json): "The CLI uses these values to place generated components in the correct location and rewrite imports" | 2026-10-18 |
17
+
18
+ ## Component authoring
19
+
20
+ | Bullet | Source | Read |
21
+ | ------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------- |
22
+ | `ComponentProps` typing | [Tailwind v4](https://ui.shadcn.com/docs/tailwind-v4): "Replace React.forwardRef<...> with React.ComponentProps<...>" | 2026-10-18, React 19 |
23
+ | `data-slot` on primitives | [Tailwind v4](https://ui.shadcn.com/docs/tailwind-v4): "Every primitive now has a data-slot attribute for styling" | 2026-10-18, Tailwind CSS 4 |
24
+
25
+ ## Tokens and styling
26
+
27
+ | Bullet | Source | Read |
28
+ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
29
+ | Semantic tokens | [Theming](https://ui.shadcn.com/docs/theming): "We use semantic background and foreground pairs", mapped "into utilities like bg-background, text-foreground, border-border, and ring-ring" | 2026-10-18 |
30
+ | `cn()` merging | [Manual installation](https://ui.shadcn.com/docs/installation/manual): re-export `cn` "from lib/utils.ts so your own code has a single place to import helpers from" | 2026-10-18 |
31
+
32
+ ## Composition
33
+
34
+ | Bullet | Source | Read |
35
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
36
+ | `render` or `asChild` | [Base UI as the default](https://ui.shadcn.com/docs/changelog/2026-07-base-ui-default): "New projects now use Base UI by default", "Radix is not being deprecated", and "asChild is now render" | 2026-10-18 |
37
+ | `buttonVariants()` for links | [Button](https://ui.shadcn.com/docs/components/button): "The Base UI Button component always applies role="button", which overrides the semantic link role on a elements" | 2026-10-18 |
38
+ | `sonner` for toasts | [Tailwind v4](https://ui.shadcn.com/docs/tailwind-v4): "We're deprecating the toast component in favor of sonner" | 2026-10-18 |
39
+
40
+ ## Declined
41
+
42
+ Every bullet the rewrite removed or reshaped, grouped by why.
43
+
44
+ ### Contradicted by the docs
45
+
46
+ - Replaced "do not edit installed component files, treat them as vendored". The [introduction](https://ui.shadcn.com/docs) says "The top layer of your component code is open for modification".
47
+ - Cut "extend behavior via wrapper components over modifying installed files" for the same reason.
48
+ - Cut "do not override component internals with arbitrary classes, extend via `className` only". Editing the variants in the owned file is what the docs describe.
49
+ - Reworded "use `asChild` with `<Slot>` for polymorphic rendering", since Base UI projects use `render` and the scoped and open searches agreed on that split.
50
+
51
+ ### Cut without a source or a bug class
52
+
53
+ - Cut "compose shadcn primitives as documented", which no reviewer can check against a line of code.
54
+ - Cut "do not destructure or restructure internal component trees" for the same reason.
55
+ - Cut "do not wrap primitives in extra DOM elements" as a style call with no page read taking a side.
56
+
57
+ ### Merged or reworded
58
+
59
+ - Reworded "check `components.json` for the install path" to the aliases bullet, which names what the file controls.
60
+ - Reworded "use `cn()` for all className merging" to the override it guarantees.
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: Tailwind CSS rule ledger
3
+ description: Sources for governance/rules/framework/tailwind.md, one row per bullet
4
+ ---
5
+
6
+ # Tailwind CSS rule ledger
7
+
8
+ The field is front-end engineering, and the authority is the Tailwind CSS documentation at tailwindcss.com, read for Tailwind CSS 4.
9
+
10
+ ## Theme variables
11
+
12
+ | Bullet | Source | Read |
13
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
14
+ | `@theme` or `:root` | [Theme variables](https://tailwindcss.com/docs/theme): "use :root for defining regular CSS variables that shouldn't have corresponding utility classes", and theme variables must be "defined top-level and not nested" | 2026-10-18, Tailwind CSS 4 |
15
+ | Custom dark variant for a class | [Dark mode](https://tailwindcss.com/docs/dark-mode): "By default this uses the prefers-color-scheme CSS media feature", and a selector-driven theme overrides it with `@custom-variant dark` | 2026-10-18, Tailwind CSS 4 |
16
+
17
+ ## Layout and spacing
18
+
19
+ | Bullet | Source | Read |
20
+ | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
21
+ | `flex` or `grid` for flow | House choice: a floated or absolutely positioned element leaves the document flow, so its siblings overlap or collapse once the viewport width changes | 2026-10-18 |
22
+ | `gap-*` over child margins | House choice: a margin on each child leaves a stray edge when the last item wraps or a conditional item is hidden, which `gap` never does | 2026-10-18 |
23
+ | `size-*` for equal sides | [Width](https://tailwindcss.com/docs/width): "Use utilities like size-px, size-4, and size-full to set both the width and height of an element at the same time" | 2026-10-18, Tailwind CSS 4 |
24
+ | Mobile first | [Responsive design](https://tailwindcss.com/docs/responsive-design): "unprefixed utilities take effect on all screen sizes", and "Don't think of sm: as meaning on small screens" | 2026-10-18, Tailwind CSS 4 |
25
+
26
+ ## Class application
27
+
28
+ | Bullet | Source | Read |
29
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------- |
30
+ | Complete class names | [Detecting classes in source files](https://tailwindcss.com/docs/detecting-classes-in-source-files): Tailwind "has no way of understanding string concatenation or interpolation", so "map props to complete class names" | 2026-10-18, Tailwind CSS 4 |
31
+ | No conflicting utilities | [Styling with utility classes](https://tailwindcss.com/docs/styling-with-utility-classes): "you should just never add two conflicting classes to the same element" | 2026-10-18, Tailwind CSS 4 |
32
+ | `!` only as a last resort | [Styling with utility classes](https://tailwindcss.com/docs/styling-with-utility-classes): "When you really need to force a specific utility class to take effect and have no other means of managing the specificity, you can add ! to the end" | 2026-10-18, Tailwind CSS 4 |
33
+ | Arbitrary values for one-offs | [Styling with utility classes](https://tailwindcss.com/docs/styling-with-utility-classes): "When you need to use a one-off value outside of your theme, use the special square bracket syntax" | 2026-10-18, Tailwind CSS 4 |
34
+ | Inline style for dynamic values | [Styling with utility classes](https://tailwindcss.com/docs/styling-with-utility-classes): inline styles are useful "when a value is coming from a dynamic source like a database or API", and for "setting CSS variables" | 2026-10-18, Tailwind CSS 4 |
35
+
36
+ ## Declined
37
+
38
+ Every bullet the rewrite removed or reshaped, grouped by why.
39
+
40
+ ### Contradicted by the docs
41
+
42
+ - Reworded "do not use the `!` important modifier", since the [utility classes](https://tailwindcss.com/docs/styling-with-utility-classes) page documents the trailing `!` for the case nothing else resolves.
43
+
44
+ ### Cut without a source or a bug class
45
+
46
+ - Cut "always pair light and dark utilities explicitly". No page read requires it, and a color token redefined for dark mode switches with no `dark:` pair at all.
47
+ - Cut "define dark mode color overrides in `.dark { }` at root level over `@layer base`", which no Tailwind page read takes a side on.
48
+ - Cut "use `cn()` from `@/lib/utils` for all conditional class application" as the import convention the shadcn rule already owns. The kept conflict bullet names `cn()` for the override case.
49
+
50
+ ### Merged or reworded
51
+
52
+ - Merged "use `flex` and `grid` for all layouts" and "never use floats or absolute positioning for flow" into one bullet naming the bug class.
53
+ - Reworded "use `size-*` over `w-* h-*`" to the matching pair it replaces.
54
+ - Reworded "mobile-first, default styles apply to mobile" to the `sm:` misreading the responsive page warns about.
55
+ - Added "write every class name in full", the footgun the source detection page names and the old rule missed.