Files
headroom/openspec/config.yaml

239 lines
9.6 KiB
YAML

schema: spec-driven
# 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)
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