@jeiemgi/cckit 0.1.6

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 (191) hide show
  1. package/.claude-plugin/plugin.json +22 -0
  2. package/AGENTS.md +101 -0
  3. package/LICENSE-APACHE +202 -0
  4. package/LICENSE-MIT +21 -0
  5. package/README.md +143 -0
  6. package/SECURITY.md +22 -0
  7. package/bin/cckit +215 -0
  8. package/cckit.config.json +34 -0
  9. package/commands/kit-add.md +42 -0
  10. package/commands/kit-docs.md +45 -0
  11. package/commands/kit-doctor.md +52 -0
  12. package/commands/kit-export-project.md +58 -0
  13. package/commands/kit-export-training.md +49 -0
  14. package/commands/kit-init.md +126 -0
  15. package/commands/kit-routines.md +59 -0
  16. package/commands/kit-update.md +132 -0
  17. package/docs/kit-annotate/01-explainer.html +225 -0
  18. package/docs/kit-annotate/02-implementation-plan.html +196 -0
  19. package/docs/media/.onboarding-capture.cast +5 -0
  20. package/docs/media/README.md +43 -0
  21. package/docs/media/build-demo.sh +63 -0
  22. package/docs/media/build-kit-init.sh +51 -0
  23. package/docs/media/build-onboarding.sh +51 -0
  24. package/docs/media/kit-dry-run.cast +107 -0
  25. package/docs/media/kit-dry-run.gif +0 -0
  26. package/docs/media/kit-init.cast +56 -0
  27. package/docs/media/kit-init.gif +0 -0
  28. package/docs/media/kit-onboarding.cast +148 -0
  29. package/docs/media/kit-onboarding.gif +0 -0
  30. package/githooks/pre-commit +18 -0
  31. package/kit.config.schema.json +105 -0
  32. package/package.json +54 -0
  33. package/privacy-denylist.example +8 -0
  34. package/profiles/automation.json +36 -0
  35. package/profiles/content.json +41 -0
  36. package/profiles/minimal.json +31 -0
  37. package/profiles/research.json +37 -0
  38. package/profiles/software.json +32 -0
  39. package/scripts/annotate-setup.sh +149 -0
  40. package/scripts/autopilot.sh +50 -0
  41. package/scripts/capture-project-ids.sh +53 -0
  42. package/scripts/check.sh +66 -0
  43. package/scripts/contribute.sh +48 -0
  44. package/scripts/debug.sh +54 -0
  45. package/scripts/init-upgrade-test.sh +99 -0
  46. package/scripts/init.sh +827 -0
  47. package/scripts/install.sh +24 -0
  48. package/scripts/kit-add-test.sh +62 -0
  49. package/scripts/kit-add.sh +115 -0
  50. package/scripts/kit-adopt-test.sh +61 -0
  51. package/scripts/kit-adopt.sh +122 -0
  52. package/scripts/kit-bump-version.sh +79 -0
  53. package/scripts/kit-digest.sh +126 -0
  54. package/scripts/kit-doctor.sh +663 -0
  55. package/scripts/kit-export-project-test.sh +82 -0
  56. package/scripts/kit-export-project.sh +245 -0
  57. package/scripts/kit-export-training-test.sh +51 -0
  58. package/scripts/kit-export-training.sh +175 -0
  59. package/scripts/kit-migrate-test.sh +80 -0
  60. package/scripts/kit-migrate.sh +190 -0
  61. package/scripts/kit-onboard-test.sh +63 -0
  62. package/scripts/kit-onboard.sh +69 -0
  63. package/scripts/kit-promote-test.sh +54 -0
  64. package/scripts/kit-promote.sh +102 -0
  65. package/scripts/kit-remove-test.sh +61 -0
  66. package/scripts/kit-remove.sh +84 -0
  67. package/scripts/kit-routines.sh +322 -0
  68. package/scripts/kit-version-check.sh +91 -0
  69. package/scripts/kit-wire-test.sh +54 -0
  70. package/scripts/kit-wire.sh +132 -0
  71. package/scripts/knowledge-lint.sh +96 -0
  72. package/scripts/lib/cckit-output.sh +36 -0
  73. package/scripts/lib/effort-metrics.sh +452 -0
  74. package/scripts/lib/effort-ops-test.sh +83 -0
  75. package/scripts/lib/effort-ops.sh +132 -0
  76. package/scripts/lib/effort-plan.sh +104 -0
  77. package/scripts/lib/effort.sh +191 -0
  78. package/scripts/lib/engine-adapter.sh +92 -0
  79. package/scripts/lib/gh-log.sh +58 -0
  80. package/scripts/lib/gh-project.sh +212 -0
  81. package/scripts/lib/handoff.sh +35 -0
  82. package/scripts/lib/kit-cli-test.sh +42 -0
  83. package/scripts/lib/kit-cli.sh +32 -0
  84. package/scripts/lib/kit-config-resolve.sh +145 -0
  85. package/scripts/lib/kit-config.sh +88 -0
  86. package/scripts/lib/kit-engine-test.sh +107 -0
  87. package/scripts/lib/kit-events.sh +62 -0
  88. package/scripts/lib/kit-gc.sh +117 -0
  89. package/scripts/lib/kit-interview-test.sh +77 -0
  90. package/scripts/lib/kit-interview.sh +203 -0
  91. package/scripts/lib/kit-local.sh +79 -0
  92. package/scripts/lib/kit-manifest.sh +127 -0
  93. package/scripts/lib/kit-mode-test.sh +49 -0
  94. package/scripts/lib/kit-mode.sh +67 -0
  95. package/scripts/lib/kit-operate.sh +105 -0
  96. package/scripts/lib/kit-profile-test.sh +62 -0
  97. package/scripts/lib/kit-profile.sh +115 -0
  98. package/scripts/lib/kit-task-ops-test.sh +63 -0
  99. package/scripts/lib/kit-task-ops.sh +341 -0
  100. package/scripts/lib/pr-evidence.sh +173 -0
  101. package/scripts/lib/project-scan.sh +16 -0
  102. package/scripts/lib/react-detect.sh +78 -0
  103. package/scripts/lib/role-identity.sh +47 -0
  104. package/scripts/lib/secret-guard.sh +96 -0
  105. package/scripts/lib/toon.sh +35 -0
  106. package/scripts/lib/ui.sh +42 -0
  107. package/scripts/lib/version-bump.sh +59 -0
  108. package/scripts/lib/worktree-issue-test.sh +45 -0
  109. package/scripts/lib/worktree-issue.sh +73 -0
  110. package/scripts/lib/worktree-start.sh +280 -0
  111. package/scripts/orchestrate.sh +160 -0
  112. package/scripts/portable-test.sh +53 -0
  113. package/scripts/publish.sh +94 -0
  114. package/scripts/setup-labels.sh +25 -0
  115. package/scripts/setup-milestones.sh +17 -0
  116. package/scripts/showcase.sh +64 -0
  117. package/scripts/status.sh +44 -0
  118. package/scripts/task-sync.sh +59 -0
  119. package/scripts/test.sh +48 -0
  120. package/scripts/web-install.sh +22 -0
  121. package/skills/kit-annotate/SKILL.md +107 -0
  122. package/skills/kit-autopilot/SKILL.md +108 -0
  123. package/skills/kit-contribute/SKILL.md +134 -0
  124. package/skills/kit-customize/SKILL.md +134 -0
  125. package/skills/kit-dev/SKILL.md +67 -0
  126. package/skills/kit-digest/SKILL.md +41 -0
  127. package/skills/kit-effort-close/SKILL.md +156 -0
  128. package/skills/kit-effort-new/SKILL.md +173 -0
  129. package/skills/kit-effort-pr/SKILL.md +139 -0
  130. package/skills/kit-effort-start/SKILL.md +85 -0
  131. package/skills/kit-gc/SKILL.md +80 -0
  132. package/skills/kit-onboard/SKILL.md +50 -0
  133. package/skills/kit-security-sweep/SKILL.md +57 -0
  134. package/skills/kit-ship/SKILL.md +43 -0
  135. package/skills/kit-task-close/SKILL.md +66 -0
  136. package/skills/kit-task-new/SKILL.md +51 -0
  137. package/skills/kit-task-pr/SKILL.md +43 -0
  138. package/skills/kit-task-pr-auto/SKILL.md +27 -0
  139. package/skills/kit-task-pr-merge/SKILL.md +53 -0
  140. package/skills/kit-task-start/SKILL.md +76 -0
  141. package/skills/kit-task-sync/SKILL.md +37 -0
  142. package/templates/CLAUDE.md.tmpl +106 -0
  143. package/templates/agents/analyst.md +55 -0
  144. package/templates/agents/auto-dev.md +93 -0
  145. package/templates/agents/backend.md +59 -0
  146. package/templates/agents/designer.md +73 -0
  147. package/templates/agents/devops.md +57 -0
  148. package/templates/agents/editor.md +48 -0
  149. package/templates/agents/frontend.md +81 -0
  150. package/templates/agents/generalist.md +46 -0
  151. package/templates/agents/local-delegate.md +70 -0
  152. package/templates/agents/n8n.md +65 -0
  153. package/templates/agents/pm.md +69 -0
  154. package/templates/agents/qa.md +66 -0
  155. package/templates/agents/researcher.md +57 -0
  156. package/templates/agents/security.md +65 -0
  157. package/templates/agents/tech-lead.md +75 -0
  158. package/templates/hooks/guard-base-branch-commit.sh.tmpl +45 -0
  159. package/templates/hooks/kit-local-status.sh.tmpl +34 -0
  160. package/templates/hooks/kit_version_check.sh.tmpl +6 -0
  161. package/templates/hooks/mempal_followup.sh.tmpl +97 -0
  162. package/templates/hooks/mempal_precompact.sh.tmpl +4 -0
  163. package/templates/hooks/mempal_save.sh.tmpl +4 -0
  164. package/templates/hooks/mempal_session_start.sh.tmpl +8 -0
  165. package/templates/hooks/prepush_gate.sh.tmpl +36 -0
  166. package/templates/hooks/repo-hygiene.sh.tmpl +72 -0
  167. package/templates/kit.config.json.tmpl +32 -0
  168. package/templates/knowledge-INDEX.md.tmpl +12 -0
  169. package/templates/lib/kit-sigil.sh.tmpl +124 -0
  170. package/templates/rules/branch-naming.md +104 -0
  171. package/templates/rules/communication-style.md +22 -0
  172. package/templates/rules/delegation-brief.md +40 -0
  173. package/templates/rules/design-routing.md +35 -0
  174. package/templates/rules/effort-model.md +122 -0
  175. package/templates/rules/knowledge-base.md +41 -0
  176. package/templates/rules/mempalace.md +110 -0
  177. package/templates/rules/plan-output-format.md +58 -0
  178. package/templates/rules/react-annotate.md +69 -0
  179. package/templates/rules/risk-tiered-review.md +62 -0
  180. package/templates/rules/skill-gaps.md +48 -0
  181. package/templates/rules/task-management.md +42 -0
  182. package/templates/settings/settings.local.json.tmpl +27 -0
  183. package/templates/skills/NAMESPACED +13 -0
  184. package/templates/skills/copywriting/SKILL.md +252 -0
  185. package/templates/skills/copywriting/references/copy-frameworks.md +344 -0
  186. package/templates/skills/copywriting/references/natural-transitions.md +272 -0
  187. package/templates/skills/feature-build-refine/SKILL.md +367 -0
  188. package/templates/skills/karpathy-guidelines/SKILL.md +69 -0
  189. package/templates/skills/morning-briefing/SKILL.md +46 -0
  190. package/templates/skills/speckit/SKILL.md +239 -0
  191. package/templates/skills/supabase-patterns/SKILL.md +88 -0
@@ -0,0 +1,367 @@
1
+ ---
2
+ name: feature-build-refine
3
+ description: Feature/form/page build strategy for Next.js (App Router) + React + Supabase + RefineDev + shadcn projects. Self-gating — applies ONLY when RefineDev is in the stack.
4
+ when_to_use: "STACK-GATED. Use when building features, forms, components, or pages AND the project uses RefineDev — detect by checking package.json for @refinedev/* deps (e.g. @refinedev/core, @refinedev/react-hook-form, @refinedev/react-table). If RefineDev is NOT in package.json, this skill does NOT apply — ignore it. When it applies, follow it exactly; its conventions are non-negotiable for that stack."
5
+ ---
6
+
7
+ # Feature / Form / Page Build Strategy (Next.js + Supabase + RefineDev)
8
+
9
+ > **Applicability check first.** Read `package.json`. If there is no `@refinedev/*` dependency,
10
+ > STOP — this skill does not apply to this project. Otherwise follow it exactly. Replace
11
+ > `<model>` / `<feature>` with your domain entity. Supabase-specific data patterns are also
12
+ > covered by the `supabase-patterns` skill; they compose.
13
+
14
+ You are building features for a **Next.js 15 (App Router) + React 19 + TypeScript** app with this stack:
15
+
16
+ - **Backend:** Supabase (PostgreSQL + Auth + RLS)
17
+ - **Admin/CRUD framework:** RefineDev with custom data providers wrapping Supabase
18
+ - **UI:** shadcn-style component library in `src/components/ui/` (built with `cva` variants + a `cn()` clsx/tailwind-merge helper)
19
+ - **Styling:** TailwindCSS v4 with **semantic design tokens** (never hardcoded colors)
20
+ - **Forms:** React Hook Form (`@refinedev/react-hook-form`) + Zod validation
21
+ - **Tables:** TanStack Table via `@refinedev/react-table`
22
+ - **i18n:** i18next — every user-facing string goes through `t()`
23
+ - **Icons:** lucide-react, always with an explicit `className` for sizing
24
+
25
+ Follow the conventions below exactly. They are non-negotiable.
26
+
27
+ ---
28
+
29
+ ## 1. Feature Folder Architecture
30
+
31
+ Every domain entity is a **self-contained feature module** at `src/features/<model>/`. The folder is **flat** — the only allowed subdirectory is `components/`.
32
+
33
+ ```
34
+ src/features/<model>/
35
+ ├── types.ts # Domain interfaces & type aliases ONLY (no constants, no fns, no React)
36
+ ├── constants.ts # Label maps, option arrays, badge-variant maps, pure helper fns
37
+ ├── actions.ts # "use server" — server actions calling Supabase (no types, no React)
38
+ ├── components/
39
+ │ └── <model>-form.tsx # ONE unified Create/Edit form component
40
+ └── index.ts # Public barrel — re-exports types, constants, components
41
+ ```
42
+
43
+ **File responsibility table — enforce strictly:**
44
+
45
+ | File | Contains | Never contains |
46
+ |---|---|---|
47
+ | `types.ts` | interfaces, type aliases | constants, functions, React |
48
+ | `constants.ts` | label maps, option lists, helpers, badge variants | types, server actions, React |
49
+ | `actions.ts` | `"use server"` functions | types, constants, React |
50
+ | `components/<model>-form.tsx` | React form component | business logic, DB calls |
51
+ | `index.ts` | re-exports | **never re-exports `actions.ts`** |
52
+
53
+ **Barrel rule:** `index.ts` exports the form component + its `FormData` type + `export * from "./types"` + `export * from "./constants"`. **Server actions are imported directly from `./actions`** — never through the barrel (keeps `"use server"` boundaries clean).
54
+
55
+ ```typescript
56
+ // src/features/<model>/index.ts
57
+ export { ModelForm } from "./components/<model>-form";
58
+ export type { ModelFormData } from "./components/<model>-form";
59
+ export * from "./types";
60
+ export * from "./constants";
61
+ // DO NOT re-export from ./actions — server actions are imported directly
62
+ ```
63
+
64
+ **Import discipline:**
65
+
66
+ - **Inside** the feature boundary, use **relative** imports (`"./types"`, `"../constants"`) — never `@/features/<model>/…`.
67
+ - **Outside** consumers import from the barrel: `import { ModelForm, FOO_LABELS } from "@/features/<model>"`.
68
+ - **No `src/lib/<model>/`** — feature-specific helpers live in the feature's `constants.ts`. `src/lib/` is only for truly generic, feature-agnostic utilities (`date.ts`, `utils.ts`, `supabase/`, `validations.ts`).
69
+ - **No shims** — when moving code, rewrite all import paths with `sed` and delete the old files. Never leave a re-export stub behind.
70
+
71
+ ---
72
+
73
+ ## 2. The Unified Form Component (the core pattern)
74
+
75
+ There is **ONE component per feature** that handles both Create and Edit. A single `<model>Id?: string` prop drives everything: `isEdit = !!<model>Id`.
76
+
77
+ ### Internal structure (in this order)
78
+
79
+ ```
80
+ <model>-form.tsx
81
+ ├── makeModelSchema(isEdit) → Zod schema factory; superRefine for mode-aware cross-field rules
82
+ ├── ModelFormData (exported) → z.infer<ReturnType<typeof makeModelSchema>>
83
+ ├── DEFAULT_VALUES → const covering EVERY field (shared baseline, both modes)
84
+ ├── Payload (local, unexported) → type for the edit onFinish cast
85
+ └── ModelForm (exported) → ONE component, ONE return, isEdit drives all branching
86
+ ```
87
+
88
+ ### Schema: compose from shared primitives, never inline
89
+
90
+ Keep a `src/lib/validations.ts` of named Zod atoms (`zFullName`, `zEmail`, `zPhone`, `zPhoneOptional`, `zOptionalString`, `zCodigoPostal`, `zUrlOptional`, `zColorHex`, region/enum lists, etc.). **Never write `z.string().min(3).max(100)` when a named primitive exists.**
91
+
92
+ Mode-aware validation uses a **schema factory + `superRefine`**, not two separate schemas:
93
+
94
+ ```typescript
95
+ function makeModelSchema(isEdit: boolean) {
96
+ return z.object({
97
+ // ── Shared ──
98
+ full_name: zFullName,
99
+ email: zEmail,
100
+ // ── Create-only ──
101
+ password: z.string().optional(),
102
+ confirm_password: z.string().optional(),
103
+ // ── Edit-only ──
104
+ status: publicStatusSchema.optional(),
105
+ change_password: z.boolean().default(false),
106
+ }).superRefine((data, ctx) => {
107
+ if (!isEdit) {
108
+ // create-mode cross-field validation (e.g. password match)
109
+ } else {
110
+ // edit-mode cross-field validation
111
+ }
112
+ });
113
+ }
114
+
115
+ export type ModelFormData = z.infer<ReturnType<typeof makeModelSchema>>;
116
+ ```
117
+
118
+ `DEFAULT_VALUES` is a single const covering every field (used for both modes and as the spread base for edit values).
119
+
120
+ ### Populate edit data via `values` — NEVER `useEffect + reset()`
121
+
122
+ This is critical. The fetched record arrives asynchronously; feed it through RHF's `values` prop, which re-initializes the form when its reference changes. `values: undefined` while loading keeps the form at `defaultValues`. `useEffect + reset()` is a banned anti-pattern (stale closures, fires after render).
123
+
124
+ ```typescript
125
+ const isEdit = !!modelId;
126
+ const schema = useMemo(() => makeModelSchema(isEdit), [isEdit]); // stable; isEdit never changes
127
+
128
+ // Fetch existing record only in edit mode
129
+ const { query, result: record } = useOne<ModelProfile, HttpError>({
130
+ resource: "<table>",
131
+ id: modelId ?? "",
132
+ queryOptions: { enabled: isEdit },
133
+ });
134
+
135
+ // Reactive edit values — undefined until the record arrives
136
+ const editValues: ModelFormData | undefined =
137
+ isEdit && record
138
+ ? { ...DEFAULT_VALUES, full_name: record.full_name ?? "", /* …map fields… */ }
139
+ : undefined;
140
+
141
+ const {
142
+ refineCore: { onFinish, formLoading },
143
+ ...form
144
+ } = useForm<BaseRecord, HttpError, ModelFormData>({
145
+ // Bridge Zod's input/output type split WITHOUT `as any`:
146
+ resolver: zodResolver(schema) as unknown as Resolver<ModelFormData>,
147
+ defaultValues: DEFAULT_VALUES,
148
+ values: editValues, // ← drives re-initialization; no useEffect
149
+ refineCoreProps: isEdit
150
+ ? { resource: "<table>", action: "edit", id: modelId, redirect: false, onMutationSuccess: () => { /* router.push + refresh */ } }
151
+ : { action: "create" },
152
+ });
153
+ ```
154
+
155
+ **Submit handling:** edit flow calls refine's `onFinish` (through the data provider); create flow calls the **server action directly**. When the payload type differs from the form type, cast as `(onFinish as unknown as (v: Payload) => Promise<void>)(payload)`.
156
+
157
+ ### Loading / error guards, then ONE return
158
+
159
+ ```tsx
160
+ if (isEdit && query?.isLoading) return <SkeletonCard />;
161
+ if (isEdit && (query?.isError || !record)) return <ErrorCard />;
162
+
163
+ return (
164
+ <Form {...form}>
165
+ <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-8">
166
+ <FormSection title={t("<feature>.sections.general")}>
167
+ <FormGrid cols={2}>
168
+ <TextField name="full_name" label={t("<feature>.fields.fullName")} icon={UserIcon} control={form.control} />
169
+ <TextField name="email" label={t("<feature>.fields.email")} icon={MailIcon} control={form.control} />
170
+ </FormGrid>
171
+ </FormSection>
172
+
173
+ <FormSection title={t("<feature>.sections.details")} separator>
174
+ <FormGrid cols={3}>{/* … */}</FormGrid>
175
+ </FormSection>
176
+
177
+ <FormSubmitActions isLoading={isLoading} isEdit={isEdit} onCancel={() => router.back()} />
178
+ </form>
179
+ </Form>
180
+ );
181
+ ```
182
+
183
+ ---
184
+
185
+ ## 3. Form Layout Primitives — always use, never ad-hoc
186
+
187
+ From `src/components/ui/form-grid.tsx`. **Never** write raw `<div className="grid grid-cols-X gap-Y">` for field rows.
188
+
189
+ - **`<FormGrid cols={1|2|3|4}>`** — responsive grid, collapses to 1 column on mobile.
190
+ - **`<FormSection title description separator>`** — labeled block; `separator` draws a divider above.
191
+ - **`<FormActions>`** — right-aligned submit/cancel row.
192
+ - **`<FormPanel title description action>`** — bordered row with descriptive text + an action button on the right (for non-field actions inside a form, e.g. "Send recovery email").
193
+
194
+ ## 4. Form Field Primitives — `src/components/forms/`
195
+
196
+ These are **pure controlled components** (no internal state, no `useForm` inside them). Each wraps the `FormField → FormItem → FormLabel → FormControl → input → FormMessage` chain. Build them once, reuse everywhere:
197
+
198
+ | Pattern | Component |
199
+ |---|---|
200
+ | Label + Input (optional icon prefix) | `TextField` (pass `icon={IconComponent}` — **never** a manual wrapper div) |
201
+ | Label + Select dropdown | `SelectField` (accepts `Record`, `string[]`, or `{value,label}[]`; uses a `__none__` sentinel because Radix Select rejects empty-string values) |
202
+ | Label + Textarea (+ optional char-count) | `TextareaField` |
203
+ | Label + row of toggle buttons | `ToggleField` / `ToggleButtonGroup` (single or multiple) |
204
+ | Label + searchable multi-select with pills | `MultiSelectField` (wraps `MultiSelectCombobox` — Popover + Command) |
205
+ | Label + bordered checkbox + description | `CheckboxField` |
206
+ | Label + URL input + image preview | `ImageUrlField` |
207
+ | Cancel + Submit button row | `FormSubmitActions` (shows `Loader2` spinner, disables while loading, uses shared `buttons.*` i18n keys) |
208
+ | Anything appearing only once | inline `FormField` |
209
+
210
+ **Extraction rule:** only create a new reusable primitive when the exact raw pattern appears **3+ times** OR a matching primitive already exists. Don't add props for hypothetical future use — add only what the current form needs.
211
+
212
+ **Array/controlled fields:** always use `render={({ field }) => …}` and pass `field.value` / `field.onChange`. Never reach for `form.getValues` / `form.setValue` on a controlled field.
213
+
214
+ Example `TextField` (the canonical primitive shape — generic over `FieldValues`, forwards native input props):
215
+
216
+ ```tsx
217
+ interface TextFieldProps<T extends FieldValues>
218
+ extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "name"> {
219
+ control: Control<T>;
220
+ name: FieldPath<T>;
221
+ label: string;
222
+ icon?: ComponentType<{ className?: string }>;
223
+ description?: React.ReactNode;
224
+ }
225
+ // Renders: FormField → FormItem → FormLabel → FormControl → (icon ? relative-wrapped Input.pl-10 : Input) → FormMessage
226
+ ```
227
+
228
+ ---
229
+
230
+ ## 5. List Pages (DataTable)
231
+
232
+ Built on TanStack Table via `@refinedev/react-table` + a `DataTable` wrapper in `src/components/refine-ui/data-table/`.
233
+
234
+ ```tsx
235
+ const columns = useMemo<ColumnDef<Model>[]>(() => [ /* … */ ], [router]);
236
+
237
+ const table = useTable<Model>({
238
+ columns,
239
+ refineCoreProps: {
240
+ resource: "<table>",
241
+ filters: { permanent: [{ field: "role", operator: "in", value: [...] }] },
242
+ syncWithLocation: true,
243
+ },
244
+ });
245
+
246
+ const { tableQuery } = table.refineCore; // NOT tableQueryResult
247
+ const data = tableQuery.data?.data ?? [];
248
+ ```
249
+
250
+ Column rules:
251
+
252
+ - **Wrap columns in `useMemo`.** Every column has an `id` and a `size` (px width).
253
+ - Use `id` / `accessorKey` / `header` / `cell` (TanStack), **not** `dataIndex` / `render` / `width` (legacy Ant).
254
+ - Headers compose `<DataTableSorter>`, `<DataTableFilterDropdownText>`, `<DataTableFilterCombobox>` (multi-select), `<DataTableFilterDropdownNumeric>`.
255
+ - Action columns set `enableSorting: false` + `enableColumnFilter: false`.
256
+ - Cells use `DataTableTooltip` (hover info), `DataTableBadgeList` (overflowing tag lists), `truncate` for long text.
257
+ - Parent container: `min-w-0`; table container `overflow-x-auto`; `minWidth` = sum of column sizes.
258
+
259
+ Page shell uses `<ListView>` / `<ListViewHeader>` + optional `<ListViewStatistics>` for summary cards.
260
+
261
+ Recommended column sizes: ID 60–80px · Status badge 100–120px · short text 150–200px · name/title 200–300px · email 200–250px · date 100–120px · actions 60–100px.
262
+
263
+ ---
264
+
265
+ ## 6. Route Pages — thin wiring only
266
+
267
+ Pages are thin: they pick a View shell and render the feature form/list. No business logic.
268
+
269
+ ```tsx
270
+ // <route>/create/page.tsx
271
+ "use client";
272
+ import { ModelForm } from "@/features/<model>";
273
+ import { CreateView } from "@/components/refine-ui/views/create-view";
274
+
275
+ export default function CreateModelPage() {
276
+ return <CreateView title="Nuevo Model"><ModelForm /></CreateView>;
277
+ }
278
+
279
+ // <route>/[id]/edit/page.tsx
280
+ "use client";
281
+ import { use } from "react";
282
+ import { ModelForm } from "@/features/<model>";
283
+ import { EditView } from "@/components/refine-ui/views/edit-view";
284
+
285
+ export default function ModelEditPage({ params }: { params: Promise<{ id: string }> }) {
286
+ const { id } = use(params); // React 19: params is a Promise, unwrap with use()
287
+ return <EditView title="Editar Model"><ModelForm modelId={id} /></EditView>;
288
+ }
289
+ ```
290
+
291
+ View shells: `CreateView` / `EditView` / `ListView` / `ShowView` (+ their `*Header` variants). Use the canonical path `<route>/[id]/edit/page.tsx` (not `edit/[id]`).
292
+
293
+ ---
294
+
295
+ ## 7. Server Actions
296
+
297
+ ```typescript
298
+ // src/features/<model>/actions.ts
299
+ "use server";
300
+ import { createClient } from "@/lib/supabase/server";
301
+ import type { CreateModelInput } from "./types";
302
+
303
+ async function requireRole() { // shared auth guard at top of file
304
+ const supabase = await createClient();
305
+ const { data: { user } } = await supabase.auth.getUser();
306
+ if (!user) throw new Error("No autorizado");
307
+ // …role check via profiles table…
308
+ return { supabase, userId: user.id };
309
+ }
310
+
311
+ export async function createModelAction(input: CreateModelInput): Promise<{ id: string }> {
312
+ const { supabase } = await requireRole();
313
+ const { data, error } = await supabase.from("<table>").insert(input).select("id").single();
314
+ if (error) throw error;
315
+ return { id: data.id };
316
+ }
317
+ ```
318
+
319
+ Three Supabase clients, by context (see the `supabase-patterns` skill for detail):
320
+
321
+ - `@/lib/supabase/client` — browser / client components
322
+ - `@/lib/supabase/server` — server components, route handlers, server actions
323
+ - `@/lib/supabase/admin` — service-role operations (`createAdminClient`)
324
+
325
+ ---
326
+
327
+ ## 8. Styling & Tokens
328
+
329
+ - **Semantic tokens only:** `bg-background`, `bg-card`, `bg-muted`, `bg-accent`, `border-border`, `text-foreground`, `text-muted-foreground`, `bg-primary`, `bg-destructive`, etc. These make light/dark themes work. Never hardcode `text-white`, `bg-gray-800`, hex values, or inline `style={{}}`.
330
+ - Brand color used sparingly (`text-brand-*`).
331
+ - Layout with Tailwind grid/flex utilities — never Ant-style `Row`/`Col`.
332
+ - Icons: lucide `*Icon` names, always sized (`<UserIcon className="h-4 w-4" />`).
333
+ - Use `cn()` for conditional classes, not template-string concatenation.
334
+ - Date formatting: a shared `src/lib/date.ts` (`formatDateShort`, `formatDateMedium`, `formatDateTime`, `formatMonthYear`) — never inline `toLocaleDateString` in feature code.
335
+
336
+ ### UI craft constraints
337
+
338
+ - `motion/react` for JS animation, `tw-animate-css` for CSS animation.
339
+ - Animate **only** `transform` and `opacity`, never layout properties. Interaction feedback ≤ 200ms.
340
+ - Radix primitives for keyboard/focus behavior; `AlertDialog` for destructive actions.
341
+ - `text-balance` for headings, `tabular-nums` for data. `h-dvh` not `h-screen`. No gradients unless explicitly requested.
342
+
343
+ ---
344
+
345
+ ## 9. i18n
346
+
347
+ Every user-facing string goes through `t()` from `useTranslation()`. Keys live in `public/locales/<lang>/common.json` under a namespace matching the feature name. No hardcoded display strings in JSX. Use shared keys for generic buttons (`buttons.cancel`, `buttons.save`, `buttons.create`).
348
+
349
+ ---
350
+
351
+ ## 10. Non-Negotiable Rules (checklist)
352
+
353
+ 1. Feature folder is **flat** — only `components/` subdir allowed.
354
+ 2. File names are **dashed-case** (`model-form.tsx`, `constants.ts`).
355
+ 3. **No `src/lib/<model>/`** — feature code goes in `constants.ts`.
356
+ 4. **No shims** — rewrite imports with `sed`, delete old files.
357
+ 5. **No `as any`** — use `as unknown as SpecificType` with a comment.
358
+ 6. **Relative imports inside the feature**, barrel imports outside.
359
+ 7. **`actions.ts` never re-exported** from `index.ts`.
360
+ 8. **Shared date formatting** via `@/lib/date`.
361
+ 9. **Form layout** always via `FormGrid`/`FormSection`/`FormActions` — no ad-hoc grids.
362
+ 10. **Controlled fields** use `field.value`/`field.onChange`, never `getValues`/`setValue`.
363
+ 11. **`values` not `useEffect + reset()`** for edit population.
364
+ 12. **No constants in `.tsx`** — they belong in `constants.ts`; check shared validations first.
365
+ 13. **Compose Zod from shared primitives**, don't duplicate inline chains.
366
+ 14. **All strings through `t()`**.
367
+ 15. **`TextField` icon via `icon` prop**, never manual wrapper divs.
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: karpathy-guidelines
3
+ description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
4
+ license: MIT
5
+ ---
6
+
7
+ # Karpathy Guidelines
8
+
9
+ Behavioral guidelines to reduce common LLM coding mistakes, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls.
10
+
11
+ > Vendored into claude-kit from [multica-ai/andrej-karpathy-skills](https://github.com/multica-ai/andrej-karpathy-skills) (MIT, © forrestchang). Available in every profile — it applies to all developers.
12
+
13
+ **Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
14
+
15
+ ## 1. Think Before Coding
16
+
17
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
18
+
19
+ Before implementing:
20
+ - State your assumptions explicitly. If uncertain, ask.
21
+ - If multiple interpretations exist, present them - don't pick silently.
22
+ - If a simpler approach exists, say so. Push back when warranted.
23
+ - If something is unclear, stop. Name what's confusing. Ask.
24
+
25
+ ## 2. Simplicity First
26
+
27
+ **Minimum code that solves the problem. Nothing speculative.**
28
+
29
+ - No features beyond what was asked.
30
+ - No abstractions for single-use code.
31
+ - No "flexibility" or "configurability" that wasn't requested.
32
+ - No error handling for impossible scenarios.
33
+ - If you write 200 lines and it could be 50, rewrite it.
34
+
35
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
36
+
37
+ ## 3. Surgical Changes
38
+
39
+ **Touch only what you must. Clean up only your own mess.**
40
+
41
+ When editing existing code:
42
+ - Don't "improve" adjacent code, comments, or formatting.
43
+ - Don't refactor things that aren't broken.
44
+ - Match existing style, even if you'd do it differently.
45
+ - If you notice unrelated dead code, mention it - don't delete it.
46
+
47
+ When your changes create orphans:
48
+ - Remove imports/variables/functions that YOUR changes made unused.
49
+ - Don't remove pre-existing dead code unless asked.
50
+
51
+ The test: Every changed line should trace directly to the user's request.
52
+
53
+ ## 4. Goal-Driven Execution
54
+
55
+ **Define success criteria. Loop until verified.**
56
+
57
+ Transform tasks into verifiable goals:
58
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
59
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
60
+ - "Refactor X" → "Ensure tests pass before and after"
61
+
62
+ For multi-step tasks, state a brief plan:
63
+ ```
64
+ 1. [Step] → verify: [check]
65
+ 2. [Step] → verify: [check]
66
+ 3. [Step] → verify: [check]
67
+ ```
68
+
69
+ Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: morning-briefing
3
+ description: Daily briefing — what's active on the board, what's blocked, what to focus on.
4
+ when_to_use: When the owner starts their day or asks for a morning briefing / daily summary.
5
+ ---
6
+
7
+ # Morning Briefing
8
+
9
+ ## What it does
10
+
11
+ Reads GitHub (source of truth) + active plans, then delivers a concise briefing. Reads repo + plans dir from `.claude/kit.config.json`.
12
+
13
+ ## How to run
14
+
15
+ ```bash
16
+ source scripts/lib/kit-config.sh && load_kit_config
17
+ gh issue list --repo "$KIT_REPO" --state open --json number,title,labels,assignees --limit 30
18
+ # then scan $KIT_PLANS_DIR for active plans (anything not in archive/) if plans are enabled
19
+ ```
20
+
21
+ Then produce:
22
+
23
+ ---
24
+
25
+ **Buenos días.** · **Today is [day], [date].**
26
+
27
+ ### Urgent
28
+ - [p1 issues open or blocked]
29
+
30
+ ### Focus today
31
+ - [top 1–3 In Progress or unblocked items]
32
+
33
+ ### On the radar
34
+ - [upcoming Todo items or active plans]
35
+
36
+ ### Active plans
37
+ - [active plans by title; skip if none]
38
+
39
+ ---
40
+
41
+ ## Rules
42
+
43
+ - No long intros — straight to the briefing
44
+ - Bullets only · keep under 30 lines · skip empty sections
45
+ - Language: match the owner (see `.claude/rules/communication-style.md`)
46
+ - Source of truth is GitHub — never invent task state