# req-planner A standalone requirements management tool with interactive graph visualization, hierarchical decomposition, quality gates, and code traceability. Designed as a general-purpose planning tool that can connect to any repository. ## What It Does req-planner lets you decompose high-level project goals into traceable, testable requirements organized as a directed acyclic graph (DAG). Each requirement is a card that can be drilled down from abstract pillars to code-level leaf nodes, with quality validation at every level. ### Core Concepts - **Pillars** — Top-level project goals (e.g., "MIDI Signal Path") - **Requirements** — Functional requirements under a pillar - **Sub-requirements** — Decomposed pieces of a requirement - **Leaves** — Code-level items with test specs and implementation - **Planning** — Planning-phase nodes (larger green-tinted cards) Each node carries: - Acceptance criteria (what it must do) - Test specification (GIVEN/WHEN/THEN format) - Test and implementation code snippets - Target file paths for code export - Quality gate status - Gitea issue integration fields ### Quality Gates (TMCS) Every requirement is validated against four gates: | Gate | Type | Rule | |------|------|------| | **T**raceable | Auto | Has a parent requirement and description | | **M**easurable | Toggle | Forced false without test specification; user can toggle when test spec exists | | **C**onsistent | Toggle | User asserts no contradictions with sibling requirements | | **S**ingle-purpose | Toggle | User asserts requirement serves exactly one concern | **T** is auto-calculated from the requirement's structure. **M**, **C**, and **S** are user-set toggles — click the badge in the detail panel to flip them. **M** is enforced: if a node has no test specification, measurable is always false regardless of the toggle. Visual indicators on graph nodes: - **Red dot** — Fewer than 2 quality gates pass - **Orange dot** — 2 of 3 gates pass - **Green dot** — All quality gates pass ### Requirement Status Flow Requirements follow a lifecycle: `idea` → `draft` → `todo` → `in_progress` → `done` - **idea** (purple) — ideas backlog; things you're thinking about but haven't committed to building - **draft** (gray) — being defined, not yet ready for work - **todo** (blue) — defined and ready to implement - **in_progress** (yellow) — actively being worked on - **done** (green) — completed ### Satisfaction Links Requirements can declare they "also satisfy" other requirements beyond their parent. This creates cross-cutting traceability: - **Also Satisfies** — outgoing links: "this requirement also contributes to requirement X" - **Satisfied By** — incoming links: "requirement Y also contributes to this one" These appear as purple dashed edges in the graph. ## Features ### Interactive Graph View (`/graph`) The main view renders the requirement tree as a Cytoscape.js DAG with dagre layout. **Semantic zoom** — node detail changes continuously with zoom level: | Zoom Range | What You See | |------------|--------------| | 0 - 0.3 | Dots with ID only | | 0.3 - 0.6 | Cards with ID, title, child count | | 0.6 - 1.0 | Cards with TMCS quality badges | | 1.0+ | Expanded cards with AC count and status | **Mouse interactions:** | Action | Behavior | |--------|----------| | Click node | Select node, open detail panel, highlight paths to root (parent-child + satisfaction links) | | Shift+Click | Highlight parent-child path to root only (no satisfaction links) | | Alt+Click (Win) / Option+Click (Mac) | Highlight only "also satisfies" links for a node | | Ctrl+Click (Win) / Cmd+Click (Mac) | Focus mode: show node, direct children, and paths to roots | | Ctrl+Shift+Click (Win) / Cmd+Shift+Click (Mac) | Deep focus: show node, all descendants to leaves, and paths to roots | | Right-click | Highlight entire subtree downward | | Click background | Exit focus mode or close detail panel | | Drag node | Reposition (saved across sessions) | **Keyboard shortcuts:** | Key | Action | |-----|--------| | `+` / `=` | Zoom in | | `-` | Zoom out | | `0` | Fit graph to screen | | Ctrl+Z (Win) / Cmd+Z (Mac) | Undo last canvas action | | Esc | Exit focus mode | **Canvas undo** tracks all interactions: node clicks, focus/exit, right-click highlights, and node drags. Up to 20 states are kept in the undo stack. **Persistence:** - Node positions saved to localStorage — drag nodes to rearrange and they stay put across reloads - Viewport (zoom + pan) persisted across sessions - Selected node and panel state restored on reload - Re-layout button resets to auto-calculated dagre positions **Named layouts:** - Save the current graph layout (node positions + viewport) with a name and description - Load any saved layout from the toolbar dropdown - Set a default layout that auto-loads on startup - Manage layouts: load, set default, or delete **Edge rendering:** - Parent-child edges: solid gray lines, width scales up when zoomed out - Satisfaction links: purple dashed lines with directional arrows - Path highlight: blue for parent-child, purple for satisfaction links ### Detail Panel A 420px side panel for viewing and editing a requirement: - Inline editing for title, description, priority, status, phase, node type - Acceptance criteria and test spec (GIVEN/WHEN/THEN) editors - Test code and implementation code blocks (monospace) - Quality gate badges — click M/C/S to toggle, T is auto-calculated - Quality validation with error/warning display - Child requirements list with add-child form (auto-generates IDs) - Parent card link — click to navigate to parent - **Also Satisfies** section — manage outgoing satisfaction links with typeahead search - **Satisfied By** section — view incoming links, click to navigate - **Edit history** — collapsible section showing all versions with timestamps and change summaries - Click a version to see field-level diffs (changed fields highlighted) - Restore any previous version (creates a new version with "Restored from version N" note) - Gitea issue badge with link (when issue number is set) - Delete with cascade confirmation ### Dashboard (`/dashboard`) Statistics overview with: - Node counts by type (pillars, requirements, sub-requirements, leaves, planning) - Test coverage percentage - Breakdown by status and priority - Quality gates pass/fail ratio ### Authentication - Password-based login with JWT tokens (24-hour expiry) - Protected routes with auth guard - Token auto-injected into API requests via HTTP interceptor - Configurable password via `REQ_PLANNER_PASSWORD` environment variable ## Architecture ``` req-planner/ ├── backend/ FastAPI + SQLAlchemy + SQLite │ └── app/ │ ├── main.py App entry, CORS config, router registration │ ├── auth.py JWT authentication │ ├── database.py SQLite connection (data/planner.db) │ ├── models.py ORM models (RequirementNode, CrossPillarLink, │ │ Project, RequirementHistory, GraphLayout) │ ├── schemas.py Pydantic request/response schemas │ ├── quality.py TMCS validation logic │ └── routers/ │ ├── requirements.py CRUD + tree + validation + history endpoints │ ├── links.py Cross-pillar link management │ ├── projects.py Project CRUD │ ├── stats.py Aggregated statistics │ └── layouts.py Named graph layout CRUD ├── frontend/ Angular 17 + Cytoscape.js │ └── src/app/ │ ├── core/ │ │ ├── guards/ Auth route guard │ │ ├── interceptors/ JWT token interceptor │ │ ├── models/ TypeScript interfaces │ │ └── services/ HTTP API client (requirements, auth) │ └── features/ │ ├── graph/ Interactive DAG visualization │ ├── detail/ Side panel editor with history │ ├── dashboard/ Statistics overview │ └── login/ Password login ├── data/ │ └── planner.db SQLite database (auto-created) └── docs/ └── MARKET-RESEARCH.md Competitive analysis ``` ## API Endpoints ### Requirements | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/requirements` | List requirements (filter by project_id, parent_id) | | GET | `/api/requirements/tree` | Tree structure for graph rendering | | GET | `/api/requirements/{id}` | Single requirement with children | | POST | `/api/requirements` | Create requirement | | PUT | `/api/requirements/{id}` | Update requirement | | DELETE | `/api/requirements/{id}` | Delete requirement (cascades to children) | | PATCH | `/api/requirements/{id}/status` | Update status only | | POST | `/api/requirements/{id}/validate` | Run TMCS quality gates | | GET | `/api/requirements/{id}/children` | List direct children | ### Edit History | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/requirements/{id}/history` | List all versions (newest first) | | GET | `/api/requirements/{id}/history/{version}` | Get specific version snapshot | | POST | `/api/requirements/{id}/history/{version}/restore` | Restore to previous version | ### Satisfaction Links | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/links` | List links (optional `node_id` filter) | | POST | `/api/links` | Create satisfaction link | | DELETE | `/api/links/{source_id}/{target_id}` | Delete link | ### Graph Layouts | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/layouts` | List saved layouts (optional `project_id` filter) | | GET | `/api/layouts/{id}` | Get layout with positions and viewport | | POST | `/api/layouts` | Save current layout | | PUT | `/api/layouts/{id}` | Update layout | | DELETE | `/api/layouts/{id}` | Delete layout | ### Other | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/api/health` | Health check | | POST | `/api/auth/login` | Login, returns JWT token | | GET/POST/DELETE | `/api/projects` | Project management | | GET | `/api/stats` | Aggregated statistics | Interactive API docs available at `http://localhost:8100/docs` (Swagger UI). ## Tech Stack **Backend:** - Python 3.12+, FastAPI, SQLAlchemy 2.0, SQLite - Pydantic 2.10+ for validation - python-jose for JWT tokens - Uvicorn ASGI server **Frontend:** - Angular 17 (standalone components, new control flow syntax) - Cytoscape.js + cytoscape-dagre for graph rendering - RxJS for reactive data flow - SCSS with dark theme (GitHub-inspired palette) - OnPush change detection, lazy-loaded routes ## Running Locally ### Backend ```bash cd backend uv sync # or: pip install -e ".[dev]" uvicorn app.main:app --reload --port 8100 ``` ### Frontend ```bash cd frontend npm install ng serve # runs on http://localhost:4200 ``` The frontend proxies API requests to `http://localhost:8100/api` via `proxy.conf.json`. ## Database SQLite database at `data/planner.db`, auto-created on first backend startup. Five tables: - **requirement_nodes** — hierarchical requirements with quality flags, code metadata, and timestamps - **cross_pillar_links** — many-to-many satisfaction links between requirements - **projects** — project containers with optional repo path/URL - **requirement_history** — versioned snapshots of requirement edits - **graph_layouts** — named layout snapshots with node positions and viewport state