282 lines
12 KiB
Markdown
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
|