rbin-task-flow 1.5.0 → 1.7.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/.cursor/rules/coding_standards.mdc +68 -27
- package/AGENTS.md +42 -0
- package/lib/install.js +32 -38
- package/package.json +2 -1
|
@@ -21,12 +21,42 @@ src/
|
|
|
21
21
|
└── shared/ # Global reusable code
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
### Allowed folders in shared/ and features/ (Front web & Mobile only)
|
|
25
|
+
|
|
26
|
+
In **front web** (Next.js, React, or other React-based web) or **mobile** (Expo, React Native) projects, only the following folder names may exist directly under `shared/` or under each feature in `features/`:
|
|
27
|
+
|
|
28
|
+
| Folder | Use |
|
|
29
|
+
|---------------|------------------------|
|
|
30
|
+
| `pages/` | Web only — page components |
|
|
31
|
+
| `screens/` | Mobile only — screen components |
|
|
32
|
+
| `components/` | UI components |
|
|
33
|
+
| `constants/` | Constants |
|
|
34
|
+
| `utils/` | Utilities |
|
|
35
|
+
| `validations/` | Validation helpers (e.g. `.validation.ts` for Zod) |
|
|
36
|
+
| `hooks/` | Custom hooks |
|
|
37
|
+
| `providers/` | Context providers |
|
|
38
|
+
| `styles/` | Styles |
|
|
39
|
+
| `types/` | TypeScript types |
|
|
40
|
+
| `libs/` | Library wrappers |
|
|
41
|
+
| `services/` | React Query / API wrappers |
|
|
42
|
+
| `use-cases/` | Pure API / business logic |
|
|
43
|
+
| `schemas/` | Zod (or similar) schemas |
|
|
44
|
+
|
|
45
|
+
**No other folder names** are allowed under `shared/` or under `features/[feature-name]/`. Use only `pages/` for web and `screens/` for mobile; do not mix both in the same project type.
|
|
46
|
+
|
|
47
|
+
### No subfolders in shared/ (Front web & Mobile only)
|
|
48
|
+
|
|
49
|
+
In **front web** (Next.js, React) or **mobile** (Expo, React Native) projects, each folder under `shared/` must be **flat**: no subfolders. Files assume the responsibility through clear naming.
|
|
50
|
+
|
|
51
|
+
- **shared/components/**: One file per component, directly in `shared/components/`. No nested folders (e.g. no `form/`, `inputs/`). Name files so the purpose is clear (e.g. `button.tsx`, `input-text.tsx`, `input-container.tsx`, `input-error.tsx`, `input-label.tsx`).
|
|
52
|
+
- **shared/hooks/**, **shared/utils/**, **shared/validations/**, **shared/constants/**, etc.: Same rule — only files, no subfolders. Use the file name to carry the responsibility. Validation helpers (e.g. `required-email.validation.ts`) live in `shared/validations/`.
|
|
53
|
+
|
|
24
54
|
---
|
|
25
55
|
|
|
26
56
|
## Tech Stack
|
|
27
57
|
|
|
28
|
-
### Front-end (Next.js)
|
|
29
|
-
- **Framework**: Next.js 15+ with App Router
|
|
58
|
+
### Front-end (Next.js / React)
|
|
59
|
+
- **Framework**: Next.js 15+ with App Router, or React (Vite, CRA, or similar). These rules apply to any React-based web project.
|
|
30
60
|
- **Language**: TypeScript (strict mode)
|
|
31
61
|
- **Styling**: Tailwind CSS v4 + `clsx` + `tailwind-merge` via `cn()` helper
|
|
32
62
|
- **UI Components**: shadcn/ui + `lucide-react` icons
|
|
@@ -37,7 +67,7 @@ src/
|
|
|
37
67
|
- **E2E Testing**: Playwright and/or Cypress
|
|
38
68
|
|
|
39
69
|
### Mobile (Expo / React Native)
|
|
40
|
-
- **Framework**: Expo with Expo Router
|
|
70
|
+
- **Framework**: Expo with Expo Router, or React Native (bare or managed). These rules apply to both Expo and React Native.
|
|
41
71
|
- **Language**: TypeScript (strict mode)
|
|
42
72
|
- **Styling**: NativeWind + `clsx` + `tailwind-merge` via `cn()` helper
|
|
43
73
|
- **Data Fetching**: `@tanstack/react-query`
|
|
@@ -61,7 +91,7 @@ src/
|
|
|
61
91
|
|
|
62
92
|
The `app/` directory contains ONLY route definitions. Each file is a thin wrapper that imports and renders the feature page/screen.
|
|
63
93
|
|
|
64
|
-
**Front-end (Next.js App Router):**
|
|
94
|
+
**Front-end (Next.js App Router or React):**
|
|
65
95
|
```typescript
|
|
66
96
|
// src/app/(private)/dashboard/page.tsx
|
|
67
97
|
import { DashboardPage } from '@/features/dashboard/pages/dashboard.page'
|
|
@@ -71,7 +101,7 @@ export default function Dashboard() {
|
|
|
71
101
|
}
|
|
72
102
|
```
|
|
73
103
|
|
|
74
|
-
**Mobile (Expo Router):**
|
|
104
|
+
**Mobile (Expo Router or React Native):**
|
|
75
105
|
```typescript
|
|
76
106
|
// src/app/(private)/dashboard.tsx
|
|
77
107
|
import { DashboardScreen } from '@/features/dashboard/screens/dashboard.screen'
|
|
@@ -283,6 +313,8 @@ export function DashboardActiveCard({ data, isLoading, isError }: DashboardActiv
|
|
|
283
313
|
|
|
284
314
|
## shared/ — Global Reusable Code
|
|
285
315
|
|
|
316
|
+
In front web (Next.js, React) and mobile (Expo, React Native), `shared/` is flat per folder (no subfolders). One file per concern; naming carries the responsibility.
|
|
317
|
+
|
|
286
318
|
```
|
|
287
319
|
shared/
|
|
288
320
|
├── components/
|
|
@@ -291,14 +323,11 @@ shared/
|
|
|
291
323
|
│ ├── data-handler.tsx
|
|
292
324
|
│ ├── skeleton.tsx
|
|
293
325
|
│ ├── dialog.tsx
|
|
294
|
-
│
|
|
295
|
-
│
|
|
296
|
-
│
|
|
297
|
-
│
|
|
298
|
-
│
|
|
299
|
-
│ ├── input-container.tsx
|
|
300
|
-
│ ├── input-error.tsx
|
|
301
|
-
│ └── input-label.tsx
|
|
326
|
+
│ ├── input-text.tsx
|
|
327
|
+
│ ├── input-select.tsx
|
|
328
|
+
│ ├── input-container.tsx
|
|
329
|
+
│ ├── input-error.tsx
|
|
330
|
+
│ └── input-label.tsx
|
|
302
331
|
├── hooks/
|
|
303
332
|
│ ├── dialog.hook.tsx
|
|
304
333
|
│ └── drawer.hook.tsx
|
|
@@ -312,11 +341,11 @@ shared/
|
|
|
312
341
|
│ └── shared.ui.type.ts
|
|
313
342
|
├── constants/
|
|
314
343
|
│ └── server-routes.constants.ts
|
|
344
|
+
├── validations/
|
|
345
|
+
│ ├── required-email.validation.ts
|
|
346
|
+
│ ├── required-string.validation.ts
|
|
347
|
+
│ └── required-phone.validation.ts
|
|
315
348
|
└── utils/
|
|
316
|
-
├── validation/
|
|
317
|
-
│ ├── required-email.validation.ts
|
|
318
|
-
│ ├── required-string.validation.ts
|
|
319
|
-
│ └── required-phone.validation.ts
|
|
320
349
|
└── error.util.ts
|
|
321
350
|
```
|
|
322
351
|
|
|
@@ -516,8 +545,8 @@ export type ServiceInput<TData = unknown> = {
|
|
|
516
545
|
```typescript
|
|
517
546
|
// src/features/auth/schemas/login.schema.ts
|
|
518
547
|
import { z } from 'zod'
|
|
519
|
-
import { requiredEmail } from '@/shared/
|
|
520
|
-
import { requiredString } from '@/shared/
|
|
548
|
+
import { requiredEmail } from '@/shared/validations/required-email.validation'
|
|
549
|
+
import { requiredString } from '@/shared/validations/required-string.validation'
|
|
521
550
|
|
|
522
551
|
export const loginSchema = z.object({
|
|
523
552
|
email: requiredEmail(),
|
|
@@ -529,7 +558,7 @@ export type LoginSchema = z.infer<typeof loginSchema>
|
|
|
529
558
|
|
|
530
559
|
**Reusable validators in shared/:**
|
|
531
560
|
```typescript
|
|
532
|
-
// src/shared/
|
|
561
|
+
// src/shared/validations/required-string.validation.ts
|
|
533
562
|
import { z } from 'zod'
|
|
534
563
|
|
|
535
564
|
export const requiredString = ({ field, min = 1 }: { field: string; min?: number }) =>
|
|
@@ -547,7 +576,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
|
|
|
547
576
|
import { useForm } from 'react-hook-form'
|
|
548
577
|
import { LoginSchema, loginSchema } from '@/features/auth/schemas/login.schema'
|
|
549
578
|
import { SessionCreateService } from '@/features/auth/services/session-create.service'
|
|
550
|
-
import { InputText } from '@/shared/components/
|
|
579
|
+
import { InputText } from '@/shared/components/input-text'
|
|
551
580
|
import { Button } from '@/shared/components/button'
|
|
552
581
|
|
|
553
582
|
export function LoginForm() {
|
|
@@ -572,7 +601,7 @@ export function LoginForm() {
|
|
|
572
601
|
|
|
573
602
|
**Input uses `Controller` from RHF and is generic:**
|
|
574
603
|
```typescript
|
|
575
|
-
// src/shared/components/
|
|
604
|
+
// src/shared/components/input-text.tsx
|
|
576
605
|
import { Control, Controller, FieldValues, Path, PathValue } from 'react-hook-form'
|
|
577
606
|
import { cn } from '@/shared/libs/tw-merge'
|
|
578
607
|
|
|
@@ -616,13 +645,24 @@ export function InputText<T extends FieldValues>({
|
|
|
616
645
|
|
|
617
646
|
## File Naming Conventions
|
|
618
647
|
|
|
619
|
-
|
|
648
|
+
### Rule for front (web & mobile): outside `app/` only
|
|
649
|
+
|
|
650
|
+
Every file outside the `app/` folder must follow:
|
|
651
|
+
|
|
652
|
+
- **Format**: lowercase, words separated by `-`, then `.tipo.ext` (suffix by role).
|
|
653
|
+
- **Examples**: `pagina-exemplo.page.tsx`, `login.schema.ts`, `session-create.use-case.ts`, `dashboard-active.type.ts`.
|
|
654
|
+
|
|
655
|
+
**Components are the exception**: do **not** use a `.component` suffix. Use only kebab-case + extension, e.g. `pagina-exemplo.tsx`, `dashboard-revenue-card.tsx`, `input-text.tsx`.
|
|
656
|
+
|
|
657
|
+
**Another exception**: files inside any `styles/` folder do not need to follow this pattern (e.g. CSS/SCSS modules may use their own convention).
|
|
658
|
+
|
|
659
|
+
### Suffix by role
|
|
620
660
|
|
|
621
661
|
| Role | Suffix | Example |
|
|
622
662
|
|------|--------|---------|
|
|
623
|
-
| Page component | `.page.tsx` | `
|
|
663
|
+
| Page component | `.page.tsx` | `pagina-exemplo.page.tsx` |
|
|
624
664
|
| Screen component (mobile) | `.screen.tsx` | `login.screen.tsx` |
|
|
625
|
-
| UI component | `.tsx` | `dashboard-revenue-card.tsx` |
|
|
665
|
+
| UI component | (no suffix) `.tsx` | `dashboard-revenue-card.tsx`, `input-text.tsx` |
|
|
626
666
|
| React Query service | `.service.tsx` | `session-create.service.tsx` |
|
|
627
667
|
| API call (pure) | `.use-case.ts` | `session-create.use-case.ts` |
|
|
628
668
|
| Zod schema | `.schema.ts` | `login.schema.ts` |
|
|
@@ -630,7 +670,7 @@ Use kebab-case for all filenames. Suffix reflects the file's role:
|
|
|
630
670
|
| API response type | `.api.type.ts` | `session.api.type.ts` |
|
|
631
671
|
| Domain type | `.type.ts` | `dashboard-active.type.ts` |
|
|
632
672
|
| Utility | `.util.ts` | `error.util.ts` |
|
|
633
|
-
| Validation helper | `.validation.ts` | `required-email.validation.ts` |
|
|
673
|
+
| Validation helper | `.validation.ts` | `required-email.validation.ts` (in `validations/`) |
|
|
634
674
|
| Constants | `.constants.ts` | `server-routes.constants.ts` |
|
|
635
675
|
|
|
636
676
|
---
|
|
@@ -684,7 +724,7 @@ export const useAuth = () => useContext(AuthContext)
|
|
|
684
724
|
|
|
685
725
|
## Testing
|
|
686
726
|
|
|
687
|
-
### Front-end (Next.js)
|
|
727
|
+
### Front-end (Next.js / React)
|
|
688
728
|
- **E2E**: Playwright and/or Cypress
|
|
689
729
|
- Tests live in `e2e/` or `cypress/` at project root
|
|
690
730
|
- Test files: `[feature].spec.ts` (Playwright) or `[feature].cy.ts` (Cypress)
|
|
@@ -710,3 +750,4 @@ export const useAuth = () => useContext(AuthContext)
|
|
|
710
750
|
8. **Type everything**: No `any`. All props, params, and return values must be typed.
|
|
711
751
|
9. **Shared is truly shared**: Only put in `shared/` what is used by 2+ features.
|
|
712
752
|
10. **Naming reflects role**: File name + suffix must make the file's purpose immediately obvious.
|
|
753
|
+
11. **No barrel files for re-exports**: Do not use `index.ts` (or `index.tsx`) only to re-export other modules. Import directly from the source file (e.g. `from '@/shared/components/button'` not `from '@/shared/components'`). An `index.ts` is only allowed when it contains real logic or composition, not mere re-exports.
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Project norms (Codex)
|
|
2
|
+
|
|
3
|
+
This repo follows the same development norms as in `.cursor/rules/` and `CLAUDE.md`. When working here, follow these rules.
|
|
4
|
+
|
|
5
|
+
## Git
|
|
6
|
+
|
|
7
|
+
- **Never run** `git add`, `git commit`, `git push`, `git pull`, `git merge`, `git checkout`, `git reset`, `git rebase`, etc.
|
|
8
|
+
- **Only suggest** git commands; the user runs them.
|
|
9
|
+
- You **may** run read-only git: `git status`, `git diff`, `git log`, `git show`, `git branch` (list only).
|
|
10
|
+
|
|
11
|
+
## Commits
|
|
12
|
+
|
|
13
|
+
- After completing tasks, **suggest** a commit message (Conventional Commits: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`).
|
|
14
|
+
- Include task/subtask ID when relevant, e.g. `Task ID: 3.2`.
|
|
15
|
+
|
|
16
|
+
## Code and comments
|
|
17
|
+
|
|
18
|
+
- **No explanatory comments** in code; keep code self-explanatory via names.
|
|
19
|
+
- **Document non-obvious or complex topics** in `dev-logs/` (markdown).
|
|
20
|
+
- **Allowed comments**: only section separators in this form:
|
|
21
|
+
```text
|
|
22
|
+
// ────────────────────────────────
|
|
23
|
+
// Section Name
|
|
24
|
+
// ────────────────────────────────
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## RBIN Task Flow
|
|
28
|
+
|
|
29
|
+
- **Task flow** always means **RBIN Task Flow**.
|
|
30
|
+
- Tasks: `.task-flow/tasks.input.txt` (format: `- Task description`).
|
|
31
|
+
- Status: `.task-flow/tasks.status.md` and `.task-flow/.internal/status.json`.
|
|
32
|
+
- **Commands** to support: `task-flow: sync`, `task-flow: think`, `task-flow: audit`, `task-flow: status`, `task-flow: run next X`, `task-flow: run X` (or `X,Y` / `all`), `task-flow: review X`, `task-flow: refactor X`, `task-flow: estimate X`, `task-flow: report X`.
|
|
33
|
+
- When running `task-flow: audit`: scan the codebase, score it against `.cursor/rules/coding_standards.mdc`, present a report, and ask the user which improvements to adopt — never impose changes.
|
|
34
|
+
- When running subtasks: read `.task-flow/.internal/tasks.json` and `status.json`, implement, then update `status.json` and `tasks.status.md` (mark done, refresh summary).
|
|
35
|
+
- Use context from `.task-flow/contexts/` when subtask instructions reference it.
|
|
36
|
+
|
|
37
|
+
## Full rules
|
|
38
|
+
|
|
39
|
+
For complete wording and examples, see:
|
|
40
|
+
|
|
41
|
+
- `CLAUDE.md` – overview and task-flow commands
|
|
42
|
+
- `.cursor/rules/` – all rules (git, commits, comments, task-flow, etc.)
|
package/lib/install.js
CHANGED
|
@@ -48,7 +48,7 @@ async function installInProject(targetPath, options = {}) {
|
|
|
48
48
|
|
|
49
49
|
spinner.text = 'Copying configuration files...';
|
|
50
50
|
|
|
51
|
-
await copyConfigs(targetPath);
|
|
51
|
+
await copyConfigs(targetPath, isUpdate);
|
|
52
52
|
|
|
53
53
|
spinner.text = 'Updating .gitignore...';
|
|
54
54
|
|
|
@@ -69,14 +69,14 @@ async function installInProject(targetPath, options = {}) {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
async function copyConfigs(targetPath) {
|
|
72
|
+
async function copyConfigs(targetPath, isUpdate = false) {
|
|
73
73
|
const cursorRulesPath = path.join(TEMPLATE_DIR, '.cursor/rules');
|
|
74
|
+
const cursorRulesDest = path.join(targetPath, '.cursor/rules');
|
|
74
75
|
if (fs.existsSync(cursorRulesPath)) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
);
|
|
76
|
+
if (isUpdate && fs.existsSync(cursorRulesDest)) {
|
|
77
|
+
await fs.emptyDir(cursorRulesDest);
|
|
78
|
+
}
|
|
79
|
+
await fs.copy(cursorRulesPath, cursorRulesDest, { overwrite: true });
|
|
80
80
|
showSuccess('Cursor rules');
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -110,6 +110,16 @@ async function copyConfigs(targetPath) {
|
|
|
110
110
|
showSuccess('Claude instructions');
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
const agentsPath = path.join(TEMPLATE_DIR, 'AGENTS.md');
|
|
114
|
+
if (fs.existsSync(agentsPath)) {
|
|
115
|
+
await fs.copy(
|
|
116
|
+
agentsPath,
|
|
117
|
+
path.join(targetPath, 'AGENTS.md'),
|
|
118
|
+
{ overwrite: true }
|
|
119
|
+
);
|
|
120
|
+
showSuccess('Codex instructions (AGENTS.md)');
|
|
121
|
+
}
|
|
122
|
+
|
|
113
123
|
await copyTaskFlow(targetPath);
|
|
114
124
|
}
|
|
115
125
|
|
|
@@ -119,39 +129,22 @@ async function copyTaskFlow(targetPath) {
|
|
|
119
129
|
|
|
120
130
|
await fs.ensureDir(taskFlowDest);
|
|
121
131
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const contextsDest = path.join(taskFlowDest, 'contexts');
|
|
126
|
-
await fs.ensureDir(contextsDest);
|
|
127
|
-
showSuccess('Contexts directory (.task-flow/contexts/)');
|
|
128
|
-
|
|
129
|
-
const docsDest = path.join(taskFlowDest, 'docs');
|
|
130
|
-
await fs.ensureDir(docsDest);
|
|
131
|
-
showSuccess('Documentation directory (.task-flow/docs/)');
|
|
132
|
-
|
|
133
|
-
const exampleSrc = path.join(taskFlowSrc, 'contexts/example.png.txt');
|
|
134
|
-
const exampleDest = path.join(contextsDest, 'example.png.txt');
|
|
135
|
-
if (fs.existsSync(exampleSrc) && !fs.existsSync(exampleDest)) {
|
|
136
|
-
await fs.copy(exampleSrc, exampleDest);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const files = [
|
|
140
|
-
{ name: 'README.md', overwrite: true },
|
|
141
|
-
{ name: 'tasks.input.txt', overwrite: false },
|
|
142
|
-
{ name: 'tasks.status.md', overwrite: false }
|
|
132
|
+
const PROTECTED = [
|
|
133
|
+
path.join(taskFlowDest, '.internal'),
|
|
143
134
|
];
|
|
144
135
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
136
|
+
await fs.copy(taskFlowSrc, taskFlowDest, {
|
|
137
|
+
overwrite: true,
|
|
138
|
+
filter: (src) => {
|
|
139
|
+
return !PROTECTED.some((p) => src.startsWith(p));
|
|
140
|
+
},
|
|
141
|
+
});
|
|
148
142
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
143
|
+
await fs.ensureDir(path.join(taskFlowDest, 'contexts'));
|
|
144
|
+
await fs.ensureDir(path.join(taskFlowDest, 'docs'));
|
|
145
|
+
|
|
146
|
+
showSuccess('Task Flow directory (overwritten)');
|
|
147
|
+
showInfo('Protected: .internal/ (your task data is safe)');
|
|
155
148
|
}
|
|
156
149
|
|
|
157
150
|
async function updateGitignore(targetPath) {
|
|
@@ -167,7 +160,8 @@ async function updateGitignore(targetPath) {
|
|
|
167
160
|
'.claude/',
|
|
168
161
|
'.cursor/',
|
|
169
162
|
'.task-flow/',
|
|
170
|
-
'CLAUDE.md'
|
|
163
|
+
'CLAUDE.md',
|
|
164
|
+
'AGENTS.md'
|
|
171
165
|
];
|
|
172
166
|
|
|
173
167
|
for (const entry of entries) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rbin-task-flow",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "AI-powered task management for Claude and Cursor",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
".task-flow/",
|
|
34
34
|
".model-versions.json",
|
|
35
35
|
"CLAUDE.md",
|
|
36
|
+
"AGENTS.md",
|
|
36
37
|
"lib/"
|
|
37
38
|
],
|
|
38
39
|
"preferGlobal": true,
|