@erclx/canon 5.42.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.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/auto-ship/SKILL.md +3 -3
- package/claude/skills/backlog-triage/references/apply.md +6 -6
- package/claude/skills/canon-cli/SKILL.md +4 -4
- package/claude/skills/canvas-board/REQUIREMENT.md +1 -1
- package/claude/skills/canvas-board/SKILL.md +1 -1
- package/claude/skills/ci-workflow/REQUIREMENT.md +2 -1
- package/claude/skills/ci-workflow/SKILL.md +12 -2
- package/claude/skills/ci-workflow/references/workflows.md +12 -9
- package/claude/skills/context-fold/references/context.md +1 -1
- package/claude/skills/create-rule/SKILL.md +1 -0
- package/claude/skills/create-skill/REQUIREMENT.md +1 -1
- package/claude/skills/create-skill/SKILL.md +2 -2
- package/claude/skills/create-skill/references/skill-requirement.md +68 -9
- package/claude/skills/create-skill/references/skill.md +1 -1
- package/claude/skills/decision-escalate/SKILL.md +1 -2
- package/claude/skills/design-identity/REQUIREMENT.md +40 -0
- package/claude/skills/design-identity/SKILL.md +138 -0
- package/claude/skills/{draft-identity → design-identity}/references/card-route.md +2 -2
- package/claude/skills/design-taste/REQUIREMENT.md +4 -4
- package/claude/skills/design-taste/SKILL.md +2 -2
- package/claude/skills/design-taste/references/kinds.md +1 -1
- package/claude/skills/design-taste/references/preflight.md +1 -1
- package/claude/skills/document-health/references/axes.md +2 -1
- package/claude/skills/draft-and-pick/REQUIREMENT.md +8 -69
- package/claude/skills/draft-and-pick/SKILL.md +3 -153
- package/claude/skills/draft-doc/REQUIREMENT.md +9 -30
- package/claude/skills/draft-doc/SKILL.md +4 -76
- package/claude/skills/draft-figure/REQUIREMENT.md +8 -42
- package/claude/skills/draft-figure/SKILL.md +3 -77
- package/claude/skills/draft-identity/REQUIREMENT.md +8 -23
- package/claude/skills/draft-identity/SKILL.md +3 -130
- package/claude/skills/draft-ready/REQUIREMENT.md +8 -37
- package/claude/skills/draft-ready/SKILL.md +3 -128
- package/claude/skills/draft-screencast/REQUIREMENT.md +8 -23
- package/claude/skills/draft-screencast/SKILL.md +3 -62
- package/claude/skills/draft-slides/REQUIREMENT.md +8 -27
- package/claude/skills/draft-slides/SKILL.md +3 -72
- package/claude/skills/draw-figure/REQUIREMENT.md +59 -0
- package/claude/skills/draw-figure/SKILL.md +85 -0
- package/claude/skills/{draft-figure → draw-figure}/references/architecture-set.md +2 -2
- package/claude/skills/{draft-figure → draw-figure}/references/hand-drawn.md +2 -2
- package/claude/skills/{draft-figure → draw-figure}/references/mermaid-path.md +2 -2
- package/claude/skills/{draft-figure → draw-figure}/references/mermaid.md +1 -1
- package/claude/skills/git-commit/references/commit.md +1 -5
- package/claude/skills/git-pr/references/pr.md +1 -0
- package/claude/skills/make-deck/REQUIREMENT.md +44 -0
- package/claude/skills/make-deck/SKILL.md +80 -0
- package/claude/skills/markdown-craft/REQUIREMENT.md +1 -1
- package/claude/skills/markdown-craft/SKILL.md +2 -2
- package/claude/skills/pick-by-eye/REQUIREMENT.md +86 -0
- package/claude/skills/pick-by-eye/SKILL.md +161 -0
- package/claude/skills/plan-feature/SKILL.md +3 -2
- package/claude/skills/plan-feature/references/plan.md +25 -11
- package/claude/skills/plan-groundwork/SKILL.md +1 -1
- package/claude/skills/plan-intake/SKILL.md +1 -1
- package/claude/skills/plan-ready/REQUIREMENT.md +54 -0
- package/claude/skills/plan-ready/SKILL.md +136 -0
- package/claude/skills/{draft-ready → plan-ready}/references/assembly.md +1 -1
- package/claude/skills/{draft-ready → plan-ready}/references/ready.md +1 -1
- package/claude/skills/pr-evidence/references/evidence.md +1 -1
- package/claude/skills/record-screencast/REQUIREMENT.md +3 -3
- package/claude/skills/record-screencast/SKILL.md +2 -2
- package/claude/skills/role-orchestrator/REQUIREMENT.md +1 -1
- package/claude/skills/role-orchestrator/SKILL.md +2 -0
- package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +5 -2
- package/claude/skills/role-orchestrator/references/orchestrator-output.md +4 -0
- package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -2
- package/claude/skills/role-orchestrator/references/orchestrator-refill.md +18 -13
- package/claude/skills/role-planner/REQUIREMENT.md +1 -1
- package/claude/skills/role-planner/SKILL.md +5 -4
- package/claude/skills/role-worker/REQUIREMENT.md +2 -0
- package/claude/skills/role-worker/SKILL.md +35 -2
- package/claude/skills/script-screencast/REQUIREMENT.md +40 -0
- package/claude/skills/script-screencast/SKILL.md +70 -0
- package/claude/skills/{draft-screencast → script-screencast}/references/beats-template.md +2 -2
- package/claude/skills/search-craft/REQUIREMENT.md +4 -4
- package/claude/skills/search-craft/SKILL.md +2 -2
- package/claude/skills/target-setup/SKILL.md +1 -0
- package/claude/skills/task-board/SKILL.md +11 -9
- package/claude/skills/task-board/references/board.md +15 -12
- package/claude/skills/teach-workspace/SKILL.md +1 -1
- package/claude/skills/teach-workspace/references/lesson-craft.md +2 -2
- package/claude/skills/ui-checklist/SKILL.md +2 -0
- package/claude/skills/write-doc/REQUIREMENT.md +46 -0
- package/claude/skills/write-doc/SKILL.md +83 -0
- package/claude/skills/{draft-doc → write-doc}/references/context.md +2 -2
- package/claude/skills/{draft-doc → write-doc}/references/docs.md +2 -2
- package/claude/skills/{draft-doc → write-doc}/references/readme.md +2 -2
- package/claude/skills/{draft-doc → write-doc}/references/wiki-kind.md +4 -4
- package/claude/skills/{draft-doc → write-doc}/references/wiki.md +1 -1
- package/docs/agents/audits.md +1 -0
- package/docs/agents/markdown-audit.md +4 -2
- package/docs/agents/migrate.md +13 -10
- package/docs/target/migrations.md +28 -4
- package/docs/target/projects.md +1 -1
- package/docs/workflow/parallel-features.md +3 -2
- package/docs/workflow/skill-map-on-request.md +18 -12
- package/docs/workflow/skill-map.md +13 -12
- package/docs/workflow/visual-design-workflow.md +2 -2
- package/governance/detect.toml +4 -0
- package/governance/ledger/framework/astro.md +73 -0
- package/governance/ledger/framework/fastapi.md +76 -0
- package/governance/ledger/framework/nextjs.md +86 -0
- package/governance/ledger/framework/react.md +83 -0
- package/governance/ledger/framework/shadcn.md +60 -0
- package/governance/ledger/framework/tailwind.md +55 -0
- package/governance/rules/canon/context.md +2 -1
- package/governance/rules/canon/plan.md +3 -5
- package/governance/rules/canon/scratch.md +3 -1
- package/governance/rules/canon/task-scope.md +2 -1
- package/governance/rules/canon/tasks.md +2 -1
- package/governance/rules/canon/worktrees.md +5 -2
- package/governance/rules/claude/output.md +7 -4
- package/governance/rules/claude/skill.md +6 -4
- package/governance/rules/framework/astro.md +12 -14
- package/governance/rules/framework/fastapi.md +20 -24
- package/governance/rules/framework/nextjs.md +19 -27
- package/governance/rules/framework/react.md +22 -33
- package/governance/rules/framework/shadcn.md +11 -15
- package/governance/rules/framework/tailwind.md +12 -14
- package/governance/rules/tooling/ci-workflow.md +6 -39
- package/governance/rules/ui/design-reference.md +37 -0
- package/governance/rules/writing/markdown.md +3 -2
- package/package.json +6 -6
- package/src/audits/catalog.ts +42 -0
- package/src/claude/cases/authoring.ts +15 -3
- package/src/claude/cases/misc.ts +12 -0
- package/src/claude/cases/workflow.ts +19 -1
- package/src/claude/settings.ts +8 -4
- package/src/claude/skills-audit.ts +113 -1
- package/src/commands/claude.ts +45 -12
- package/src/commands/demo.ts +1 -1
- package/src/commands/gov.ts +198 -0
- package/src/commands/markdown.ts +1 -1
- package/src/commands/migrate.ts +125 -2
- package/src/commands/pr.ts +34 -83
- package/src/commands/tasks.ts +383 -2
- package/src/commands/tooling.ts +3 -3
- package/src/commands/worktrees.ts +49 -0
- package/src/context/audit.ts +1 -1
- package/src/demo/beats.ts +1 -1
- package/src/gate/stages.ts +15 -0
- package/src/gov/audit.ts +441 -0
- package/src/listeners/belongs.ts +21 -0
- package/src/listeners/machine.ts +93 -0
- package/src/listeners/parse.ts +41 -0
- package/src/markdown/scope.ts +45 -35
- package/src/migrate/record-layout.ts +1 -1
- package/src/migrate/session-defaults.ts +138 -0
- package/src/migrate/skill-names.ts +68 -21
- package/src/pr/frames.ts +14 -3
- package/src/pr/local.ts +4 -69
- package/src/records/validate.ts +31 -0
- package/src/sync/check.ts +15 -0
- package/src/tasks/board.ts +854 -0
- package/src/tasks/record.ts +20 -1
- package/src/tasks/validate.ts +206 -9
- package/src/tooling/stamp.ts +56 -12
- package/src/worktrees/stop.ts +92 -0
- package/tooling/astro/configs/card-src/pages/og-card.astro +1 -1
- package/tooling/astro/reference.md +2 -2
- package/tooling/base/configs/.github/workflows/phase-label-gate.yml +6 -2
- package/tooling/base/configs/commitlint.config.js +0 -20
- package/tooling/base/reference.md +1 -1
- package/tooling/base/seeds/.github/workflows/verify.yml +4 -1
- package/tooling/claude/reference.md +13 -7
- package/tooling/claude/seeds/.claude/hooks/board-validate.sh +65 -0
- package/tooling/claude/seeds/.claude/settings.json +8 -0
- package/tooling/claude/user/settings.template.json +0 -4
- package/tooling/cloudflare/configs/.github/workflows/deploy.yml +5 -5
- package/tooling/public/configs/.github/dependabot.yml +12 -0
- package/tooling/public/configs/.github/workflows/release-please.yml +30 -0
- package/tooling/public/manifest.toml +8 -0
- package/tooling/public/reference.md +53 -0
- package/tooling/public/seeds/.github/ISSUE_TEMPLATE/bug.yml +48 -0
- package/tooling/public/seeds/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/tooling/public/seeds/.github/ISSUE_TEMPLATE/feature.yml +16 -0
- package/tooling/public/seeds/.release-please-manifest.json +3 -0
- package/tooling/public/seeds/CONTRIBUTING.md +50 -0
- package/tooling/public/seeds/LICENSE +21 -0
- package/tooling/public/seeds/SECURITY.md +13 -0
- package/tooling/public/seeds/release-please-config.json +12 -0
- package/tooling/shell/configs/.github/workflows/shell.yml +4 -1
- package/tooling/web/configs/.github/workflows/readme-screenshot.yml +6 -3
- package/tooling/web/configs/.github/workflows/verify.yml +15 -12
- /package/claude/skills/{draft-figure → draw-figure}/references/figures.md +0 -0
- /package/claude/skills/{draft-slides → make-deck}/references/deck.md +0 -0
- /package/claude/skills/{draft-and-pick → pick-by-eye}/references/live-arms.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/agent-facing.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/application.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/cli.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/library.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/readme/plugin.md +0 -0
- /package/claude/skills/{draft-doc → write-doc}/references/requirements.md +0 -0
|
@@ -1,43 +1,39 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce FastAPI
|
|
2
|
+
description: Enforce FastAPI routers, sync and async handlers, dependency injection, lifespan, and error mapping
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.py'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# FastAPI standards
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Routers
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- Use an `app_factory()` callable over a module-level `app = FastAPI()` for testability.
|
|
11
|
+
- Declare path operations on one `APIRouter` per feature and add each with `app.include_router()`, not on `FastAPI()` directly.
|
|
12
|
+
- Put a dependency every route in a group needs, such as auth, in the router's `dependencies=[...]`.
|
|
14
13
|
|
|
15
|
-
##
|
|
14
|
+
## Path operations
|
|
16
15
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- Return pydantic models and set `response_model=` on the decorator for serialization control.
|
|
16
|
+
- Declare a path operation `async def` only when every I/O call in it is awaited. Use plain `def` for a blocking library, which FastAPI runs in a threadpool.
|
|
17
|
+
- Declare the return type or `response_model` as a model that omits secrets, since FastAPI filters the output to it.
|
|
18
|
+
- Take a request body as a Pydantic model parameter, never by parsing `await request.json()` by hand.
|
|
21
19
|
|
|
22
|
-
##
|
|
20
|
+
## Dependencies
|
|
23
21
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
22
|
+
- Declare a dependency as `Annotated[T, Depends(fn)]`, and share a repeated one as a type alias.
|
|
23
|
+
- Open a database session in a `yield` dependency and close it after the `yield`, so each request gets its own.
|
|
24
|
+
- Replace a dependency in tests through `app.dependency_overrides`, never by patching the module.
|
|
27
25
|
|
|
28
|
-
## Lifespan and
|
|
26
|
+
## Lifespan and settings
|
|
29
27
|
|
|
30
|
-
-
|
|
31
|
-
- Load settings
|
|
28
|
+
- Run startup and shutdown in a `lifespan` context manager, never `@app.on_event`, which stops running once `lifespan` is set.
|
|
29
|
+
- Load settings through `pydantic_settings.BaseSettings` behind an `@lru_cache` dependency, so `.env` is read once and tests can override it.
|
|
32
30
|
|
|
33
31
|
## Errors
|
|
34
32
|
|
|
35
|
-
- Raise `HTTPException`
|
|
36
|
-
-
|
|
37
|
-
-
|
|
33
|
+
- Raise `HTTPException` with an explicit status code for a client error.
|
|
34
|
+
- Map a domain exception to a response in one `@app.exception_handler`, over a try and except in each route.
|
|
35
|
+
- Return a safe summary from a handler, never the exception's message or traceback.
|
|
38
36
|
|
|
39
|
-
##
|
|
37
|
+
## Middleware
|
|
40
38
|
|
|
41
|
-
-
|
|
42
|
-
- Apply `dependencies=[Depends(auth)]` at the router or app level for cross-cutting auth.
|
|
43
|
-
- Configure CORS, trusted hosts, and HTTPS redirects through middleware, not per-route checks.
|
|
39
|
+
- Configure CORS through `CORSMiddleware`, listing origins explicitly when `allow_credentials=True`, since a wildcard is refused then.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce Next.js App Router
|
|
2
|
+
description: Enforce Next.js App Router boundaries, caching, Server Action security, and built-in primitives
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.tsx'
|
|
5
5
|
- '**/*.ts'
|
|
@@ -7,42 +7,34 @@ paths:
|
|
|
7
7
|
|
|
8
8
|
# Next.js standards
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Routing
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
12
|
+
- Add routes under `app/` with the App Router, never under `pages/`.
|
|
13
|
+
- Await `params` and `searchParams`, which are Promises in a page, a layout, and a route handler.
|
|
14
14
|
|
|
15
15
|
## Server and client components
|
|
16
16
|
|
|
17
|
-
- Default to Server Components. Add `
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
17
|
+
- Default to Server Components. Add `'use client'` only to a file needing state, event handlers, effects, or browser APIs.
|
|
18
|
+
- Put `'use client'` on the interactive leaf, not a layout, since every module it imports joins the client bundle.
|
|
19
|
+
- Pass a Client Component only serializable props holding the fields it renders, never a whole database record.
|
|
20
|
+
- Add `import 'server-only'` to a module that reads secrets or the database.
|
|
21
21
|
|
|
22
|
-
## Data
|
|
22
|
+
## Data and caching
|
|
23
23
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
24
|
+
- Cache with `'use cache'` and a `cacheLife` call where Cache Components is on, the default for new apps. A `fetch` is not cached by default.
|
|
25
|
+
- Wrap a component reading `cookies()`, `headers()`, or uncached data in `<Suspense>` with a fallback.
|
|
26
|
+
- Call `revalidatePath` or `revalidateTag` in the Server Action after a mutation.
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## Mutations
|
|
29
29
|
|
|
30
|
-
-
|
|
31
|
-
- Validate Server Action
|
|
32
|
-
- Return serializable values. Do not return Response or stream objects from a Server Action.
|
|
33
|
-
|
|
34
|
-
## Route handlers
|
|
35
|
-
|
|
36
|
-
- Place HTTP endpoints in `app/**/route.ts`. Do not add `pages/api/`.
|
|
37
|
-
- Export named methods (`GET`, `POST`, ...). Return `NextResponse` over raw `Response` for typed helpers.
|
|
38
|
-
- Read params from the function signature (`{ params }`), not from the request URL.
|
|
30
|
+
- Verify authentication and resource ownership inside every Server Action, since each is reachable by a direct POST.
|
|
31
|
+
- Validate every Server Action argument before use, and return only the fields the UI needs.
|
|
39
32
|
|
|
40
33
|
## Built-in primitives
|
|
41
34
|
|
|
42
|
-
- Use `next/link`
|
|
43
|
-
-
|
|
35
|
+
- Use `next/link` for internal navigation and `next/image` for raster images.
|
|
36
|
+
- Give `next/image` a `width` and `height` for a remote source, or `fill` inside a positioned parent.
|
|
44
37
|
|
|
45
|
-
##
|
|
38
|
+
## Environment
|
|
46
39
|
|
|
47
|
-
-
|
|
48
|
-
- Prefix browser-exposed env vars with `NEXT_PUBLIC_`. Never read unprefixed server-only env vars from a client component.
|
|
40
|
+
- Prefix a variable with `NEXT_PUBLIC_` only when the browser needs it, since its value is inlined at build time.
|
|
@@ -1,51 +1,40 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce
|
|
2
|
+
description: Enforce React render purity, state derivation, memoization, and boundary placement
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.tsx'
|
|
5
5
|
- '**/*.ts'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# React
|
|
8
|
+
# React standards
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Rendering
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
## Project structure
|
|
16
|
-
|
|
17
|
-
- Place domain logic in `src/features/` and restrict `src/components/` to shared UI.
|
|
18
|
-
- Do not place feature-specific components in the global components folder.
|
|
19
|
-
- Import environment variables only from the validated configuration module.
|
|
20
|
-
|
|
21
|
-
## Component patterns
|
|
22
|
-
|
|
23
|
-
- Use function declarations for components over arrow functions.
|
|
24
|
-
- Define TypeScript interfaces for props immediately above the component.
|
|
25
|
-
- Use `<>` shorthand for fragments unless key prop is required.
|
|
26
|
-
- Use stable, unique keys for list items over array index.
|
|
27
|
-
- Extract components when JSX exceeds a single responsibility.
|
|
12
|
+
- Keep components and hooks pure during render. Move side effects and `Math.random()` into an event handler or an effect.
|
|
13
|
+
- Never mutate props or state. Build a new value and pass it to the `useState` setter.
|
|
14
|
+
- Key list items by a stable ID from the data, never by array index or a value generated during render.
|
|
28
15
|
|
|
29
16
|
## State and effects
|
|
30
17
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
- Lift the state to a parent and reset the child with a `key` prop, over running a reset effect in the child.
|
|
36
|
-
- Return a sentinel (`undefined` or a `useSyncExternalStore` placeholder) from hooks that hydrate asynchronously and gate consumers on it, over running a hydration effect.
|
|
18
|
+
- Calculate a value derivable from props or state during render, never in an effect that syncs it into state.
|
|
19
|
+
- Reset a child's state by passing it a new `key`, over a reset effect in the child.
|
|
20
|
+
- Read a browser or external store with `useSyncExternalStore` and a `getServerSnapshot` matching the server output.
|
|
21
|
+
- Wrap a data-fetching effect in a custom hook whose cleanup ignores stale responses, when the framework has no fetching primitive.
|
|
37
22
|
|
|
38
23
|
## Memoization
|
|
39
24
|
|
|
40
|
-
-
|
|
41
|
-
-
|
|
25
|
+
- Leave memoization to React Compiler where it is enabled, as React recommends for new code. Add `useMemo` only for precise control.
|
|
26
|
+
- Without the compiler, memoize only a calculation measured at 1ms or more, or a value a `memo` child or a Hook dependency reads.
|
|
27
|
+
|
|
28
|
+
## Composition
|
|
29
|
+
|
|
30
|
+
- Pass props first, then extract components and pass JSX as `children`. Reach for context only when neither works.
|
|
42
31
|
|
|
43
|
-
##
|
|
32
|
+
## Error and loading boundaries
|
|
44
33
|
|
|
45
|
-
-
|
|
34
|
+
- Place an error boundary where an error message makes sense, such as around a list and each item, never around every component.
|
|
35
|
+
- Expect Suspense to catch `lazy`, `use` on a cached Promise, or a framework loader, never a fetch inside an effect.
|
|
36
|
+
- Place Suspense boundaries to match the loading sequence the user should see.
|
|
46
37
|
|
|
47
|
-
##
|
|
38
|
+
## Exports
|
|
48
39
|
|
|
49
|
-
-
|
|
50
|
-
- Place Suspense at data-fetching boundaries.
|
|
51
|
-
- Do not use a single root-level error boundary as the only safety net.
|
|
40
|
+
- Use named exports for components and hooks, since a default export renamed at import drifts from its name in a search.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce shadcn/ui
|
|
2
|
+
description: Enforce shadcn/ui component ownership, typed primitives, semantic tokens, and composition props
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.tsx'
|
|
5
5
|
- '**/*.jsx'
|
|
@@ -9,26 +9,22 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
## Source files
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
12
|
+
- Edit an installed component in place when the design needs it, since the code is the project's own.
|
|
13
|
+
- Read `shadcn add --diff` before running `--overwrite` on a component, since overwriting discards local edits.
|
|
14
|
+
- Import components and `cn` through the aliases in `components.json`, which the CLI uses to place files and rewrite imports.
|
|
15
15
|
|
|
16
16
|
## Component authoring
|
|
17
17
|
|
|
18
|
-
-
|
|
19
|
-
- Add `data-slot="
|
|
18
|
+
- Type a component's props as `React.ComponentProps<typeof Primitive>`, not `React.forwardRef`.
|
|
19
|
+
- Add `data-slot="<name>"` to the root of a new primitive, matching the installed components.
|
|
20
20
|
|
|
21
21
|
## Tokens and styling
|
|
22
22
|
|
|
23
|
-
- Use semantic
|
|
24
|
-
-
|
|
25
|
-
- Do not override shadcn component internals with arbitrary classes.
|
|
26
|
-
- Extend via `className` prop only.
|
|
23
|
+
- Use semantic tokens such as `bg-background`, `text-foreground`, and `border-border` over hardcoded colors.
|
|
24
|
+
- Merge classes with `cn()` from `@/lib/utils`, so a caller's `className` overrides the component's defaults.
|
|
27
25
|
|
|
28
26
|
## Composition
|
|
29
27
|
|
|
30
|
-
- Compose
|
|
31
|
-
-
|
|
32
|
-
- Use `
|
|
33
|
-
- Do not wrap primitives in extra DOM elements.
|
|
34
|
-
- Use `sonner` for toasts over the deprecated `toast` component.
|
|
28
|
+
- Compose through `render` in a Base UI project, the default for new ones, and through `asChild` in a Radix one.
|
|
29
|
+
- Style a link as a button with `buttonVariants()`, never a Base UI `Button` rendering an `<a>`, which forces `role="button"`.
|
|
30
|
+
- Use `sonner` for toasts, since the `toast` component is deprecated.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Enforce Tailwind CSS v4
|
|
2
|
+
description: Enforce Tailwind CSS v4 theme variables, dark mode, layout spacing, and class application
|
|
3
3
|
paths:
|
|
4
4
|
- '**/*.tsx'
|
|
5
5
|
- '**/*.jsx'
|
|
@@ -11,22 +11,20 @@ paths:
|
|
|
11
11
|
|
|
12
12
|
## Theme variables
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- Define dark mode color overrides in `.dark { }` at root level over `@layer base`.
|
|
17
|
-
- Always pair light and dark utilities explicitly: `bg-white dark:bg-gray-900`.
|
|
14
|
+
- Define a token in a top-level `@theme` block when it needs a utility class, and in `:root` when it does not.
|
|
15
|
+
- Add `@custom-variant dark (&:where(.dark, .dark *))` when a `.dark` class toggles dark mode, since `dark:` follows `prefers-color-scheme` by default.
|
|
18
16
|
|
|
19
17
|
## Layout and spacing
|
|
20
18
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- Use `
|
|
24
|
-
-
|
|
25
|
-
- Mobile-first: default styles apply to mobile. Use `sm:` and up to override.
|
|
19
|
+
- Lay out flow content with `flex` or `grid`, never `float` or `absolute`, which pulls an element out of flow so it overlaps at other widths.
|
|
20
|
+
- Space siblings with `gap-*` on the parent over margins on the children, which leave a stray edge when an item wraps or hides.
|
|
21
|
+
- Use `size-*` over a matching `w-*` and `h-*` pair.
|
|
22
|
+
- Write unprefixed utilities for mobile and add `sm:` and up for wider screens, since `sm:` means that breakpoint and above.
|
|
26
23
|
|
|
27
24
|
## Class application
|
|
28
25
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- Use
|
|
26
|
+
- Write every class name in full, mapping a prop to a complete class, since Tailwind cannot detect a class built by concatenation.
|
|
27
|
+
- Never put two conflicting utilities on one element. Merge a caller's override through `cn()`, which drops the losing class.
|
|
28
|
+
- Add the trailing `!` modifier only when no other way to manage specificity exists.
|
|
29
|
+
- Use an arbitrary value such as `bg-[#316ff6]` for a static one-off, never an inline `style`.
|
|
30
|
+
- Keep inline `style` for a value from a dynamic source, or to set a CSS variable a utility reads.
|
|
@@ -1,55 +1,22 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Keep GitHub Actions commit-back steps and token scopes safe, and route workflow authoring to the ci-workflow skill
|
|
3
3
|
paths:
|
|
4
4
|
- '.github/workflows/**'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# CI workflow standards
|
|
8
8
|
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
- Include `workflow_dispatch` alongside the primary trigger on every workflow.
|
|
12
|
-
- Pin every action to a major version tag. Never `@latest` or `@main`.
|
|
13
|
-
- Run every job on `ubuntu-latest`.
|
|
14
|
-
|
|
15
|
-
## Job naming
|
|
16
|
-
|
|
17
|
-
- Name every job as an emoji followed by a title, such as `🛡️ Checks`, `🧪 Unit Tests`, `📦 Build Check`, `🎭 E2E Tests`, or `🚀 Deploy`.
|
|
18
|
-
|
|
19
|
-
## Job granularity
|
|
20
|
-
|
|
21
|
-
- Fold static analysis, unit tests, and build into one job while the gate runs under two minutes end to end.
|
|
22
|
-
- Split them into parallel jobs once a run log puts the gate past two minutes.
|
|
23
|
-
- Give E2E, release, and deploy a job each from the start.
|
|
24
|
-
|
|
25
|
-
## Job dependencies
|
|
26
|
-
|
|
27
|
-
- Use `needs` for a data dependency, where a job consumes another job's artifact, or for a job whose cost is prohibitive against the gate in front of it. Leave every other job unwired so it runs in parallel.
|
|
28
|
-
- Gate E2E on the job that uploads the build artifact.
|
|
29
|
-
- Gate release and deploy on E2E.
|
|
30
|
-
- Emit a deploy, publish, or release job with a placeholder step and name what the caller fills in. Never guess a deploy command.
|
|
31
|
-
|
|
32
|
-
## Artifacts
|
|
33
|
-
|
|
34
|
-
- Upload an artifact on `if: failure()` alone, with `retention-days: 7`.
|
|
35
|
-
|
|
36
|
-
## Bun stack
|
|
9
|
+
## Authority
|
|
37
10
|
|
|
38
|
-
-
|
|
39
|
-
- Install with `bun install --frozen-lockfile`.
|
|
40
|
-
- Key the Playwright browser cache on the Playwright version string, never a static key.
|
|
11
|
+
- Load the `canon:ci-workflow` skill for triggers, pinning, job shape, artifacts, and the Bun stack. Report it rather than proceeding silently when the skill does not resolve.
|
|
41
12
|
|
|
42
13
|
## Commit-back
|
|
43
14
|
|
|
44
|
-
- Commit a refreshed file back to the pull request branch only when
|
|
15
|
+
- Commit a refreshed file back to the pull request branch only when that branch's change moved it. Report the diff when an outside input can move it, such as a build-time count or a font.
|
|
45
16
|
- Commit only what a deterministic step regenerates from source, and run the diff check before the commit step so an unchanged capture pushes nothing.
|
|
46
17
|
- Skip a pull request from a fork with `github.event.pull_request.head.repo.full_name == github.repository`, since the default token cannot push to a fork's branch.
|
|
47
|
-
- Set the concurrency group on the ref so a newer push cancels the run committing onto a stale head.
|
|
48
|
-
- Set `HUSKY: 0` on the commit step when the runner lacks a tool a hook shells out to.
|
|
49
18
|
- Never commit back to the trunk. A commit with no pull request and no reviewer needs an operator's decision, not a workflow's.
|
|
50
|
-
- Leave `workflow_dispatch` off a commit-back workflow. A manual run has no branch to commit onto, so the trigger would pass and do nothing.
|
|
51
|
-
- Fail a template's first step while a path list still holds its placeholder, so an unfinished install fails loudly rather than never firing.
|
|
52
19
|
|
|
53
|
-
##
|
|
20
|
+
## Token scopes
|
|
54
21
|
|
|
55
|
-
-
|
|
22
|
+
- In a workflow with more than one job, add a write scope to the job that needs it, never to the workflow-level block, so every other job keeps the read-only token.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Build UI against the tracked design references under canon/design, and show each reference beside its build in the pull request
|
|
3
|
+
paths:
|
|
4
|
+
- 'canon/design/**'
|
|
5
|
+
- '**/*.tsx'
|
|
6
|
+
- '**/*.jsx'
|
|
7
|
+
- '**/*.vue'
|
|
8
|
+
- '**/*.svelte'
|
|
9
|
+
- '**/*.astro'
|
|
10
|
+
- '**/*.html'
|
|
11
|
+
- '**/*.css'
|
|
12
|
+
- '**/*.scss'
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Design reference standards
|
|
16
|
+
|
|
17
|
+
## Where the design lives
|
|
18
|
+
|
|
19
|
+
- Build UI against `canon/design/`, never against the canvas directly.
|
|
20
|
+
- Land a picked or changed canvas design in `canon/design/` through the project's design sync, as its own pull request, before any feature builds against it.
|
|
21
|
+
- Never copy, edit, or delete a reference file under `canon/design/` by hand.
|
|
22
|
+
- Add a new surface's row to the index in `canon/design/` before running the sync, and remove it only in the change that removes the surface.
|
|
23
|
+
|
|
24
|
+
## Building against a reference
|
|
25
|
+
|
|
26
|
+
- Open each reference image and its frame HTML, light and dark, before changing the surface they show.
|
|
27
|
+
- Match the reference closely or identically, taking sizes, spacing, and colors from the frame HTML.
|
|
28
|
+
|
|
29
|
+
## Showing the comparison
|
|
30
|
+
|
|
31
|
+
- Put each changed surface's reference image beside its built capture, light and dark, in the pull request description.
|
|
32
|
+
- Name each place the build departs from its reference, with its reason, in the pull request description.
|
|
33
|
+
- Report an unexplained departure from a reference as a review finding.
|
|
34
|
+
|
|
35
|
+
## Naming
|
|
36
|
+
|
|
37
|
+
- Give each app part one plain kebab-case folder under `canon/design/`, and name each file `<name>-dark` or `<name>-light`.
|
|
@@ -9,7 +9,8 @@ paths:
|
|
|
9
9
|
## Format
|
|
10
10
|
|
|
11
11
|
- Never write an em dash or a semicolon. `canon markdown audit` reads the full ban list from the package.
|
|
12
|
-
- Load the `canon:markdown-craft` skill before a substantial markdown edit for headings,
|
|
12
|
+
- Load the `canon:markdown-craft` skill before a substantial markdown edit, for headings, structure, code spans, dates, punctuation, emphasis, file references, spelling, and frontmatter.
|
|
13
|
+
- Report it rather than proceeding silently when `canon:markdown-craft` does not resolve.
|
|
13
14
|
- Run `canon markdown audit <path>` after the edit, and rewrite the sentence carrying a hit rather than swapping the token for a near-synonym.
|
|
14
15
|
|
|
15
16
|
## Voice
|
|
@@ -20,4 +21,4 @@ paths:
|
|
|
20
21
|
|
|
21
22
|
## Figures
|
|
22
23
|
|
|
23
|
-
- Load the `canon:
|
|
24
|
+
- Load the `canon:draw-figure` skill before drafting or revising a Mermaid fence or a figure, and report it rather than proceeding silently when it does not resolve.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erclx/canon",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.44.0",
|
|
5
5
|
"description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"execa": "^9.5.2",
|
|
56
56
|
"highlight.js": "^11.12.0",
|
|
57
57
|
"jszip": "^3.10.1",
|
|
58
|
-
"playwright-core": "1.
|
|
58
|
+
"playwright-core": "1.64.1",
|
|
59
59
|
"pptxgenjs": "^4.0.1",
|
|
60
60
|
"preact": "^11.0.0"
|
|
61
61
|
},
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"@astrojs/react": "^5.0.4",
|
|
65
65
|
"@commitlint/cli": "^20.4.1",
|
|
66
66
|
"@commitlint/config-conventional": "^20.4.1",
|
|
67
|
-
"@playwright/test": "1.
|
|
67
|
+
"@playwright/test": "1.64.1",
|
|
68
68
|
"@tailwindcss/vite": "^4.2.4",
|
|
69
69
|
"@testing-library/jest-dom": "^6.9.1",
|
|
70
70
|
"@types/bun": "^1.2.10",
|
|
@@ -73,11 +73,11 @@
|
|
|
73
73
|
"happy-dom": "^20.14.5",
|
|
74
74
|
"husky": "^9.1.7",
|
|
75
75
|
"micromatch": "^4.0.8",
|
|
76
|
-
"oxfmt": "0.
|
|
77
|
-
"oxlint": "1.
|
|
76
|
+
"oxfmt": "0.73.0",
|
|
77
|
+
"oxlint": "1.88.0",
|
|
78
78
|
"prettier": "^3.8.1",
|
|
79
79
|
"prettier-plugin-astro": "^0.14.1",
|
|
80
|
-
"prettier-plugin-tailwindcss": "^0.
|
|
80
|
+
"prettier-plugin-tailwindcss": "^0.8.1",
|
|
81
81
|
"typescript": "^5.9.3",
|
|
82
82
|
"vitest": "^4.1.5"
|
|
83
83
|
}
|
package/src/audits/catalog.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { ReachRefusal } from '@/claude/skills-reach'
|
|
|
4
4
|
import type { ContextAuditRefusal } from '@/context/audit'
|
|
5
5
|
import type { SweepVerdict } from '@/context/classify/patterns'
|
|
6
6
|
import type { AuditRefusal } from '@/deps/audit'
|
|
7
|
+
import type { RuleAuditRefusal } from '@/gov/audit'
|
|
7
8
|
import type { RestatedRefusal } from '@/gov/restated'
|
|
8
9
|
import type { LabelAuditRefusal } from '@/labels/audit'
|
|
9
10
|
import type { ValidateRefusal as RecordRefusal } from '@/records/validate'
|
|
@@ -412,6 +413,33 @@ function restatedCounts(record: unknown): Record<string, number> | undefined {
|
|
|
412
413
|
})
|
|
413
414
|
}
|
|
414
415
|
|
|
416
|
+
/**
|
|
417
|
+
* Counts rules rather than findings, since a rule past four limits is one
|
|
418
|
+
* rewrite, and keeps the two ledger findings apart because a missing ledger and
|
|
419
|
+
* a short one are fixed by different passes.
|
|
420
|
+
*/
|
|
421
|
+
function ruleCounts(record: unknown): Record<string, number> | undefined {
|
|
422
|
+
const rules = asObject(record)?.rules
|
|
423
|
+
if (!Array.isArray(rules)) return undefined
|
|
424
|
+
|
|
425
|
+
let shapeRules = 0
|
|
426
|
+
let missingLedgers = 0
|
|
427
|
+
let ledgerMismatches = 0
|
|
428
|
+
|
|
429
|
+
for (const raw of rules) {
|
|
430
|
+
const rule = asObject(raw)
|
|
431
|
+
const findings = lengthOf(rule?.findings)
|
|
432
|
+
const ledger = asObject(rule?.ledger)
|
|
433
|
+
if (findings === undefined || ledger === undefined) return undefined
|
|
434
|
+
|
|
435
|
+
if (findings > 0) shapeRules += 1
|
|
436
|
+
if (ledger.status === 'missing') missingLedgers += 1
|
|
437
|
+
if ((lengthOf(ledger.mismatches) ?? 0) > 0) ledgerMismatches += 1
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return { shapeRules, missingLedgers, ledgerMismatches }
|
|
441
|
+
}
|
|
442
|
+
|
|
415
443
|
function findingsOnly(record: unknown): Record<string, number> | undefined {
|
|
416
444
|
const root = asObject(record)
|
|
417
445
|
if (root === undefined) return undefined
|
|
@@ -681,6 +709,20 @@ export const AUDITS: readonly AuditSpec[] = [
|
|
|
681
709
|
] satisfies RestatedRefusal[],
|
|
682
710
|
counts: restatedCounts,
|
|
683
711
|
},
|
|
712
|
+
{
|
|
713
|
+
id: 'rules',
|
|
714
|
+
label: 'Rule shape and ledgers',
|
|
715
|
+
argv: ['gov', 'audit', '--json'],
|
|
716
|
+
// Reports rather than gates. The corpus starts far from zero, and the
|
|
717
|
+
// `rule-shape` stage already fails a push on each folder once its rewrite
|
|
718
|
+
// lists it as gated, so gating the whole set here would fail every push.
|
|
719
|
+
gatingExits: [],
|
|
720
|
+
corpus: 'tracked',
|
|
721
|
+
// A target that authors no rule of its own has no corpus here, which is an
|
|
722
|
+
// absence rather than a break, on the same test the restated sweep takes.
|
|
723
|
+
absentReasons: ['no-rules'] satisfies RuleAuditRefusal[],
|
|
724
|
+
counts: ruleCounts,
|
|
725
|
+
},
|
|
684
726
|
{
|
|
685
727
|
id: 'counts',
|
|
686
728
|
label: 'Self-stated catalog counts',
|
|
@@ -22,26 +22,38 @@ export const AUTHORING_CASES: readonly SkillCase[] = [
|
|
|
22
22
|
{
|
|
23
23
|
prompt:
|
|
24
24
|
'Write a brand-new docs page for the capture command, nothing under docs/ covers it yet.',
|
|
25
|
+
expect: 'write-doc',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
prompt:
|
|
29
|
+
'I typed draft-doc and it said the doc skill was renamed to write-doc.', // canon-keep-retired
|
|
30
|
+
// The pointer answers under its old name on purpose. canon-keep-retired
|
|
25
31
|
expect: 'draft-doc',
|
|
26
32
|
},
|
|
27
33
|
{
|
|
28
34
|
prompt:
|
|
29
35
|
'I already wrote the finished skill files, package them as a ready folder with a plan and a task for a worker to copy.',
|
|
36
|
+
expect: 'plan-ready',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
prompt:
|
|
40
|
+
'I typed draft-ready and it said the ready skill was renamed to plan-ready.', // canon-keep-retired
|
|
41
|
+
// The pointer answers under its old name on purpose. canon-keep-retired
|
|
30
42
|
expect: 'draft-ready',
|
|
31
43
|
},
|
|
32
44
|
{
|
|
33
45
|
prompt: 'This project has no README.md at all, write one from scratch.',
|
|
34
|
-
expect: '
|
|
46
|
+
expect: 'write-doc',
|
|
35
47
|
},
|
|
36
48
|
{
|
|
37
49
|
prompt:
|
|
38
50
|
'Write a context entry for the payments domain, there is no canon/context page for it yet.',
|
|
39
|
-
expect: '
|
|
51
|
+
expect: 'write-doc',
|
|
40
52
|
},
|
|
41
53
|
{
|
|
42
54
|
prompt:
|
|
43
55
|
'Write a wiki reference page for Claude Code output styles, no page covers that subject yet.',
|
|
44
|
-
expect: '
|
|
56
|
+
expect: 'write-doc',
|
|
45
57
|
},
|
|
46
58
|
{
|
|
47
59
|
prompt: 'This passage reads flat and robotic, give it some real cadence.',
|
package/src/claude/cases/misc.ts
CHANGED
|
@@ -10,6 +10,12 @@ export const MISC_CASES: readonly SkillCase[] = [
|
|
|
10
10
|
{
|
|
11
11
|
prompt:
|
|
12
12
|
'Show me a few different treatments for this callout so I can pick one by looking.',
|
|
13
|
+
expect: 'pick-by-eye',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
prompt:
|
|
17
|
+
'I typed draft-and-pick and it said the pick skill was renamed to pick-by-eye.', // canon-keep-retired
|
|
18
|
+
// The pointer answers under its old name on purpose. canon-keep-retired
|
|
13
19
|
expect: 'draft-and-pick',
|
|
14
20
|
},
|
|
15
21
|
{
|
|
@@ -20,6 +26,12 @@ export const MISC_CASES: readonly SkillCase[] = [
|
|
|
20
26
|
{
|
|
21
27
|
prompt:
|
|
22
28
|
'This project has no logo yet. Draft one and give me a social card to go with it.',
|
|
29
|
+
expect: 'design-identity',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
prompt:
|
|
33
|
+
'I typed draft-identity and it said the identity skill was renamed to design-identity.', // canon-keep-retired
|
|
34
|
+
// The pointer answers under its old name on purpose. canon-keep-retired
|
|
23
35
|
expect: 'draft-identity',
|
|
24
36
|
},
|
|
25
37
|
{
|