Files
2026-03-18 06:40:53 -05:00

282 lines
12 KiB
Markdown

# 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