Compare commits
2 Commits
8eddbed00b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a91a8e9dfa | ||
|
|
fb94745588 |
251
.agents/skills/feature-planning/SKILL.md
Normal file
251
.agents/skills/feature-planning/SKILL.md
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
# Feature Planning Skill
|
||||||
|
|
||||||
|
This skill provides a structured workflow for implementing new features in the TimeTracker project. Use this skill when the user requests a new feature or significant functionality change.
|
||||||
|
|
||||||
|
## Workflow Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Requirements Discovery (iterative)
|
||||||
|
└── Clarify edge cases, acceptance criteria, constraints
|
||||||
|
|
||||||
|
2. Feature Plan Creation
|
||||||
|
└── docs/features/{feature-name}.md
|
||||||
|
|
||||||
|
3. Implementation
|
||||||
|
└── Use plan as single source of truth
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 1: Requirements Discovery
|
||||||
|
|
||||||
|
**Goal:** Understand exactly what needs to be built before writing any code.
|
||||||
|
|
||||||
|
### Questions to Ask
|
||||||
|
|
||||||
|
Ask targeted questions to clarify:
|
||||||
|
|
||||||
|
#### Core Functionality
|
||||||
|
- What is the primary purpose of this feature?
|
||||||
|
- What user problem does it solve?
|
||||||
|
- How should users interact with this feature?
|
||||||
|
|
||||||
|
#### Data & API
|
||||||
|
- What new data needs to be stored?
|
||||||
|
- What existing data structures are affected?
|
||||||
|
- What API endpoints are needed (if any)?
|
||||||
|
|
||||||
|
#### User Interface
|
||||||
|
- Where in the UI should this feature appear?
|
||||||
|
- What views or components are needed?
|
||||||
|
- What user interactions are required?
|
||||||
|
|
||||||
|
#### Edge Cases
|
||||||
|
- What happens when inputs are invalid?
|
||||||
|
- How should errors be handled?
|
||||||
|
- What are the boundary conditions?
|
||||||
|
- Are there any race conditions to consider?
|
||||||
|
|
||||||
|
#### Constraints
|
||||||
|
- Are there performance requirements?
|
||||||
|
- Any security considerations?
|
||||||
|
- Browser/device compatibility?
|
||||||
|
- Integration with existing features?
|
||||||
|
|
||||||
|
### Iteration Process
|
||||||
|
|
||||||
|
1. **Initial Questions** — Ask 3-5 focused questions based on the feature description
|
||||||
|
2. **Wait for Answers** — Let the programmer respond
|
||||||
|
3. **Follow-up Questions** — Dig deeper based on responses
|
||||||
|
4. **Confirm Understanding** — Summarize your understanding and ask for confirmation
|
||||||
|
5. **Iterate** — Repeat until requirements are clear
|
||||||
|
|
||||||
|
### Example Question Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "Add the ability to export time entries to CSV"
|
||||||
|
|
||||||
|
Agent: "Before I start planning, I have a few questions:
|
||||||
|
|
||||||
|
1. Should the export include all entries or only filtered entries (if filters are active)?
|
||||||
|
2. What columns should be included in the CSV? (date, duration, project, client, description?)
|
||||||
|
3. Should the CSV include break minutes and net duration, or just total time?
|
||||||
|
4. Is there a date range limit, or can users export all historical data?
|
||||||
|
5. Should the export be triggered from the Time Entries page, or from a separate Export page?"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 2: Feature Plan
|
||||||
|
|
||||||
|
**Goal:** Create a comprehensive plan document before implementation.
|
||||||
|
|
||||||
|
### Plan Location
|
||||||
|
|
||||||
|
Create the plan at: `docs/features/{feature-name}.md`
|
||||||
|
|
||||||
|
Use kebab-case for the filename (e.g., `csv-export.md`, `dark-mode.md`).
|
||||||
|
|
||||||
|
### Plan Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Feature: {Feature Name}
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Brief description of what this feature does and why it's needed.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Functional Requirements
|
||||||
|
- Requirement 1
|
||||||
|
- Requirement 2
|
||||||
|
- Requirement 3
|
||||||
|
|
||||||
|
### Non-Functional Requirements
|
||||||
|
- Performance: ...
|
||||||
|
- Security: ...
|
||||||
|
- Usability: ...
|
||||||
|
|
||||||
|
### Constraints
|
||||||
|
- Constraint 1
|
||||||
|
- Constraint 2
|
||||||
|
|
||||||
|
## Technical Approach
|
||||||
|
|
||||||
|
### Architecture Decisions
|
||||||
|
- Decision 1 and rationale
|
||||||
|
- Decision 2 and rationale
|
||||||
|
|
||||||
|
### Database Changes
|
||||||
|
- New tables/columns
|
||||||
|
- Migrations needed
|
||||||
|
- Data migration strategy (if any)
|
||||||
|
|
||||||
|
### API Changes
|
||||||
|
- New endpoints
|
||||||
|
- Modified endpoints
|
||||||
|
- Request/response formats
|
||||||
|
|
||||||
|
### Frontend Changes
|
||||||
|
- New components
|
||||||
|
- Modified components
|
||||||
|
- State management approach
|
||||||
|
|
||||||
|
## Implementation Steps
|
||||||
|
|
||||||
|
1. **Step 1: Backend - Database**
|
||||||
|
- Create migration
|
||||||
|
- Update Prisma schema
|
||||||
|
- Regenerate client
|
||||||
|
|
||||||
|
2. **Step 2: Backend - Service**
|
||||||
|
- Add service methods
|
||||||
|
- Add validation schemas
|
||||||
|
|
||||||
|
3. **Step 3: Backend - Routes**
|
||||||
|
- Create route handlers
|
||||||
|
- Add middleware
|
||||||
|
|
||||||
|
4. **Step 4: Frontend - API Client**
|
||||||
|
- Add API functions
|
||||||
|
|
||||||
|
5. **Step 5: Frontend - Components**
|
||||||
|
- Create/update components
|
||||||
|
- Add to routes if needed
|
||||||
|
|
||||||
|
6. **Step 6: Testing**
|
||||||
|
- Manual testing steps
|
||||||
|
- Edge case verification
|
||||||
|
|
||||||
|
## File Changes
|
||||||
|
|
||||||
|
### New Files
|
||||||
|
- `backend/src/services/export.service.ts`
|
||||||
|
- `frontend/src/hooks/useExport.ts`
|
||||||
|
|
||||||
|
### Modified Files
|
||||||
|
- `backend/src/routes/timeEntry.routes.ts` — Add export endpoint
|
||||||
|
- `frontend/src/pages/TimeEntriesPage.tsx` — Add export button
|
||||||
|
- `frontend/src/api/timeEntries.ts` — Add export function
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- No changes required (or specify migration)
|
||||||
|
|
||||||
|
## Edge Cases
|
||||||
|
|
||||||
|
| Case | Handling |
|
||||||
|
|------|----------|
|
||||||
|
| No entries match filter | Show empty state, export empty CSV with headers |
|
||||||
|
| Very large export (>10k entries) | Stream response, show progress indicator |
|
||||||
|
| User cancels export mid-stream | Gracefully close connection |
|
||||||
|
| Invalid date range | Return 400 error with clear message |
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
### Manual Testing
|
||||||
|
1. Navigate to Time Entries page
|
||||||
|
2. Apply date filter
|
||||||
|
3. Click Export button
|
||||||
|
4. Verify CSV downloads with correct data
|
||||||
|
5. Open CSV and verify format
|
||||||
|
|
||||||
|
### Edge Case Testing
|
||||||
|
1. Export with no entries
|
||||||
|
2. Export with 1000+ entries
|
||||||
|
3. Export with special characters in descriptions
|
||||||
|
4. Export while timer is running
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
|
||||||
|
- [ ] Question 1 (to be resolved during implementation)
|
||||||
|
- [ ] Question 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Plan Review
|
||||||
|
|
||||||
|
After creating the plan:
|
||||||
|
|
||||||
|
1. Present the plan to the programmer
|
||||||
|
2. Ask for feedback and approval
|
||||||
|
3. Make requested changes
|
||||||
|
4. Get final approval before proceeding to implementation
|
||||||
|
|
||||||
|
## Phase 3: Implementation
|
||||||
|
|
||||||
|
**Goal:** Implement the feature exactly as planned.
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
1. **Read the plan first** — Start by reading the full plan file
|
||||||
|
2. **Follow the plan** — Implement step by step as outlined
|
||||||
|
3. **Update if needed** — If implementation differs from plan, update the plan file
|
||||||
|
4. **Document changes** — After completion, update relevant documentation
|
||||||
|
|
||||||
|
### Implementation Checklist
|
||||||
|
|
||||||
|
- [ ] Read `docs/features/{feature-name}.md`
|
||||||
|
- [ ] Implement database changes (if any)
|
||||||
|
- [ ] Implement backend service logic
|
||||||
|
- [ ] Implement backend routes
|
||||||
|
- [ ] Implement frontend API client
|
||||||
|
- [ ] Implement frontend components
|
||||||
|
- [ ] Run linting: `npm run lint`
|
||||||
|
- [ ] Manual testing
|
||||||
|
- [ ] Update plan if implementation differs
|
||||||
|
- [ ] Update `project.md` if requirements changed
|
||||||
|
- [ ] Update `README.md` if API changed
|
||||||
|
- [ ] Update `AGENTS.md` if patterns changed
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
- Frontend lint: `npm run lint` (in `frontend/`)
|
||||||
|
- Backend build: `npm run build` (in `backend/`)
|
||||||
|
- DB migration: `npm run db:migrate` (in `backend/`)
|
||||||
|
- DB generate: `npm run db:generate` (in `backend/`)
|
||||||
|
|
||||||
|
### File Locations
|
||||||
|
- Backend routes: `backend/src/routes/`
|
||||||
|
- Backend services: `backend/src/services/`
|
||||||
|
- Backend schemas: `backend/src/schemas/`
|
||||||
|
- Frontend pages: `frontend/src/pages/`
|
||||||
|
- Frontend hooks: `frontend/src/hooks/`
|
||||||
|
- Frontend API: `frontend/src/api/`
|
||||||
|
- Feature plans: `docs/features/`
|
||||||
24
AGENTS.md
24
AGENTS.md
@@ -49,6 +49,30 @@ This document describes the structure, conventions, and commands for the `vibe_c
|
|||||||
### After Making Changes
|
### After Making Changes
|
||||||
**Always update documentation.** See [Documentation Maintenance](#documentation-maintenance).
|
**Always update documentation.** See [Documentation Maintenance](#documentation-maintenance).
|
||||||
|
|
||||||
|
## Feature Development Workflow
|
||||||
|
|
||||||
|
**For new features, AI agents MUST follow this process before writing any code.**
|
||||||
|
|
||||||
|
### Phase 1: Requirements Discovery
|
||||||
|
1. Ask clarifying questions about the feature request
|
||||||
|
2. Identify edge cases, constraints, and acceptance criteria
|
||||||
|
3. Confirm understanding with the programmer
|
||||||
|
4. Iterate until requirements are clear
|
||||||
|
|
||||||
|
### Phase 2: Feature Plan
|
||||||
|
1. Create `docs/features/{feature-name}.md` with the feature plan
|
||||||
|
2. Include: overview, requirements, technical approach, file changes, edge cases, testing
|
||||||
|
3. Present plan for review
|
||||||
|
4. Iterate until approved by the programmer
|
||||||
|
|
||||||
|
### Phase 3: Implementation
|
||||||
|
1. Use the approved plan as the single source of truth
|
||||||
|
2. Implement step by step following the plan
|
||||||
|
3. Update the plan if implementation differs
|
||||||
|
4. Update documentation after completion
|
||||||
|
|
||||||
|
**See the `feature-planning` skill for detailed workflow and templates.**
|
||||||
|
|
||||||
## Documentation Maintenance
|
## Documentation Maintenance
|
||||||
|
|
||||||
**Every code change requires a documentation review.** When you modify the codebase, check whether documentation needs updating.
|
**Every code change requires a documentation review.** When you modify the codebase, check whether documentation needs updating.
|
||||||
|
|||||||
7
DOCS.md
7
DOCS.md
@@ -8,6 +8,13 @@
|
|||||||
| `README.md` | Setup instructions, API reference, features list | New endpoints, config changes, new features, technology stack changes |
|
| `README.md` | Setup instructions, API reference, features list | New endpoints, config changes, new features, technology stack changes |
|
||||||
| `project.md` | Requirements, data model, functional specifications | Business logic changes, new entities, validation rules, UI requirements |
|
| `project.md` | Requirements, data model, functional specifications | Business logic changes, new entities, validation rules, UI requirements |
|
||||||
| `DOCS.md` | Documentation standards and index | Documentation process changes, new documentation files |
|
| `DOCS.md` | Documentation standards and index | Documentation process changes, new documentation files |
|
||||||
|
| `docs/features/*.md` | Feature implementation plans | Created during feature development, updated if implementation differs |
|
||||||
|
|
||||||
|
## AI Agent Skills
|
||||||
|
|
||||||
|
| Skill | Purpose | When to Use |
|
||||||
|
|-------|---------|-------------|
|
||||||
|
| `feature-planning` | Structured workflow for new features | When implementing new features or significant functionality changes |
|
||||||
|
|
||||||
## Documentation Standards
|
## Documentation Standards
|
||||||
|
|
||||||
|
|||||||
0
docs/features/.gitkeep
Normal file
0
docs/features/.gitkeep
Normal file
131
docs/features/timer-breaks.md
Normal file
131
docs/features/timer-breaks.md
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
# Feature: Timer Breaks (Pause During Work)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Allow users to take breaks while a timer is running. When on break, elapsed time is frozen and break time is tracked. When resumed, break time accumulates and is subtracted from the displayed work time.
|
||||||
|
|
||||||
|
## User Experience
|
||||||
|
|
||||||
|
### Timer States
|
||||||
|
1. **Running** — normal state, elapsed time ticking
|
||||||
|
2. **On Break** — elapsed time frozen, break time ticking, Stop/Cancel buttons disabled
|
||||||
|
3. **Stopped** — no timer active
|
||||||
|
|
||||||
|
### UI Changes (TimerWidget)
|
||||||
|
- Add a **"Break"** button (amber, `Pause` icon) next to Stop when timer is running
|
||||||
|
- When on break:
|
||||||
|
- Change pulsing dot color from red to amber
|
||||||
|
- Elapsed time frozen at net work time
|
||||||
|
- Show break time below: `Break: Xm XXs` (live-ticking)
|
||||||
|
- Replace "Break" button with **"Resume"** button (green, `Play` icon)
|
||||||
|
- **Disable** Stop and Cancel buttons (tooltip: "Resume before stopping")
|
||||||
|
|
||||||
|
### Duration Calculations
|
||||||
|
- **Work time (displayed):** `now - startTime - totalBreakSeconds`
|
||||||
|
- Where `totalBreakSeconds = (breakMinutes * 60) + (now - breakStart if on break)`
|
||||||
|
- When on break: frozen at `(breakStart - startTime - breakMinutes * 60)`
|
||||||
|
- **Break time (displayed):** `breakMinutes * 60 + (now - breakStart if on break)`
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
### 1. Database Schema (`backend/prisma/schema.prisma`)
|
||||||
|
Add two fields to `OngoingTimer`:
|
||||||
|
```prisma
|
||||||
|
model OngoingTimer {
|
||||||
|
// ... existing fields ...
|
||||||
|
breakMinutes Int @default(0) @map("break_minutes")
|
||||||
|
breakStart DateTime? @map("break_start") @db.Timestamptz()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Run: `npx prisma migrate dev --name add_timer_break_fields`
|
||||||
|
|
||||||
|
### 2. Backend Service (`backend/src/services/timer.service.ts`)
|
||||||
|
|
||||||
|
**New method `startBreak(userId)`:**
|
||||||
|
- Get ongoing timer, throw `NotFoundError` if none
|
||||||
|
- Check `timer.breakStart` is null (not already on break), throw `BadRequestError` if on break
|
||||||
|
- Update: `breakStart = new Date()`
|
||||||
|
- Return updated timer
|
||||||
|
|
||||||
|
**New method `endBreak(userId)`:**
|
||||||
|
- Get ongoing timer, throw `NotFoundError` if none
|
||||||
|
- Check `timer.breakStart` is not null, throw `BadRequestError` if not on break
|
||||||
|
- Calculate additional break minutes: `Math.floor((now - breakStart) / 60000)`
|
||||||
|
- Update: `breakMinutes += additionalMinutes`, `breakStart = null`
|
||||||
|
- Return updated timer
|
||||||
|
|
||||||
|
**Modify `stop(userId)`:**
|
||||||
|
- Before creating time entry, check `timer.breakStart` is null — throw `BadRequestError("Cannot stop timer while on break")` if break is active
|
||||||
|
- When creating `TimeEntry`, set `breakMinutes: timer.breakMinutes`
|
||||||
|
|
||||||
|
**Modify `cancel(userId)`:**
|
||||||
|
- Check `timer.breakStart` is null — throw `BadRequestError("Cannot cancel timer while on break")` if break is active
|
||||||
|
|
||||||
|
### 3. Backend Routes (`backend/src/routes/timer.routes.ts`)
|
||||||
|
Add two new routes (both require auth, no body validation):
|
||||||
|
```
|
||||||
|
POST /api/timer/break → timerService.startBreak(userId)
|
||||||
|
POST /api/timer/resume → timerService.endBreak(userId)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. MCP Tools (`backend/src/routes/mcp.routes.ts`)
|
||||||
|
Add two MCP tools: `pause_timer` and `resume_timer`.
|
||||||
|
|
||||||
|
### 5. Frontend Types (`frontend/src/types/index.ts`)
|
||||||
|
Update `OngoingTimer` interface:
|
||||||
|
```typescript
|
||||||
|
export interface OngoingTimer {
|
||||||
|
// ... existing fields ...
|
||||||
|
breakMinutes: number;
|
||||||
|
breakStart: string | null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Frontend API (`frontend/src/api/timer.ts`)
|
||||||
|
Add two methods:
|
||||||
|
```typescript
|
||||||
|
startBreak: async (): Promise<OngoingTimer> => { ... }
|
||||||
|
endBreak: async (): Promise<OngoingTimer> => { ... }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Frontend TimerContext (`frontend/src/contexts/TimerContext.tsx`)
|
||||||
|
- Add `breakSeconds` state (live-updating, similar to `elapsedSeconds`)
|
||||||
|
- Expose `isOnBreak` derived boolean (`ongoingTimer?.breakStart !== null`)
|
||||||
|
- Update elapsed time calculation:
|
||||||
|
- Running: `(now - startTime) - (breakMinutes * 60) - (now - breakStart if on break)`
|
||||||
|
- On break: `(breakStart - startTime) - (breakMinutes * 60)` (frozen)
|
||||||
|
- Break seconds: `(breakMinutes * 60) + (now - breakStart if on break)`
|
||||||
|
- Add `startBreak()` and `endBreak()` callbacks
|
||||||
|
- Expose `breakSeconds` and `isOnBreak` in context value
|
||||||
|
|
||||||
|
### 8. Frontend TimerWidget (`frontend/src/components/TimerWidget.tsx`)
|
||||||
|
- Import `Pause` icon from lucide-react
|
||||||
|
- Add Break/Resume button between project selector and Stop button
|
||||||
|
- Show break time display when `breakSeconds > 0` or `isOnBreak`
|
||||||
|
- Change dot color to amber when on break
|
||||||
|
- Disable Stop/Cancel when on break with tooltip
|
||||||
|
|
||||||
|
## Files to Modify (in order)
|
||||||
|
|
||||||
|
| # | File | Change |
|
||||||
|
|---|------|--------|
|
||||||
|
| 1 | `backend/prisma/schema.prisma` | Add `breakMinutes`, `breakStart` to `OngoingTimer` |
|
||||||
|
| 2 | `backend/src/services/timer.service.ts` | Add `startBreak()`, `endBreak()`, modify `stop()` and `cancel()` |
|
||||||
|
| 3 | `backend/src/routes/timer.routes.ts` | Add `/break` and `/resume` routes |
|
||||||
|
| 4 | `backend/src/routes/mcp.routes.ts` | Add `pause_timer` and `resume_timer` MCP tools |
|
||||||
|
| 5 | `frontend/src/types/index.ts` | Add `breakMinutes`, `breakStart` to `OngoingTimer` |
|
||||||
|
| 6 | `frontend/src/api/timer.ts` | Add `startBreak()`, `endBreak()` API methods |
|
||||||
|
| 7 | `frontend/src/contexts/TimerContext.tsx` | Add break state, `breakSeconds`, `isOnBreak`, break methods |
|
||||||
|
| 8 | `frontend/src/components/TimerWidget.tsx` | Add break UI (button, display, disabled states) |
|
||||||
|
|
||||||
|
## Edge Cases
|
||||||
|
- Break start must be after timer start (always true since break is clicked after start)
|
||||||
|
- Break duration naturally cannot exceed work duration (breakStart > startTime)
|
||||||
|
- On stop: reject if break is active (user must resume first)
|
||||||
|
- On cancel: reject if break is active (user must resume first)
|
||||||
|
- Break minutes accumulate across multiple break/resume cycles
|
||||||
|
- Timer refetch (every 60s) will sync break state from server
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
- Run `npm run lint` in both `frontend/` and `backend/`
|
||||||
|
- Run `npm run build` in both `frontend/` and `backend/`
|
||||||
|
- Manual testing: start timer → break → verify elapsed frozen, break ticking → resume → verify break added to total → stop → verify time entry has correct breakMinutes
|
||||||
Reference in New Issue
Block a user