docs(workplans): write files for 4 pre-ADR-001 orphan workstreams
Resolves all orphan-workstream FAIL findings from validate_repo_adr.
The custodian domain now passes 47/47 checks (0 warn, 0 fail).
Files written:
CUST-WP-0001 custodian-agent-runtime (2 tasks: 1 done, 1 todo)
CUST-WP-0002 contribution-tracking-sbom (15 tasks, v0.5 scope
reductions annotated inline)
CUST-WP-0003 whi-kpi-card (9 tasks)
CUST-WP-0004 ep-td-tracking (10 tasks: 4 done, 6 todo)
All files cross-reference state_hub_workstream_id and
state_hub_task_id for future sync reconciliation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
69
workplans/CUST-WP-0001-custodian-agent-runtime.md
Normal file
69
workplans/CUST-WP-0001-custodian-agent-runtime.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
id: CUST-WP-0001
|
||||||
|
type: workplan
|
||||||
|
title: "Custodian Agent Runtime — Bootstrap"
|
||||||
|
domain: custodian
|
||||||
|
status: active
|
||||||
|
owner: custodian
|
||||||
|
topic_slug: custodian
|
||||||
|
state_hub_workstream_id: a2d9919d-62ec-49e7-9533-ba650757e70a
|
||||||
|
created: "2026-02-25"
|
||||||
|
updated: "2026-02-28"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Custodian Agent Runtime — Bootstrap
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Design and bootstrap the Custodian as an acting agent: a standalone
|
||||||
|
LLM-powered service that uses the State Hub as its coordination layer.
|
||||||
|
Distinct from the State Hub tooling itself.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The State Hub provides the read model and MCP interface. The Agent Runtime
|
||||||
|
is a separate concern: the loop, policy engine, and tool adapters that
|
||||||
|
make the Custodian an autonomous (or semi-autonomous) participant rather
|
||||||
|
than a passive data store.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Depends on: `markitect/llm-shared-library` (llm-connect) — must reach
|
||||||
|
stable installable state before implementation can begin.
|
||||||
|
Dependency resolved: llm-connect extracted and integrated (2026-02-27).
|
||||||
|
- Depends on: `railiance/phase-0-operational-baseline` — agent runtime
|
||||||
|
deployment requires a stable, backed-up server environment.
|
||||||
|
- state_hub_dep_ids:
|
||||||
|
- a46f5838-e489-434f-b7ee-996c2fdd81ad (llm-shared-library)
|
||||||
|
- 7f0d9856-9561-4404-96f0-91e8eb79feca (phase-0-operational-baseline)
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
### T1 — Bootstrap blocked: awaiting markitect/llm-shared-library
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0001-T01
|
||||||
|
state_hub_task_id: ac42e548-10bf-4851-94e2-c8d35876f2f9
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
All implementation tasks for the agent runtime were blocked until
|
||||||
|
llm-connect was extracted as a standalone installable package from
|
||||||
|
markitect. Resolved 2026-02-27: llm-connect integrated in state-hub as
|
||||||
|
editable dependency; markitect llm-check smoke test green.
|
||||||
|
|
||||||
|
### T2 — Define agent architecture and capability scope
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0001-T02
|
||||||
|
state_hub_task_id: 9a9297cd-bd3c-409c-8384-6f06cfc6faa2
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
Decide the Custodian agent's primary loop: what is the core OODA cycle?
|
||||||
|
What tools does it need beyond the State Hub MCP? Where does it live —
|
||||||
|
new repo or `runtime/` in the-custodian? Produce an architecture sketch
|
||||||
|
covering: entry point, LLM integration (via llm-connect), tool manifest,
|
||||||
|
state-hub interaction pattern, and deployment target.
|
||||||
294
workplans/CUST-WP-0002-contribution-tracking-sbom.md
Normal file
294
workplans/CUST-WP-0002-contribution-tracking-sbom.md
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
---
|
||||||
|
id: CUST-WP-0002
|
||||||
|
type: workplan
|
||||||
|
title: "State Hub v0.3 — Contribution Tracking & SBOM"
|
||||||
|
domain: custodian
|
||||||
|
status: active
|
||||||
|
owner: custodian
|
||||||
|
topic_slug: custodian
|
||||||
|
state_hub_workstream_id: 2446400d-6d01-4679-a314-92af0601c608
|
||||||
|
created: "2026-02-26"
|
||||||
|
updated: "2026-02-28"
|
||||||
|
---
|
||||||
|
|
||||||
|
# State Hub v0.3 — Contribution Tracking & SBOM
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Establish the custodian as the central authority for cross-repo upstream
|
||||||
|
contribution management (bug reports, feature requests, extension points,
|
||||||
|
upstream PRs) and software supply-chain transparency (SBOM aggregation,
|
||||||
|
licence governance).
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Three interconnected layers:
|
||||||
|
- **Layer 1 — Convention & Canon**: define contrib/ directory structure and
|
||||||
|
artifact types (BR, FR, EP, UPR) in markdown with typed YAML frontmatter.
|
||||||
|
- **Layer 2 — Schema & API**: DB tables for contributions, repos (deferred
|
||||||
|
to v0.5), and SBOM entries; FastAPI routers.
|
||||||
|
- **Layer 3 — MCP Tools & Dashboard**: tracking tools and Observable pages.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Depends on: `dynamic-domains-multi-repo` (v0.5, CUST-WP-0005).
|
||||||
|
Four tasks in this workplan (P2.2, P2.4, P3.2, P4.1) are reduced in
|
||||||
|
scope because v0.5 supersedes their original designs:
|
||||||
|
- `managed_repos` table → done by v0.5 P2.1
|
||||||
|
- `/repos/` API router → done by v0.5 P2.2
|
||||||
|
- `register_repo` MCP tool → done by v0.5 P3.1
|
||||||
|
- Base registration workflow → done by v0.5 P2.3
|
||||||
|
- state_hub_dep_id: 2033172d-2462-4253-acb7-cb64c7432480
|
||||||
|
|
||||||
|
## Phase 1 — Convention & Canon
|
||||||
|
|
||||||
|
### P1.1 — Write canon/standards/contribution-convention_v0.1.md
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T01
|
||||||
|
state_hub_task_id: c2d7df02-5f37-4c02-a418-fe7ab0050edc
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Define the master contrib/ convention: directory layout, artifact types
|
||||||
|
(BR/FR/EP/UPR), frontmatter schema per type, ID schemes (EP-<DOMAIN>-NNN
|
||||||
|
for EPs; date-prefixed slug for others), status lifecycle, and
|
||||||
|
relationship to state-hub. Authoritative reference for other repos.
|
||||||
|
|
||||||
|
### P1.2 — Create contrib/ templates for BR, FR, EP, UPR
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T02
|
||||||
|
state_hub_task_id: 5ef89639-950c-4d57-9578-6d0211edc2df
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Four Markdown template files under `canon/standards/contrib-templates/`:
|
||||||
|
`br-template.md`, `fr-template.md`, `ep-template.md`, `upr-template.md`.
|
||||||
|
Each has typed YAML frontmatter matching the schema in P1.1 plus a guided
|
||||||
|
prose skeleton.
|
||||||
|
|
||||||
|
### P1.3 — Store Observable Framework TOC sidebar UPR as first artifact
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T03
|
||||||
|
state_hub_task_id: e8251873-647c-4a4b-b283-298260b19c22
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `contrib/upstream-prs/2026-02-26--observablehq--framework--toc-sidebar-inject.md`
|
||||||
|
using the UPR template. Captures: summary of the `injectTocTop` utility,
|
||||||
|
motivation, link to local component, target upstream file, draft PR body.
|
||||||
|
Status: draft.
|
||||||
|
|
||||||
|
### P1.4 — Align Railiance EP convention docs with canon master spec
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T04
|
||||||
|
state_hub_task_id: 1c982457-de52-4fc1-a439-3bf3120bb5b6
|
||||||
|
status: todo
|
||||||
|
priority: low
|
||||||
|
```
|
||||||
|
|
||||||
|
The staged-promotion-lifecycle workstream defines EP-RAIL-NNN IDs and
|
||||||
|
inline doc markers. Review and update so the Railiance convention is a
|
||||||
|
proper instance of the custodian master spec, not a parallel one.
|
||||||
|
|
||||||
|
## Phase 2 — Schema & API
|
||||||
|
|
||||||
|
### P2.1 — Design and implement contributions DB table + migration
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T05
|
||||||
|
state_hub_task_id: c41d71bd-dc88-4201-bd9a-3f8a4eae4910
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `contributions` table: id (UUID PK), type (enum: br|fr|ep|upr),
|
||||||
|
target_org, target_repo, slug, title, status (enum:
|
||||||
|
draft|submitted|acknowledged|accepted|rejected|merged|withdrawn),
|
||||||
|
body_path (relative path to .md file), related_topic_id (nullable FK),
|
||||||
|
related_workstream_id (nullable FK), submitted_at, resolved_at, notes,
|
||||||
|
created_at, updated_at. Alembic migration.
|
||||||
|
|
||||||
|
### P2.2 — sbom_entries table + migration (managed_repos deferred to v0.5)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T06
|
||||||
|
state_hub_task_id: 28c9bd38-05d8-4466-bff3-3ba4e3957635
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
SCOPE REDUCED — managed_repos superseded by v0.5 P2.1.
|
||||||
|
|
||||||
|
Do not create `managed_repos` here. After v0.5 P2.1 lands, add
|
||||||
|
`sbom_source` (text) and `last_sbom_at` (timestamp) columns to the
|
||||||
|
existing `managed_repos` table via an additive migration.
|
||||||
|
|
||||||
|
Then create `sbom_entries` table: id (UUID PK), repo_id (FK
|
||||||
|
managed_repos), package_name, package_version, ecosystem, license_spdx
|
||||||
|
(nullable), is_direct (bool), is_dev (bool), snapshot_at (timestamp —
|
||||||
|
new ingest replaces old entries for that repo), created_at.
|
||||||
|
|
||||||
|
Prerequisite: v0.5 P2.1 (managed_repos table) must be complete.
|
||||||
|
|
||||||
|
### P2.3 — Implement /contributions/ router (CRUD + status patch)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T07
|
||||||
|
state_hub_task_id: ee1cd17c-6dbd-4321-bb72-4499147c4837
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
FastAPI router: GET list (filter by type, status, target_repo), POST
|
||||||
|
create, GET by id, PATCH status (validates lifecycle transitions), soft
|
||||||
|
delete (sets status=withdrawn). Schemas: `ContributionCreate`,
|
||||||
|
`ContributionRead`, `ContributionStatusPatch`. Add
|
||||||
|
`contribution_counts` to `/state/summary`.
|
||||||
|
|
||||||
|
### P2.4 — Implement /sbom/ router (basic /repos/ endpoints implemented by v0.5)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T08
|
||||||
|
state_hub_task_id: 25f7ab5c-69d8-41d7-a108-38380eb1f3a9
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
SCOPE REDUCED — /repos/ superseded by v0.5 P2.2.
|
||||||
|
|
||||||
|
This task covers the `/sbom/` router only:
|
||||||
|
- `POST /sbom/ingest` — accept repo_slug + list of package entries;
|
||||||
|
replace existing snapshot for that repo.
|
||||||
|
- `GET /sbom/` — aggregated view across all repos, grouped by license_spdx.
|
||||||
|
- `GET /sbom/{repo_slug}/` — single-repo SBOM.
|
||||||
|
- `GET /sbom/report/licences/` — counts and repo lists per SPDX identifier,
|
||||||
|
flagging copyleft (GPL/AGPL/LGPL).
|
||||||
|
- Add `licence_risk_count` to `/state/summary`.
|
||||||
|
|
||||||
|
Prerequisite: v0.5 P2.1 (managed_repos) and P2.2 (sbom_entries) must
|
||||||
|
be complete.
|
||||||
|
|
||||||
|
### P2.5 — Write make ingest-sbom tooling (pyproject + package.json parsers)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T09
|
||||||
|
state_hub_task_id: edcf9b02-8177-4abc-b133-d303cc7ea19d
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
`scripts/ingest_sbom.py`: parses `uv.lock` (Python deps with licence
|
||||||
|
metadata), `package-lock.json` / `yarn.lock` (Node deps); outputs
|
||||||
|
normalised list; POSTs to `/sbom/ingest/`. Makefile target:
|
||||||
|
`make ingest-sbom REPO=<slug>`. Composable into `make seed`.
|
||||||
|
|
||||||
|
## Phase 3 — MCP Tools & Dashboard
|
||||||
|
|
||||||
|
### P3.1 — New MCP tools: register_contribution, update_contribution_status, get_contributions
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T10
|
||||||
|
state_hub_task_id: 51b2999b-a9c7-4871-8ef8-f5c927ac2454
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
- `register_contribution(type, target_org, target_repo, title, body_path,
|
||||||
|
related_workstream_id?, notes?)` → ContributionRead
|
||||||
|
- `update_contribution_status(contribution_id, status, notes?)` →
|
||||||
|
ContributionRead
|
||||||
|
- `get_contributions(type?, status?, target_repo?)` → list
|
||||||
|
- Add `state://contributions` resource.
|
||||||
|
|
||||||
|
### P3.2 — New MCP tools: ingest_sbom, get_licence_report (register_repo implemented by v0.5)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T11
|
||||||
|
state_hub_task_id: 20c5c2ae-7758-42cc-885c-a886957e44c2
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
SCOPE REDUCED — register_repo superseded by v0.5 P3.1.
|
||||||
|
|
||||||
|
- `ingest_sbom(repo_slug: str, lockfile_path: str)` — calls
|
||||||
|
`scripts/ingest_sbom.py`, POSTs result to `/sbom/ingest/`.
|
||||||
|
- `get_licence_report()` — returns licence groups with copyleft flag from
|
||||||
|
`/sbom/report/licences/`.
|
||||||
|
- Add resources: `state://sbom/aggregated`, `state://sbom/{repo_slug}`.
|
||||||
|
|
||||||
|
Prerequisite: v0.5 P3.1 (register_repo tool) and P2.4 (/sbom/ router)
|
||||||
|
must be complete.
|
||||||
|
|
||||||
|
### P3.3 — Dashboard: contributions.md page
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T12
|
||||||
|
state_hub_task_id: 1eb13411-b2da-4d0d-8fe2-e926d029c50f
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
New Observable Framework page. Layout: filter bar (type, status,
|
||||||
|
target_repo), status Kanban columns
|
||||||
|
(draft → submitted → acknowledged → accepted/rejected/merged), count KPIs
|
||||||
|
per type. Chart: contribution velocity over time (cumulative, same period
|
||||||
|
selector as decisions page). Apply `injectTocTop` for page-level KPI.
|
||||||
|
|
||||||
|
### P3.4 — Dashboard: sbom.md page
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T13
|
||||||
|
state_hub_task_id: 1267f313-1bf3-4059-8276-bfefcd9f6aed
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
New Observable Framework page. Aggregated dependency table: package,
|
||||||
|
version, licence, repos using it, direct/dev flags. Licence summary donut
|
||||||
|
chart (MIT vs Apache-2.0 vs GPL family vs other). Copyleft risk section
|
||||||
|
(red highlight for GPL/AGPL/LGPL in direct prod deps). Per-repo
|
||||||
|
drill-down accordion. Register in `observablehq.config.js`.
|
||||||
|
|
||||||
|
### P3.5 — Update index.md overview to surface contribution and SBOM health
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T14
|
||||||
|
state_hub_task_id: abab0022-d3a4-45ef-a7e1-e0e7c05d295f
|
||||||
|
status: todo
|
||||||
|
priority: low
|
||||||
|
```
|
||||||
|
|
||||||
|
Add contribution counts KPI card (total, by type, any needing follow-up).
|
||||||
|
Add licence risk indicator (green if no copyleft in direct prod deps, red
|
||||||
|
otherwise). Uses `/state/summary` fields added in P2.3 and P2.4.
|
||||||
|
|
||||||
|
## Phase 4 — Repo Integration Tooling
|
||||||
|
|
||||||
|
### P4.1 — Add sbom_source prompt + ingest-sbom step to registration workflow (base workflow by v0.5)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0002-T15
|
||||||
|
state_hub_task_id: 47987720-23db-4465-861b-1f93bb1bb391
|
||||||
|
status: todo
|
||||||
|
priority: low
|
||||||
|
```
|
||||||
|
|
||||||
|
SCOPE REDUCED — base registration workflow superseded by v0.5 P2.3.
|
||||||
|
|
||||||
|
SBOM-specific additions to the workflow:
|
||||||
|
1. Extend the `add-repo` command to prompt for `ecosystem` and
|
||||||
|
`sbom_source` (path or URL to lockfile).
|
||||||
|
2. Optionally run `make ingest-sbom REPO=<slug>` automatically at end of
|
||||||
|
registration.
|
||||||
|
3. Update `project_claude_md.template` to document the contrib/ convention,
|
||||||
|
SBOM MCP tools, and `make ingest-sbom` target.
|
||||||
|
|
||||||
|
Prerequisite: v0.5 P2.3 (updated registration workflow) must be complete.
|
||||||
186
workplans/CUST-WP-0003-whi-kpi-card.md
Normal file
186
workplans/CUST-WP-0003-whi-kpi-card.md
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
---
|
||||||
|
id: CUST-WP-0003
|
||||||
|
type: workplan
|
||||||
|
title: "State Hub v0.4 — Workstream Health Index (WHI) KPI Card"
|
||||||
|
domain: custodian
|
||||||
|
status: active
|
||||||
|
owner: custodian
|
||||||
|
topic_slug: custodian
|
||||||
|
state_hub_workstream_id: 9cc32158-2f5c-4ef6-9713-aacce4623d5e
|
||||||
|
created: "2026-02-26"
|
||||||
|
updated: "2026-02-28"
|
||||||
|
---
|
||||||
|
|
||||||
|
# State Hub v0.4 — Workstream Health Index (WHI) KPI Card
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Implement the Workstream Health Index (WHI) — a composite structural-health
|
||||||
|
KPI — as a live card injected into the TOC sidebar of the Workstreams
|
||||||
|
dashboard page. All six metrics are computable client-side from data
|
||||||
|
already fetched by `workstreams.md`; no API or schema changes required.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
The WHI formula and metric definitions are specified in
|
||||||
|
`state-hub/dashboard/src/docs/workstream-kpi.md`. This workplan covers
|
||||||
|
only the implementation of that spec as running dashboard code.
|
||||||
|
|
||||||
|
The six base metrics:
|
||||||
|
- **DD** — Dependency Density: edge count / open workstream count
|
||||||
|
- **BR** — Blocked Ratio: blocked workstreams / open count
|
||||||
|
- **SPR** — Single Point of Risk: max inbound edges / open count
|
||||||
|
- **PEP** — Progression Enablement Proportion: ready-to-start workstreams
|
||||||
|
- **CDDR** — Cross-Domain Dependency Ratio: cross-domain edges / total edges
|
||||||
|
- **CPI** — Cycle Penalty Indicator: 1 if any cycle detected, 0 otherwise
|
||||||
|
|
||||||
|
WHI formula: `0.30*(1-DDnorm) + 0.25*(1-BR) + 0.15*(1-SPR) + 0.20*PEP + 0.10*(1-CDDR)`
|
||||||
|
CPI penalty: `WHI = WHI * 0.5` if CPI=1.
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
### P1 — Verify dependency edge fields in open_workstreams
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T01
|
||||||
|
state_hub_task_id: 243646e0-b77a-41e7-ac51-82c5828e63d2
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirm that `summary.open_workstreams[].depends_on[]` and `blocks[]`
|
||||||
|
each carry `workstream_id`, `workstream_slug`, and `workstream_title`.
|
||||||
|
Verify these fields are sufficient to build a complete directed dependency
|
||||||
|
graph client-side without additional API calls. (Already verified during
|
||||||
|
workplan design — open_workstreams is the confirmed data source.)
|
||||||
|
|
||||||
|
### P2.1 — Build directed dependency graph from openWs + completedIds
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T02
|
||||||
|
state_hub_task_id: 6dbef71f-d2d7-44ee-abb8-279dbaeec505
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
In `workstreams.md`: derive `completedIds = new Set` of IDs of workstreams
|
||||||
|
with status completed. Build an adjacency list: for each entry in openWs,
|
||||||
|
map workstream id → array of `depends_on[].workstream_id`. Build reverse
|
||||||
|
map (prerequisite id → list of dependent ids) for SPR computation. Also
|
||||||
|
build `idToDomain` map from `data[]` for CDDR.
|
||||||
|
|
||||||
|
### P2.2 — Implement DFS cycle detection (CPI)
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T03
|
||||||
|
state_hub_task_id: f0d5c107-6029-4ad0-af00-645d35ce7db0
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Implement a DFS-based topological sort over the dependency adjacency list.
|
||||||
|
Detect back edges using visited / inStack colour sets. Return `CPI = 1`
|
||||||
|
if any cycle found, `CPI = 0` otherwise. Only nodes in openWs participate
|
||||||
|
(completed/archived workstreams excluded). Edge case: isolated nodes (no
|
||||||
|
deps, no dependents) are valid and never form cycles.
|
||||||
|
|
||||||
|
### P2.3 — Compute DD, BR, SPR, PEP, CDDR
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T04
|
||||||
|
state_hub_task_id: 6da60567-cc46-4a32-9855-b07bafe2faeb
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the graph from P2.1:
|
||||||
|
- `DD`: totalEdges / openCount, where totalEdges = openWs.flatMap(w=>w.depends_on).length
|
||||||
|
- `BR`: openWs.filter(w=>w.status==="blocked").length / openCount
|
||||||
|
- `SPR`: max inbound-edge count across prerequisite workstreams in openWs / openCount
|
||||||
|
- `PEP`: openWs.filter(w=>active && all depends_on are in completedIds).length / openCount
|
||||||
|
- `CDDR`: crossDomainEdges / totalEdges (edge with different domain endpoints); 0 if no edges
|
||||||
|
|
||||||
|
### P2.4 — WHI formula: normalisation + CPI penalty
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T05
|
||||||
|
state_hub_task_id: 29b2dbbd-5d60-49b6-ae84-3dbf22167df7
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Implement the weighted aggregation:
|
||||||
|
```
|
||||||
|
DDnorm = min(1, DD / 1.0) // DD_critical = 1.0
|
||||||
|
WHI = 0.30*(1-DDnorm) + 0.25*(1-BR) + 0.15*(1-SPR) + 0.20*PEP + 0.10*(1-CDDR)
|
||||||
|
if CPI === 1: WHI = WHI * 0.5
|
||||||
|
```
|
||||||
|
Clamp to [0, 1]. Return `{whi, dd, ddNorm, br, spr, pep, cddr, cpi, openCount, edgeCount}`.
|
||||||
|
Factor into `computeWHI(nodes, edges, idToDomain)` for reuse in per-domain scope.
|
||||||
|
|
||||||
|
### P2.5 — Per-domain WHI breakdown
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T06
|
||||||
|
state_hub_task_id: 8ce5ef74-5eb8-4259-9b11-dde13bf84a89
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
For each domain present in openWs, compute a domain-scoped WHI:
|
||||||
|
- `domainNodes = openWs.filter(w => idToDomain[w.id] === domain)`
|
||||||
|
- `domainEdges = domainNodes.flatMap(w => w.depends_on.filter(d => idToDomain[d.workstream_id] === domain))`
|
||||||
|
- `result = computeWHI(domainNodes, domainEdges, idToDomain)`
|
||||||
|
|
||||||
|
Store as `[{domain, whi, br, pep, cpi, openCount}]`. Skip domains with
|
||||||
|
`openCount === 0`.
|
||||||
|
|
||||||
|
### P3 — WHI KPI card UI
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T07
|
||||||
|
state_hub_task_id: 91efba5c-3be2-4bfe-b5ef-1b261e9423f2
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the `_whiBox` element in `workstreams.md` (mirrors `_kpiBox` in
|
||||||
|
`decisions.md`):
|
||||||
|
- Card title: "Workstream Health"
|
||||||
|
- Main WHI value with health state label: GREEN ≥ 0.75 / ORANGE ≥ 0.50 / RED < 0.50
|
||||||
|
- Sub-metric rows for DD, BR, SPR, PEP, CDDR with individual warning colours
|
||||||
|
- Cycle alert row (red ⚠) when CPI=1
|
||||||
|
- Domain breakdown: compact rows with domain name + coloured score
|
||||||
|
- Empty state if openCount=0 or no edges
|
||||||
|
|
||||||
|
Inject via `injectTocTop("whi-kpi-box", _whiBox)`. Wire
|
||||||
|
`withDocHelp(_whiBox, "/docs/workstream-health-index")`.
|
||||||
|
|
||||||
|
### P4.1 — Create src/docs/workstream-health-index.md
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T08
|
||||||
|
state_hub_task_id: 4c898472-e4ae-49a2-b6cd-7aa1a3c7604a
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
Reference documentation for the WHI KPI card. Cover: purpose, all six
|
||||||
|
metrics (formula + interpretation), WHI aggregation formula with CPI
|
||||||
|
penalty, DD normalisation, health state thresholds, domain breakdown,
|
||||||
|
cycle detection, and how to improve a poor score. Update
|
||||||
|
`workstream-kpi.md` to link to this doc.
|
||||||
|
|
||||||
|
### P4.2 — Wire withDocHelp and add to Reference nav
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0003-T09
|
||||||
|
state_hub_task_id: 20976663-7ac9-4909-8029-a479190f52ff
|
||||||
|
status: todo
|
||||||
|
priority: low
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirm `withDocHelp(_whiBox, "/docs/workstream-health-index")` is wired
|
||||||
|
(from P3). Add `{ name: "Workstream Health", path: "/docs/workstream-health-index" }`
|
||||||
|
to the Reference pages array in `observablehq.config.js`. Verify
|
||||||
|
Reference nav renders correctly in `npm run dev`.
|
||||||
157
workplans/CUST-WP-0004-ep-td-tracking.md
Normal file
157
workplans/CUST-WP-0004-ep-td-tracking.md
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
---
|
||||||
|
id: CUST-WP-0004
|
||||||
|
type: workplan
|
||||||
|
title: "Extension Points & Technical Debt Tracking"
|
||||||
|
domain: custodian
|
||||||
|
status: active
|
||||||
|
owner: custodian
|
||||||
|
topic_slug: custodian
|
||||||
|
state_hub_workstream_id: e84ecd70-b276-4a93-a298-1ef1299b7c22
|
||||||
|
created: "2026-02-27"
|
||||||
|
updated: "2026-02-28"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Extension Points & Technical Debt Tracking
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Adds structured tracking for extension points (known future enhancement
|
||||||
|
opportunities) and technical debt (known quality compromises) across all
|
||||||
|
project domains.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Phase 1 (infrastructure) is complete: DB tables (`extension_points`,
|
||||||
|
`technical_debt`), API routers, MCP tools, and dashboard pages are live
|
||||||
|
as of commit `2bf9523` (2026-02-27). Phase 2 populates the catalogue per
|
||||||
|
domain. Phase 3 triages and resolves high-priority items.
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
### P1.1 — DB schema and API routers for EP and TD
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T01
|
||||||
|
state_hub_task_id: 539da477-b9ad-4e0b-a8a1-deab4afe9bc7
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Created `extension_points` and `technical_debt` tables (migration
|
||||||
|
`a3f1c2d4e5b6`). FastAPI routers at `/extension-points/` and
|
||||||
|
`/technical-debt/` with full CRUD and soft-delete (status-based).
|
||||||
|
|
||||||
|
### P1.2 — MCP tools for EP and TD registration
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T02
|
||||||
|
state_hub_task_id: a35fa615-13a3-4168-9e25-98edbd8411da
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Added 6 MCP tools to `server.py`: `register_extension_point`,
|
||||||
|
`list_extension_points`, `update_ep_status`, `register_technical_debt`,
|
||||||
|
`list_technical_debt`, `update_td_status`. Each write tool emits a
|
||||||
|
progress event.
|
||||||
|
|
||||||
|
### P1.3 — Dashboard pages for EP and TD
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T03
|
||||||
|
state_hub_task_id: cd392ee9-9b65-48cb-8337-9fbe546ea9c3
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Created `extensions.md` and `techdept.md` Observable pages with KPI
|
||||||
|
sidebar, charts (by type, by severity/status), urgent items section, and
|
||||||
|
filterable card lists. Added to nav in `observablehq.config.js`.
|
||||||
|
|
||||||
|
### P2.1 — Catalogue technical debt in custodian repo
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T04
|
||||||
|
state_hub_task_id: 76aa3932-9a06-45ae-8836-d766eb61b755
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Automated assessment of state-hub codebase. Registered 19 items
|
||||||
|
TD-CUST-001 to TD-CUST-019 (2 high, 10 medium, 7 low). Top priorities:
|
||||||
|
TD-CUST-001 (hard-coded API URL), TD-CUST-004 (no max limit on list
|
||||||
|
endpoints).
|
||||||
|
|
||||||
|
### P2.2 — Catalogue technical debt in railiance domain
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T05
|
||||||
|
state_hub_task_id: 00492d87-3bb7-4df9-8f12-a06da0307fbc
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
Assess railiance-bootstrap and related repos for technical debt.
|
||||||
|
Register findings as `TD-RAIL-xxx` items via the `/technical-debt/` API.
|
||||||
|
|
||||||
|
### P2.3 — Catalogue extension points in custodian repo
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T06
|
||||||
|
state_hub_task_id: 3069aa1d-3d5f-4b9f-be8b-dfa0ffe690fe
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
Identify and register extension points in the state-hub codebase as
|
||||||
|
`EP-CUST-xxx` items: API gaps, MCP tool gaps, dashboard gaps, schema
|
||||||
|
gaps, integration opportunities.
|
||||||
|
|
||||||
|
### P2.4 — Catalogue extension points in railiance domain
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T07
|
||||||
|
state_hub_task_id: 3a355a74-237f-4572-af05-683eceb32694
|
||||||
|
status: todo
|
||||||
|
priority: low
|
||||||
|
```
|
||||||
|
|
||||||
|
Identify and register extension points in railiance as `EP-RAIL-xxx` items.
|
||||||
|
|
||||||
|
### P3.1 — Address TD-CUST-001: extract API URL to config
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T08
|
||||||
|
state_hub_task_id: a9b5d39e-706b-4f71-8f5d-ce4f927b3e4c
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace hard-coded `const API = 'http://127.0.0.1:8000'` in all 7
|
||||||
|
dashboard pages with a shared config module or Observable environment
|
||||||
|
variable.
|
||||||
|
|
||||||
|
### P3.2 — Address TD-CUST-004: add max limit to list endpoints
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T09
|
||||||
|
state_hub_task_id: 7050eb96-964d-4c06-a9f5-6d49db6b9c98
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
Add `Pydantic Field(le=1000)` to `limit` parameters on all list
|
||||||
|
endpoints (progress, tasks, workstreams, decisions, extension_points,
|
||||||
|
technical_debt) to prevent memory exhaustion.
|
||||||
|
|
||||||
|
### P3.3 — Extract shared dashboard CSS to common stylesheet
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: CUST-WP-0004-T10
|
||||||
|
state_hub_task_id: c54553be-d947-4b8d-9c16-eb1a0e9ae3a0
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract `.kpi-infobox`, `.filter-bar` and related CSS from all dashboard
|
||||||
|
pages into a shared CSS file imported by each page. Addresses TD-CUST-003.
|
||||||
Reference in New Issue
Block a user