Add discipline strategy, WP sizing, Split-by-Discipline & dashboard

SOP config (Governance step) now sets project discipline policy:
- disciplines list, discipline strategy (single/multi/planner-choice),
  letter instance-suffix style, and a max-hours split threshold.

WP Creator becomes discipline-aware:
- discipline picker; selecting 2+ turns the flat scope into per-discipline
  scope sections, each with its own status (rolls up to least-advanced).
- "Split by Discipline" turns a multi-discipline WP into WP01A/B/C instances
  linked to a kept master (instanceOf/parentNumber/split/children).
- est-hours warning against the SOP split threshold.

New WP Dashboard (header button, home card, ?view=dashboard deep-link):
metrics, status/discipline breakdowns, a gating panel, and a filterable
board with view/edit/issue. Reads localStorage via an API-ready WPData
adapter; masters excluded from counts.

Backend: POST /api/wps/{id}/issue (enforces the constraint gate),
POST /api/wps/{id}/status, GET /api/wps/metrics; work_packages gains
parent_id + issued_at.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 13:29:41 -07:00
parent 108a690f66
commit d1f0901897
9 changed files with 671 additions and 44 deletions

View File

@@ -79,6 +79,56 @@ API. The API is already built and testable on its own.
- Firewall hardening (no external calls).
- Export/Import feedback on every surface.
- Phase 1 backend (API + schema) + NGINX proxy + deploy docs.
- **Discipline strategy, sizing, split & dashboard** (branch `feat/wp-discipline-split-dashboard`) — see below.
## Discipline strategy, WP sizing, Split-by-Discipline & Dashboard
Discipline came back — but as a *project policy* set in the SOP, not a fixed
field. The Governance step (SOP config, step 5) now also captures:
- **Disciplines** (default Mechanical / Electrical / Tech) — comma list.
- **Discipline strategy** (`governance.discMode`): `single` (one discipline per
WP), `multi` (one WP bundles disciplines, scope split per discipline), or
`choice` (planner decides per package — build big, split later).
- **Split threshold** (`governance.sizeHoursMax`) — the Creator warns when a
package's est. hours exceed it.
- `governance.instanceSuffix` = `letter` (instances get A/B/C suffixes).
In the **WP Creator** ([wp-creation-app.js](wp-creation-app.js)):
- A **Disciplines** picker (hidden unless the SOP defines disciplines). Pick 2+
and the single flat work-step list becomes **per-discipline scope sections**,
each with its own steps and its own status (e.g. *Issued — Electrical* while
*Mechanical* is still *In Progress*). Overall WP status rolls up to the
least-advanced discipline.
- **⎘ Split by Discipline** turns a multi-discipline package into one instance
per discipline: `WP01-…``WP01A` (Mech), `WP01B` (Elec), `WP01C` (Tech).
Each instance is a single-discipline WP linked to the master via `instanceOf`
/ `parentNumber`; the master is kept as a roll-up (`split:true`, `children:[]`).
- New per-WP fields on the saved object: `disciplines`, `scope` (`{discipline:
[steps]}`), `discStatus`, `instanceOf`, `instanceLabel`, `parentNumber`,
`split`, `children`.
The **Dashboard** (📊 in the Creator header; home card *Work Package Dashboard*;
deep-link `work-package-suite.html?view=dashboard` or `…?view=dashboard#…`):
metrics (total / release-ready / on-hold / overdue / est vs actual hrs),
breakdowns by status & discipline, a **gating panel** (what's blocking each
package), and a filterable board with **view / edit / issue** per package.
Masters are excluded from counts so split hours aren't double-counted.
Data source today is `localStorage` via the `WPData` adapter in
[wp-creation-app.js](wp-creation-app.js) — swap `list()`/`issue()`/`setStatus()`
to `fetch('/api/wps…')` in Phase 2 and the UI is unchanged.
**Backend** ([server/](server/)) gained the matching endpoints:
`POST /api/wps/{id}/issue` (refuses if constraints are open — the AWP gate),
`POST /api/wps/{id}/status`, and `GET /api/wps/metrics`. `work_packages` gained
`parent_id` and `issued_at` columns.
> **Migration caveat:** tables are still auto-created on startup, so the new
> `parent_id` / `issued_at` columns appear on a **fresh** DB only. Before there's
> real data this is fine; once there is, add Alembic (see open question #2) and
> migrate rather than relying on `create_all`.
**Pending — Phase 2: wire the front end to the API**
- SOP: on *SOP Complete*, `POST /api/sops`; on load, `GET /api/sops/latest` to hydrate the Creator (currently uses `localStorage` key `wp_suite_sop`).