workflow-agent-cli 2.0.1 → 2.2.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/README.md +33 -17
- package/dist/chunk-IPMSSOXR.js +293 -0
- package/dist/chunk-IPMSSOXR.js.map +1 -0
- package/dist/{chunk-X2NQJ2ZY.js → chunk-NMHWD2GA.js} +11 -6
- package/dist/chunk-NMHWD2GA.js.map +1 -0
- package/dist/cli/index.js +777 -165
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +8 -3
- package/dist/config/index.js +9 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +10 -4
- package/dist/schema-C1lmnd7L.d.ts +256 -0
- package/dist/scripts/postinstall.js +6 -2
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/validators/index.d.ts +1 -1
- package/dist/validators/index.js +1 -1
- package/package.json +17 -15
- package/templates/AGENT_EDITING_INSTRUCTIONS.md +226 -39
- package/templates/COMPONENT_LIBRARY.md +23 -17
- package/templates/CUSTOM_SCOPE_TEMPLATE.md +5 -4
- package/templates/LIBRARY_INVENTORY.md +20 -20
- package/templates/SCOPE_CREATION_WORKFLOW.md +39 -11
- package/templates/SELF_IMPROVEMENT_MANDATE.md +24 -18
- package/templates/SINGLE_SOURCE_OF_TRUTH.md +59 -42
- package/templates/TESTING_STRATEGY.md +79 -69
- package/templates/_TEMPLATE_EXAMPLE.md +2 -1
- package/LICENSE +0 -21
- package/dist/chunk-4BIDFDSR.js +0 -152
- package/dist/chunk-4BIDFDSR.js.map +0 -1
- package/dist/chunk-X2NQJ2ZY.js.map +0 -1
- package/dist/schema-RkQ91pZW.d.ts +0 -161
|
@@ -144,6 +144,176 @@ Any decisions, blockers, or context for future reference.
|
|
|
144
144
|
|
|
145
145
|
> ⚠️ **IMPORTANT**: Never push directly to `main`. Always push to your feature branch and create a PR.
|
|
146
146
|
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 🚨 MANDATORY PRE-COMMIT CHECKLIST - ZERO EXCEPTIONS
|
|
150
|
+
|
|
151
|
+
> **CRITICAL RULE**: This is a "one-and-done" service commitment. The following pre-commit checks are MANDATORY before ANY commit and push. There are ZERO EXCEPTIONS to this rule.
|
|
152
|
+
|
|
153
|
+
### Auto-Setup Guarantee
|
|
154
|
+
|
|
155
|
+
**If ANY mandatory check tool is not configured** (missing config files, scripts, or dependencies), Agent MUST automatically set them up based on industry best practices BEFORE running checks.
|
|
156
|
+
|
|
157
|
+
👉 **Complete auto-setup documentation**: [../../docs/AUTO_SETUP_TOOLS.md](../../docs/AUTO_SETUP_TOOLS.md)
|
|
158
|
+
|
|
159
|
+
### The Rule
|
|
160
|
+
|
|
161
|
+
**Before EVERY commit and push, Agent MUST:**
|
|
162
|
+
|
|
163
|
+
1. ✅ **Run all pre-commit checks** (listed below)
|
|
164
|
+
2. 🔧 **Fix ALL errors encountered** automatically
|
|
165
|
+
3. 🔄 **Re-run checks** until all pass
|
|
166
|
+
4. ✅ **Only then commit and push**
|
|
167
|
+
|
|
168
|
+
### Pre-Commit Execution Sequence
|
|
169
|
+
|
|
170
|
+
Execute these commands in this exact order. If ANY command fails, fix the errors and restart from step 1:
|
|
171
|
+
|
|
172
|
+
#### Step 1: Type Check
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
pnpm typecheck
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**If errors occur:**
|
|
179
|
+
|
|
180
|
+
- Fix all TypeScript type errors
|
|
181
|
+
- Remove any `any` types
|
|
182
|
+
- Ensure proper type imports
|
|
183
|
+
- Re-run until clean
|
|
184
|
+
|
|
185
|
+
#### Step 2: Lint Check
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
pnpm lint
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**If errors occur:**
|
|
192
|
+
|
|
193
|
+
- Fix all ESLint errors
|
|
194
|
+
- Address all warnings
|
|
195
|
+
- Ensure import ordering is correct
|
|
196
|
+
- Re-run until clean
|
|
197
|
+
|
|
198
|
+
#### Step 3: Format Check
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
pnpm format
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**This command auto-fixes, then verify:**
|
|
205
|
+
|
|
206
|
+
- All files are properly formatted
|
|
207
|
+
- No formatting inconsistencies remain
|
|
208
|
+
|
|
209
|
+
#### Step 4: Unit Tests
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
pnpm test
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**If tests fail:**
|
|
216
|
+
|
|
217
|
+
- Fix failing test logic
|
|
218
|
+
- Update test expectations if changes are intentional
|
|
219
|
+
- Add missing test coverage for new code
|
|
220
|
+
- Re-run until all tests pass
|
|
221
|
+
|
|
222
|
+
#### Step 5: Build Verification
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
pnpm build
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**If build fails:**
|
|
229
|
+
|
|
230
|
+
- Fix compilation errors
|
|
231
|
+
- Resolve module resolution issues
|
|
232
|
+
- Ensure all imports are valid
|
|
233
|
+
- Re-run until build succeeds
|
|
234
|
+
|
|
235
|
+
### Automated Pre-Commit Check Script
|
|
236
|
+
|
|
237
|
+
Agent should execute this comprehensive check:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
#!/bin/bash
|
|
241
|
+
# Pre-commit validation - ALL must pass
|
|
242
|
+
|
|
243
|
+
echo "🔍 Running pre-commit checks..."
|
|
244
|
+
|
|
245
|
+
echo "📘 Step 1/5: Type checking..."
|
|
246
|
+
pnpm typecheck || { echo "❌ Type check failed. Fix errors and retry."; exit 1; }
|
|
247
|
+
|
|
248
|
+
echo "🔍 Step 2/5: Linting..."
|
|
249
|
+
pnpm lint || { echo "❌ Lint check failed. Fix errors and retry."; exit 1; }
|
|
250
|
+
|
|
251
|
+
echo "✨ Step 3/5: Formatting..."
|
|
252
|
+
pnpm format || { echo "❌ Format check failed. Fix errors and retry."; exit 1; }
|
|
253
|
+
|
|
254
|
+
echo "🧪 Step 4/5: Unit tests..."
|
|
255
|
+
pnpm test || { echo "❌ Tests failed. Fix errors and retry."; exit 1; }
|
|
256
|
+
|
|
257
|
+
echo "🏗️ Step 5/5: Build verification..."
|
|
258
|
+
pnpm build || { echo "❌ Build failed. Fix errors and retry."; exit 1; }
|
|
259
|
+
|
|
260
|
+
echo "✅ All pre-commit checks passed! Ready to commit."
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Agent Workflow for Commits
|
|
264
|
+
|
|
265
|
+
When Agent is ready to commit, follow this EXACT workflow:
|
|
266
|
+
|
|
267
|
+
1. **Stage changes**: `git add .`
|
|
268
|
+
|
|
269
|
+
2. **Run pre-commit checks**: Execute all 5 steps above
|
|
270
|
+
|
|
271
|
+
3. **If ANY check fails**:
|
|
272
|
+
- Analyze the error output
|
|
273
|
+
- Fix the errors in the codebase
|
|
274
|
+
- Commit the fixes
|
|
275
|
+
- Return to step 2 (re-run ALL checks)
|
|
276
|
+
|
|
277
|
+
4. **When ALL checks pass**:
|
|
278
|
+
- Commit with proper message: `git commit -m "<type>(<scope>): <description>"`
|
|
279
|
+
- Push to branch: `git push origin <branch-name>`
|
|
280
|
+
|
|
281
|
+
5. **Verification**: After push, confirm:
|
|
282
|
+
- GitHub Actions pipeline is triggered
|
|
283
|
+
- All CI checks are passing
|
|
284
|
+
- No pipeline failures
|
|
285
|
+
|
|
286
|
+
### Error Handling Protocol
|
|
287
|
+
|
|
288
|
+
**When errors are encountered:**
|
|
289
|
+
|
|
290
|
+
| Error Type | Agent Action |
|
|
291
|
+
| ------------- | ------------------------------------------------------------ |
|
|
292
|
+
| Type errors | Analyze and fix type definitions, imports, and usage |
|
|
293
|
+
| Lint errors | Apply auto-fix where possible, manual fix for complex issues |
|
|
294
|
+
| Format errors | Re-run `pnpm format` (usually auto-fixes) |
|
|
295
|
+
| Test failures | Update test logic, fix implementation, or update snapshots |
|
|
296
|
+
| Build errors | Fix compilation issues, resolve imports, check dependencies |
|
|
297
|
+
|
|
298
|
+
**After fixing errors:**
|
|
299
|
+
|
|
300
|
+
- ✅ Commit the fixes separately if needed
|
|
301
|
+
- 🔄 Re-run the COMPLETE pre-commit checklist from step 1
|
|
302
|
+
- ⚠️ Never skip steps or assume fixes worked without verification
|
|
303
|
+
|
|
304
|
+
### Accountability
|
|
305
|
+
|
|
306
|
+
This workflow ensures:
|
|
307
|
+
|
|
308
|
+
- ✅ **Zero regressions** reach the main branch
|
|
309
|
+
- ✅ **All code is production-ready** before merging
|
|
310
|
+
- ✅ **CI/CD pipelines always pass** (no surprises)
|
|
311
|
+
- ✅ **"One-and-done"** - customers receive working code, first time
|
|
312
|
+
|
|
313
|
+
> 🔒 **ENFORCEMENT**: This rule has ZERO EXCEPTIONS. Agent will not commit or push code that fails any of these checks. Period.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
147
317
|
### Auto-Cleanup Rules
|
|
148
318
|
|
|
149
319
|
| Trigger | Action |
|
|
@@ -350,15 +520,15 @@ Every component story file MUST include:
|
|
|
350
520
|
**Story Template:**
|
|
351
521
|
|
|
352
522
|
```tsx
|
|
353
|
-
import type { Meta, StoryObj } from
|
|
354
|
-
import { ComponentName } from
|
|
355
|
-
import { mockFeatureFlags } from
|
|
523
|
+
import type { Meta, StoryObj } from "@storybook/nextjs-vite";
|
|
524
|
+
import { ComponentName } from "./ui/component-name";
|
|
525
|
+
import { mockFeatureFlags } from "@/lib/feature-flags";
|
|
356
526
|
|
|
357
527
|
const meta: Meta<typeof ComponentName> = {
|
|
358
|
-
title:
|
|
528
|
+
title: "Category/ComponentName",
|
|
359
529
|
component: ComponentName,
|
|
360
|
-
tags: [
|
|
361
|
-
parameters: { layout:
|
|
530
|
+
tags: ["autodocs"],
|
|
531
|
+
parameters: { layout: "centered" },
|
|
362
532
|
decorators: [
|
|
363
533
|
(Story) => {
|
|
364
534
|
mockFeatureFlags({ FEATURE_FLAG: true });
|
|
@@ -501,28 +671,28 @@ Imports MUST follow this exact order, with blank lines between groups:
|
|
|
501
671
|
|
|
502
672
|
```typescript
|
|
503
673
|
// 1. Directive (MUST be first line if present)
|
|
504
|
-
|
|
674
|
+
"use server";
|
|
505
675
|
// OR
|
|
506
|
-
|
|
676
|
+
"use client";
|
|
507
677
|
|
|
508
678
|
// 2. React imports
|
|
509
|
-
import React, { useState, useEffect, useCallback } from
|
|
679
|
+
import React, { useState, useEffect, useCallback } from "react";
|
|
510
680
|
|
|
511
681
|
// 3. External library imports (alphabetical)
|
|
512
|
-
import { useDrag } from
|
|
513
|
-
import { QueryClient } from
|
|
514
|
-
import { z } from
|
|
682
|
+
import { useDrag } from "react-dnd";
|
|
683
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
684
|
+
import { z } from "zod";
|
|
515
685
|
|
|
516
686
|
// 4. Internal absolute imports with @/ prefix (alphabetical by path)
|
|
517
|
-
import { createServerClient } from
|
|
518
|
-
import { verifyBoardAccess } from
|
|
519
|
-
import type { Task, Sprint } from
|
|
520
|
-
import { useAuth } from
|
|
687
|
+
import { createServerClient } from "@/lib/supabase/server";
|
|
688
|
+
import { verifyBoardAccess } from "@/utils/authorization.server";
|
|
689
|
+
import type { Task, Sprint } from "@/types";
|
|
690
|
+
import { useAuth } from "@/app/providers";
|
|
521
691
|
|
|
522
692
|
// 5. Relative imports (parent directories first, then siblings)
|
|
523
|
-
import { Button } from
|
|
524
|
-
import { TaskCard } from
|
|
525
|
-
import type { LocalType } from
|
|
693
|
+
import { Button } from "../ui/button";
|
|
694
|
+
import { TaskCard } from "./TaskCard";
|
|
695
|
+
import type { LocalType } from "./types";
|
|
526
696
|
```
|
|
527
697
|
|
|
528
698
|
### Naming Conventions
|
|
@@ -548,27 +718,31 @@ import type { LocalType } from './types';
|
|
|
548
718
|
|
|
549
719
|
```typescript
|
|
550
720
|
export async function getEntity(
|
|
551
|
-
id: string
|
|
721
|
+
id: string,
|
|
552
722
|
): Promise<{ data: Entity | null; error: string | null }> {
|
|
553
723
|
try {
|
|
554
724
|
// 1. Verify access FIRST
|
|
555
725
|
const access = await verifyEntityAccess(id);
|
|
556
726
|
if (!access.hasAccess) {
|
|
557
|
-
return { data: null, error: access.error ||
|
|
727
|
+
return { data: null, error: access.error || "Access denied" };
|
|
558
728
|
}
|
|
559
729
|
|
|
560
730
|
const supabase = await createServerClient();
|
|
561
|
-
const { data, error } = await supabase
|
|
731
|
+
const { data, error } = await supabase
|
|
732
|
+
.from("entities")
|
|
733
|
+
.select("*")
|
|
734
|
+
.eq("id", id)
|
|
735
|
+
.single();
|
|
562
736
|
|
|
563
737
|
if (error) {
|
|
564
|
-
console.error(
|
|
738
|
+
console.error("Error fetching entity:", error);
|
|
565
739
|
return { data: null, error: error.message };
|
|
566
740
|
}
|
|
567
741
|
|
|
568
742
|
return { data: transformEntity(data), error: null };
|
|
569
743
|
} catch (err) {
|
|
570
|
-
console.error(
|
|
571
|
-
return { data: null, error:
|
|
744
|
+
console.error("Unexpected error:", err);
|
|
745
|
+
return { data: null, error: "An unexpected error occurred" };
|
|
572
746
|
}
|
|
573
747
|
}
|
|
574
748
|
```
|
|
@@ -583,10 +757,10 @@ const handleSubmit = async () => {
|
|
|
583
757
|
toast.error(error);
|
|
584
758
|
return;
|
|
585
759
|
}
|
|
586
|
-
toast.success(
|
|
760
|
+
toast.success("Created successfully");
|
|
587
761
|
onSuccess?.(data);
|
|
588
762
|
} catch (err) {
|
|
589
|
-
toast.error(
|
|
763
|
+
toast.error("An unexpected error occurred");
|
|
590
764
|
}
|
|
591
765
|
};
|
|
592
766
|
```
|
|
@@ -612,12 +786,12 @@ const handleSubmit = async () => {
|
|
|
612
786
|
5. **Never expose sensitive data** - filter fields before returning
|
|
613
787
|
|
|
614
788
|
```typescript
|
|
615
|
-
|
|
789
|
+
"use server";
|
|
616
790
|
|
|
617
|
-
import { createServerClient } from
|
|
618
|
-
import { verifyBoardAccess } from
|
|
619
|
-
import { revalidatePath } from
|
|
620
|
-
import type { Task } from
|
|
791
|
+
import { createServerClient } from "@/lib/supabase/server";
|
|
792
|
+
import { verifyBoardAccess } from "@/utils/authorization.server";
|
|
793
|
+
import { revalidatePath } from "next/cache";
|
|
794
|
+
import type { Task } from "@/types";
|
|
621
795
|
|
|
622
796
|
interface TaskRow {
|
|
623
797
|
id: string;
|
|
@@ -636,17 +810,20 @@ function transformTask(row: TaskRow): Task {
|
|
|
636
810
|
}
|
|
637
811
|
|
|
638
812
|
export async function getTasks(
|
|
639
|
-
boardId: string
|
|
813
|
+
boardId: string,
|
|
640
814
|
): Promise<{ data: Task[] | null; error: string | null }> {
|
|
641
815
|
// 1. Authorization FIRST
|
|
642
816
|
const access = await verifyBoardAccess(boardId);
|
|
643
817
|
if (!access.hasAccess) {
|
|
644
|
-
return { data: null, error: access.error ||
|
|
818
|
+
return { data: null, error: access.error || "Access denied" };
|
|
645
819
|
}
|
|
646
820
|
|
|
647
821
|
// 2. Fetch data
|
|
648
822
|
const supabase = await createServerClient();
|
|
649
|
-
const { data, error } = await supabase
|
|
823
|
+
const { data, error } = await supabase
|
|
824
|
+
.from("tasks")
|
|
825
|
+
.select("*")
|
|
826
|
+
.eq("board_id", boardId);
|
|
650
827
|
|
|
651
828
|
if (error) {
|
|
652
829
|
return { data: null, error: error.message };
|
|
@@ -717,12 +894,15 @@ export function TaskCard({ task, onEdit, readOnly = false }: TaskCardProps) {
|
|
|
717
894
|
|
|
718
895
|
```typescript
|
|
719
896
|
// Server action
|
|
720
|
-
import {
|
|
897
|
+
import {
|
|
898
|
+
verifyBoardAccess,
|
|
899
|
+
requireContributorAccess,
|
|
900
|
+
} from "@/utils/authorization.server";
|
|
721
901
|
|
|
722
902
|
export async function createTask(boardId: string, data: CreateTaskData) {
|
|
723
903
|
const boardAccess = await verifyBoardAccess(boardId);
|
|
724
904
|
if (!boardAccess.hasAccess) {
|
|
725
|
-
return { data: null, error:
|
|
905
|
+
return { data: null, error: "Access denied" };
|
|
726
906
|
}
|
|
727
907
|
|
|
728
908
|
// For write operations, also check role
|
|
@@ -853,16 +1033,23 @@ When creating a PR, use Agent to automatically fill out the PR description:
|
|
|
853
1033
|
|
|
854
1034
|
Before creating a PR, Agent must verify:
|
|
855
1035
|
|
|
1036
|
+
- [ ] **🚨 MANDATORY PRE-COMMIT CHECKLIST completed** - See section above (ZERO EXCEPTIONS)
|
|
1037
|
+
- [ ] ✅ Type check passed (`pnpm typecheck`)
|
|
1038
|
+
- [ ] ✅ Lint check passed (`pnpm lint`)
|
|
1039
|
+
- [ ] ✅ Format check passed (`pnpm format`)
|
|
1040
|
+
- [ ] ✅ Unit tests passed (`pnpm test`)
|
|
1041
|
+
- [ ] ✅ Build verification passed (`pnpm build`)
|
|
856
1042
|
- [ ] All required files for the change type have been touched
|
|
857
1043
|
- [ ] No `any` types introduced
|
|
858
1044
|
- [ ] Authorization added for new data access
|
|
859
1045
|
- [ ] Types updated in `types/index.ts`
|
|
860
|
-
- [ ]
|
|
861
|
-
- [ ] E2E tests pass for affected flows (`pnpm test:e2e`)
|
|
1046
|
+
- [ ] E2E tests pass for affected flows (`pnpm test:e2e`) if applicable
|
|
862
1047
|
- [ ] No unapproved new libraries added
|
|
863
1048
|
- [ ] Import order follows the standard
|
|
864
1049
|
- [ ] `data-testid` attributes added for testable elements
|
|
865
1050
|
|
|
1051
|
+
> ⚠️ **NOTE**: The mandatory pre-commit checklist MUST be completed before even considering a PR. If any pre-commit check fails, the code is not ready for PR.
|
|
1052
|
+
|
|
866
1053
|
---
|
|
867
1054
|
|
|
868
1055
|
## Quick Reference: Path Aliases
|
|
@@ -269,11 +269,12 @@ import {
|
|
|
269
269
|
FormDialogSection,
|
|
270
270
|
FormDialogField,
|
|
271
271
|
useFormDialog,
|
|
272
|
-
} from
|
|
272
|
+
} from "@/components/FormDialog";
|
|
273
273
|
|
|
274
274
|
function CreateSprintDialog() {
|
|
275
|
-
const { isOpen, isSubmitting, setIsSubmitting, open, close } =
|
|
276
|
-
|
|
275
|
+
const { isOpen, isSubmitting, setIsSubmitting, open, close } =
|
|
276
|
+
useFormDialog();
|
|
277
|
+
const [name, setName] = useState("");
|
|
277
278
|
|
|
278
279
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
279
280
|
e.preventDefault();
|
|
@@ -359,8 +360,13 @@ Use sections to group related fields:
|
|
|
359
360
|
Use `FormDialogField` error prop for validation:
|
|
360
361
|
|
|
361
362
|
```tsx
|
|
362
|
-
<FormDialogField
|
|
363
|
-
|
|
363
|
+
<FormDialogField
|
|
364
|
+
label="Email"
|
|
365
|
+
required
|
|
366
|
+
error={errors.email?.message}
|
|
367
|
+
htmlFor="email"
|
|
368
|
+
>
|
|
369
|
+
<Input id="email" {...register("email")} />
|
|
364
370
|
</FormDialogField>
|
|
365
371
|
```
|
|
366
372
|
|
|
@@ -418,14 +424,14 @@ components/
|
|
|
418
424
|
#### Behavioral Tests
|
|
419
425
|
|
|
420
426
|
```typescript
|
|
421
|
-
describe(
|
|
422
|
-
it(
|
|
423
|
-
it(
|
|
424
|
-
it(
|
|
425
|
-
it(
|
|
426
|
-
it(
|
|
427
|
-
it(
|
|
428
|
-
it(
|
|
427
|
+
describe("StatusBadge", () => {
|
|
428
|
+
it("should render without crashing", () => {});
|
|
429
|
+
it("should render all status variants", () => {});
|
|
430
|
+
it("should apply correct colors for each status", () => {});
|
|
431
|
+
it("should respect size prop", () => {});
|
|
432
|
+
it("should apply custom className", () => {});
|
|
433
|
+
it("should handle feature flag disabled state", () => {});
|
|
434
|
+
it("should handle feature flag enabled state", () => {});
|
|
429
435
|
});
|
|
430
436
|
```
|
|
431
437
|
|
|
@@ -510,19 +516,19 @@ function TaskRow({ task }) {
|
|
|
510
516
|
### Testing with Flags
|
|
511
517
|
|
|
512
518
|
```typescript
|
|
513
|
-
import { mockFeatureFlag, clearFeatureFlagMocks } from
|
|
519
|
+
import { mockFeatureFlag, clearFeatureFlagMocks } from "@/lib/feature-flags";
|
|
514
520
|
|
|
515
|
-
describe(
|
|
521
|
+
describe("Component with feature flag", () => {
|
|
516
522
|
afterEach(() => {
|
|
517
523
|
clearFeatureFlagMocks();
|
|
518
524
|
});
|
|
519
525
|
|
|
520
|
-
it(
|
|
526
|
+
it("should render new component when flag enabled", () => {
|
|
521
527
|
mockFeatureFlag(FeatureFlag.STATUS_BADGE, true);
|
|
522
528
|
// test new behavior
|
|
523
529
|
});
|
|
524
530
|
|
|
525
|
-
it(
|
|
531
|
+
it("should render fallback when flag disabled", () => {
|
|
526
532
|
mockFeatureFlag(FeatureFlag.STATUS_BADGE, false);
|
|
527
533
|
// test fallback behavior
|
|
528
534
|
});
|
|
@@ -137,11 +137,11 @@ describe('{{presetName}} Scope Preset', () => {
|
|
|
137
137
|
## tsup.config.ts Template
|
|
138
138
|
|
|
139
139
|
```typescript
|
|
140
|
-
import { defineConfig } from
|
|
140
|
+
import { defineConfig } from "tsup";
|
|
141
141
|
|
|
142
142
|
export default defineConfig({
|
|
143
|
-
entry: [
|
|
144
|
-
format: [
|
|
143
|
+
entry: ["src/index.ts"],
|
|
144
|
+
format: ["esm"],
|
|
145
145
|
dts: true,
|
|
146
146
|
clean: true,
|
|
147
147
|
sourcemap: true,
|
|
@@ -153,6 +153,7 @@ export default defineConfig({
|
|
|
153
153
|
To create a custom scope package using these templates:
|
|
154
154
|
|
|
155
155
|
1. **Use the CLI** (recommended):
|
|
156
|
+
|
|
156
157
|
```bash
|
|
157
158
|
workflow scope:create
|
|
158
159
|
```
|
|
@@ -180,7 +181,7 @@ Each scope in `{{scopeDefinitions}}` must match:
|
|
|
180
181
|
name: string; // lowercase, alphanumeric, hyphens, max 32 chars
|
|
181
182
|
description: string; // min 10 characters
|
|
182
183
|
emoji?: string; // optional emoji
|
|
183
|
-
category?: 'auth' | 'features' | 'infrastructure' | 'documentation' |
|
|
184
|
+
category?: 'auth' | 'features' | 'infrastructure' | 'documentation' |
|
|
184
185
|
'testing' | 'performance' | 'other';
|
|
185
186
|
}
|
|
186
187
|
```
|
|
@@ -84,13 +84,13 @@
|
|
|
84
84
|
|
|
85
85
|
```typescript
|
|
86
86
|
// Browser client (singleton)
|
|
87
|
-
import { getSupabaseClient } from
|
|
87
|
+
import { getSupabaseClient } from "@/lib/supabase/client";
|
|
88
88
|
|
|
89
89
|
// Server client (for server components/actions)
|
|
90
|
-
import { createServerClient } from
|
|
90
|
+
import { createServerClient } from "@/lib/supabase/server";
|
|
91
91
|
|
|
92
92
|
// Admin client (bypasses RLS)
|
|
93
|
-
import { createAdminClient } from
|
|
93
|
+
import { createAdminClient } from "@/lib/supabase/admin";
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
**Files:**
|
|
@@ -112,11 +112,11 @@ import { createAdminClient } from '@/lib/supabase/admin';
|
|
|
112
112
|
**Usage Patterns:**
|
|
113
113
|
|
|
114
114
|
```typescript
|
|
115
|
-
import { useQuery, useMutation, useQueryClient } from
|
|
115
|
+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
116
116
|
|
|
117
117
|
// Fetching data
|
|
118
118
|
const { data, isLoading, error } = useQuery({
|
|
119
|
-
queryKey: [
|
|
119
|
+
queryKey: ["tasks", boardId],
|
|
120
120
|
queryFn: () => getTasks(boardId),
|
|
121
121
|
});
|
|
122
122
|
|
|
@@ -125,7 +125,7 @@ const queryClient = useQueryClient();
|
|
|
125
125
|
const mutation = useMutation({
|
|
126
126
|
mutationFn: createTask,
|
|
127
127
|
onSuccess: () => {
|
|
128
|
-
queryClient.invalidateQueries({ queryKey: [
|
|
128
|
+
queryClient.invalidateQueries({ queryKey: ["tasks"] });
|
|
129
129
|
},
|
|
130
130
|
});
|
|
131
131
|
```
|
|
@@ -197,9 +197,9 @@ const mutation = useMutation({
|
|
|
197
197
|
**Usage Pattern:**
|
|
198
198
|
|
|
199
199
|
```typescript
|
|
200
|
-
import { Button } from
|
|
201
|
-
import { Dialog, DialogContent, DialogHeader } from
|
|
202
|
-
import { Input } from
|
|
200
|
+
import { Button } from "@/components/ui/button";
|
|
201
|
+
import { Dialog, DialogContent, DialogHeader } from "@/components/ui/dialog";
|
|
202
|
+
import { Input } from "@/components/ui/input";
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
### Lucide React (Icons)
|
|
@@ -234,11 +234,11 @@ import { Plus, Trash, Settings, ChevronDown } from "lucide-react";
|
|
|
234
234
|
**Usage Pattern:**
|
|
235
235
|
|
|
236
236
|
```typescript
|
|
237
|
-
import { toast } from
|
|
237
|
+
import { toast } from "sonner";
|
|
238
238
|
|
|
239
|
-
toast.success(
|
|
240
|
-
toast.error(
|
|
241
|
-
toast.loading(
|
|
239
|
+
toast.success("Task created successfully");
|
|
240
|
+
toast.error("Failed to delete task");
|
|
241
|
+
toast.loading("Saving changes...");
|
|
242
242
|
```
|
|
243
243
|
|
|
244
244
|
### Vaul (Drawer)
|
|
@@ -273,12 +273,12 @@ toast.loading('Saving changes...');
|
|
|
273
273
|
**Usage Pattern:**
|
|
274
274
|
|
|
275
275
|
```typescript
|
|
276
|
-
import { useForm } from
|
|
277
|
-
import { zodResolver } from
|
|
276
|
+
import { useForm } from "react-hook-form";
|
|
277
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
278
278
|
|
|
279
279
|
const form = useForm<FormData>({
|
|
280
280
|
resolver: zodResolver(formSchema),
|
|
281
|
-
defaultValues: { title:
|
|
281
|
+
defaultValues: { title: "", description: "" },
|
|
282
282
|
});
|
|
283
283
|
```
|
|
284
284
|
|
|
@@ -294,13 +294,13 @@ const form = useForm<FormData>({
|
|
|
294
294
|
**Usage Patterns:**
|
|
295
295
|
|
|
296
296
|
```typescript
|
|
297
|
-
import { z } from
|
|
297
|
+
import { z } from "zod";
|
|
298
298
|
|
|
299
299
|
// Define schema
|
|
300
300
|
export const TaskSchema = z.object({
|
|
301
301
|
id: z.string().uuid(),
|
|
302
302
|
title: z.string().min(1).max(255),
|
|
303
|
-
priority: z.enum([
|
|
303
|
+
priority: z.enum(["low", "medium", "high", "critical"]),
|
|
304
304
|
});
|
|
305
305
|
|
|
306
306
|
// Infer type from schema
|
|
@@ -520,9 +520,9 @@ pnpm test:e2e # Run E2E tests
|
|
|
520
520
|
**Usage Pattern:**
|
|
521
521
|
|
|
522
522
|
```typescript
|
|
523
|
-
import { format, parseISO, differenceInDays } from
|
|
523
|
+
import { format, parseISO, differenceInDays } from "date-fns";
|
|
524
524
|
|
|
525
|
-
format(new Date(),
|
|
525
|
+
format(new Date(), "MMM d, yyyy"); // "Jan 8, 2026"
|
|
526
526
|
differenceInDays(endDate, startDate);
|
|
527
527
|
```
|
|
528
528
|
|