strategy change to TDD
This commit is contained in:
@@ -1,20 +1,238 @@
|
||||
schema: spec-driven
|
||||
|
||||
# Project context (optional)
|
||||
# This is shown to AI when creating artifacts.
|
||||
# Add your tech stack, conventions, style guides, domain knowledge, etc.
|
||||
# Example:
|
||||
# context: |
|
||||
# Tech stack: TypeScript, React, Node.js
|
||||
# We use conventional commits
|
||||
# Domain: e-commerce platform
|
||||
# Project context - shown to AI when creating artifacts
|
||||
# This provides essential context about the Headroom project
|
||||
techstack: |
|
||||
## Backend (Laravel API)
|
||||
- **Framework:** Laravel 12 (latest) with PHP 8.4
|
||||
- **Database:** PostgreSQL (latest, Alpine container)
|
||||
- **Caching:** Redis (latest, Alpine container) - query + response caching
|
||||
- **Authentication:** JWT (tymon/jwt-auth package)
|
||||
- **API Design:** REST with Laravel API Resources
|
||||
- **API Documentation:** Laravel Scribe (auto-generates SwaggerUI)
|
||||
- **Testing:** PHPUnit (unit) + Pest (feature)
|
||||
- **Code Style:** PSR-12, Laravel conventions
|
||||
- **Container:** Docker (port 3000)
|
||||
|
||||
## Frontend (SvelteKit)
|
||||
- **Framework:** SvelteKit (latest) with Svelte 5
|
||||
- **Styling:** Tailwind CSS + DaisyUI
|
||||
- **Charts:** Recharts
|
||||
- **Tables:** TanStack Table (React Table for Svelte)
|
||||
- **Forms:** Superforms + Zod + SvelteKit Form Actions
|
||||
- **State Management:** Svelte stores (minimal - UI state only)
|
||||
- **HTTP Client:** Native fetch (no Axios)
|
||||
- **Testing:** Vitest (unit) + Playwright (E2E)
|
||||
- **Container:** Docker (port 5173)
|
||||
|
||||
## Infrastructure
|
||||
- **Local Dev:** Docker Compose with code-mounted volumes (hot reload)
|
||||
- **Reverse Proxy:** Nginx Proxy Manager (existing)
|
||||
- **Database Volume:** Mounted to ./data/postgres
|
||||
- **Cache Volume:** Mounted to ./data/redis
|
||||
- **Secrets:** .env files (all environments)
|
||||
|
||||
# Per-artifact rules (optional)
|
||||
# Add custom rules for specific artifacts.
|
||||
# Example:
|
||||
# rules:
|
||||
# proposal:
|
||||
# - Keep proposals under 500 words
|
||||
# - Always include a "Non-goals" section
|
||||
# tasks:
|
||||
# - Break tasks into chunks of max 2 hours
|
||||
conventions: |
|
||||
## Code Style Standards
|
||||
|
||||
### Backend (Laravel)
|
||||
- Follow PSR-12 coding standards
|
||||
- Use Laravel Pint for linting
|
||||
- Use PHPStan (level 5+) for static analysis
|
||||
- Use Laravel conventions for naming (camelCase methods, snake_case DB columns)
|
||||
- Use API Resources for consistent JSON responses
|
||||
- Use Form Requests for validation
|
||||
- Use Policies for authorization
|
||||
- Use UUIDs for primary keys (prevents ID enumeration)
|
||||
|
||||
### Frontend (SvelteKit)
|
||||
- Use Prettier for formatting
|
||||
- Use ESLint with Svelte plugin
|
||||
- Use TypeScript strict mode
|
||||
- Use SvelteKit file-based routing conventions
|
||||
- Use $lib alias for imports from src/lib
|
||||
- Use Zod schemas for validation (shared between frontend and API contracts)
|
||||
|
||||
## Git Conventions
|
||||
- **Branch naming:** `feature/opsx-<change-name>` for OpenSpec changes
|
||||
- **Commit format:**
|
||||
```
|
||||
[Type] Brief description (50 chars max)
|
||||
|
||||
Detailed explanation (optional, 72 char wrap)
|
||||
|
||||
Refs: openspec/changes/<change-name>
|
||||
```
|
||||
- **Types:** feat, fix, refactor, test, docs, chore
|
||||
- **Granular commits:** One fix = one commit
|
||||
|
||||
## API Conventions
|
||||
- RESTful endpoints with standard HTTP verbs
|
||||
- Response format: `{ "data": {}, "meta": {}, "links": {} }`
|
||||
- Error format: `{ "message": "...", "errors": {} }`
|
||||
- Cache keys pattern: `allocations:month:{YYYY-MM}`, `reports:forecast:{from}:{to}:{hash}`
|
||||
- TTL: 1 hour (allocations), 15 min (reports), 24 hours (master data)
|
||||
|
||||
development_strategy:
|
||||
approach: "Spec-Driven Development (SDD) + Test-Driven Development (TDD) Hybrid"
|
||||
description: |
|
||||
Every capability follows a 4-phase cycle:
|
||||
|
||||
## Phase 1: SPEC → TEST (Red Phase)
|
||||
- Read scenarios from specs/<capability>/spec.md
|
||||
- Write E2E tests (Playwright) - mark as test.fixme()
|
||||
- Write API tests (Pest) - mark as ->todo()
|
||||
- Write unit tests (Pest/Vitest) - mark as ->todo() or test.skip()
|
||||
- Write component tests (Vitest) - mark as test.skip()
|
||||
- Commit: "test(<capability>): Add pending tests for all scenarios"
|
||||
|
||||
## Phase 2: IMPLEMENT (Green Phase)
|
||||
- Remove skip/todo marker from one test
|
||||
- Write MINIMAL code to make it pass
|
||||
- Run test suite (npm run test, php artisan test, npx playwright test)
|
||||
- Commit when green: "feat(<capability>): Implement <scenario>"
|
||||
- Repeat for all scenarios
|
||||
|
||||
## Phase 3: REFACTOR (Clean Phase)
|
||||
- Review for code smells, duplication, performance
|
||||
- Refactor with confidence (tests guard against regression)
|
||||
- Run full test suite
|
||||
- Commit: "refactor(<capability>): <improvement description>"
|
||||
|
||||
## Phase 4: DOCUMENT
|
||||
- Generate API docs: php artisan scribe:generate
|
||||
- Verify all tests pass
|
||||
- Commit: "docs(<capability>): Update API documentation"
|
||||
|
||||
test_granularity: "Every spec scenario gets a test"
|
||||
test_organization: "Mirror current structure"
|
||||
test_types:
|
||||
- E2E: Playwright tests for critical user journeys
|
||||
- API: Pest Feature tests for all endpoints
|
||||
- Unit: Pest/Vitest for internal methods and business logic
|
||||
- Component: Vitest + Testing Library for Svelte components
|
||||
|
||||
pending_markers:
|
||||
php: "->todo()"
|
||||
playwright: "test.fixme()"
|
||||
vitest: "test.skip()"
|
||||
|
||||
test_naming:
|
||||
format: "Descriptive - mirror spec scenario intent"
|
||||
examples:
|
||||
- "authenticates user with valid credentials and issues JWT tokens"
|
||||
- "returns 401 when credentials are invalid"
|
||||
- "rotates refresh token on each refresh request"
|
||||
|
||||
coverage_target: ">70%"
|
||||
regression_strategy: "Every test is a regression test - run full suite on every PR"
|
||||
|
||||
scripts:
|
||||
backend:
|
||||
test: "pest"
|
||||
"test:unit": "pest --filter=Unit"
|
||||
"test:feature": "pest --filter=Feature"
|
||||
"test:coverage": "pest --coverage --min=70"
|
||||
"test:todo": "pest --filter=todo"
|
||||
lint: "pint"
|
||||
"lint:fix": "pint --fix"
|
||||
analyse: "phpstan analyse --level=5"
|
||||
docs: "scribe:generate"
|
||||
|
||||
frontend:
|
||||
test: "vitest run"
|
||||
"test:watch": "vitest"
|
||||
"test:ui": "vitest --ui"
|
||||
"test:e2e": "playwright test"
|
||||
"test:e2e:ui": "playwright test --ui"
|
||||
"test:all": "npm run test && npm run test:e2e"
|
||||
lint: "eslint ."
|
||||
"lint:fix": "eslint . --fix"
|
||||
format: "prettier --check ."
|
||||
"format:fix": "prettier --write ."
|
||||
|
||||
rules:
|
||||
# Project-level standing instructions (from decision-log.md)
|
||||
all_changes:
|
||||
- Every change must follow SDD+TDD: specs → pending tests → implementation → refactor
|
||||
- Every spec scenario must have corresponding tests (E2E, API, Unit, Component)
|
||||
- Pending tests must be committed before implementation (red phase)
|
||||
- Changes must end with code review for style, standards, and security
|
||||
- Verification (/opsx-verify) must check for uncovered code (code not tested)
|
||||
- Commits must be granular (one scenario = one commit)
|
||||
- Code coverage must be >70% (enforced in /opsx-verify)
|
||||
- All tests must pass before merge
|
||||
- Zero linting errors (Laravel Pint, ESLint, Prettier)
|
||||
- API documentation must be up-to-date (Scribe generation)
|
||||
|
||||
proposal:
|
||||
- Include clear Goals and Non-Goals sections
|
||||
- Reference the 4 personas (Superuser, Manager, Developer, Top Brass)
|
||||
- Align with monthly capacity planning workflow
|
||||
- Include data validation rules for any new entities
|
||||
|
||||
specs:
|
||||
- Document all validation rules explicitly
|
||||
- Include RBAC permissions for each operation
|
||||
- Define error scenarios and expected responses
|
||||
- Reference existing data model (team_members, projects, allocations, actuals)
|
||||
- Use YYYY-MM format for month references
|
||||
- Each scenario must be testable (clear GIVEN/WHEN/THEN)
|
||||
|
||||
design:
|
||||
- Include database schema changes (migrations needed)
|
||||
- Define API endpoints with request/response examples
|
||||
- Specify caching strategy (keys, TTL, invalidation rules)
|
||||
- Include UI/UX considerations for SvelteKit + DaisyUI
|
||||
- Document any new dependencies
|
||||
- Document test approach for each capability
|
||||
|
||||
tasks:
|
||||
- Organize by capability (not by layer)
|
||||
- Each capability has 4 phases: Test (Red) → Implement (Green) → Refactor → Document
|
||||
- Break implementation into individual scenarios
|
||||
- Include explicit test tasks (write pending, enable one by one)
|
||||
- Include API documentation updates as tasks
|
||||
- Order capabilities by dependency and business priority
|
||||
|
||||
# Domain knowledge
|
||||
context: |
|
||||
## Project Overview
|
||||
Headroom is a resource planning and capacity management tool for engineering managers.
|
||||
It replaces error-prone spreadsheets with structured capacity planning, resource allocation,
|
||||
and utilization tracking.
|
||||
|
||||
## Core Workflow (Monthly Cycle)
|
||||
1. **Capacity Planning** - Define team availability (holidays, PTO, working days)
|
||||
2. **Project Setup** - Track projects through lifecycle with approved estimates
|
||||
3. **Resource Allocation** - Allocate hours per person per project per month
|
||||
4. **Actuals Tracking** - Log actual hours worked and compare to planned
|
||||
|
||||
## Personas & Permissions
|
||||
- **Superuser:** Full access (setup, config, all projects, all teams)
|
||||
- **Manager:** Create/edit own projects, allocate own team, view all projects read-only
|
||||
- **Developer:** View own allocations, log own hours, view assigned projects
|
||||
- **Top Brass:** View all reports read-only (forecasts, utilization, costs)
|
||||
|
||||
## Key Business Rules
|
||||
- Availability: 0 (unavailable), 0.5 (half day), 1.0 (full day)
|
||||
- Project allocation indicators: GREEN (100% ±5%), YELLOW (<95%), RED (>105%)
|
||||
- Monthly aggregate for actuals (not daily)
|
||||
- Untracked resource for external team time (not billed)
|
||||
- Validation: Cannot allocate to "Done" or "Cancelled" projects
|
||||
|
||||
## Data Model Summary
|
||||
- team_members: id (UUID), name, role_id, hourly_rate, active
|
||||
- projects: id (UUID), code, title, status_id, type_id, approved_estimate, forecasted_effort (JSON)
|
||||
- allocations: id (UUID), project_id, team_member_id, month (YYYY-MM), allocated_hours
|
||||
- actuals: id (UUID), project_id, team_member_id, month (YYYY-MM), hours_logged
|
||||
- roles, project_statuses, project_types: Master data tables
|
||||
- holidays, ptos: Calendar data
|
||||
|
||||
## Deferred to Phase 2
|
||||
- Real-time notifications (WebSocket)
|
||||
- PDF/CSV exports
|
||||
- Background jobs (Laravel Queue)
|
||||
- Audit logging
|
||||
- Multi-tenancy
|
||||
- Time-tracking tool integration
|
||||
|
||||
Reference in New Issue
Block a user