Complete workplan state model cleanup

This commit is contained in:
2026-05-18 01:31:36 +02:00
parent 98b2cb6484
commit d6522a9a40
42 changed files with 789 additions and 310 deletions

View File

@@ -4,6 +4,7 @@ title: Workstreams
```js
import {API, POLL_HEAVY, apiFetch, pollDelay, waitForVisible} from "./components/config.js";
import {WORKSTREAM_STATUSES, isClosedWorkstream, normalizeWorkstreamStatus} from "./components/workplan-status.js";
```
```js
@@ -27,6 +28,7 @@ const wsState = (async function*() {
const repoMap = Object.fromEntries(repoList.map(r => [r.id, r]));
data = wsList.map(w => ({
...w,
status: normalizeWorkstreamStatus(w.status),
domain: repoMap[w.repo_id]?.domain_slug ?? topicMap[w.topic_id]?.domain_slug ?? "unknown",
topic_title: topicMap[w.topic_id]?.title ?? "—",
}));
@@ -50,7 +52,7 @@ const _ts = wsState.ts;
```js
// ── Workstream Health Index (WHI) ────────────────────────────────────────────
const _idToDomain = Object.fromEntries(data.map(w => [w.id, w.domain ?? "unknown"]));
const _completedIds = new Set(data.filter(w => w.status === "completed" || w.status === "archived").map(w => w.id));
const _closedIds = new Set(data.filter(w => isClosedWorkstream(w.status)).map(w => w.id));
const _openCount = openWs.length;
const _allEdges = openWs.flatMap(w => w.depends_on.map(d => ({from: w.id, to: d.workstream_id})));
const _totalEdges = _allEdges.length;
@@ -64,15 +66,15 @@ const _BR = _openCount > 0 ? openWs.filter(w => w.status === "blocked").length /
// Single-Point Risk — max inbound edges on one incomplete workstream
const _inbound = {};
for (const e of _allEdges) {
if (!_completedIds.has(e.to)) _inbound[e.to] = (_inbound[e.to] ?? 0) + 1;
if (!_closedIds.has(e.to)) _inbound[e.to] = (_inbound[e.to] ?? 0) + 1;
}
const _SPR = _openCount > 0
? (Object.keys(_inbound).length > 0 ? Math.max(...Object.values(_inbound)) : 0) / _openCount
: 0;
// Parallel Execution Potential — active workstreams with all deps completed
// Parallel Execution Potential — ready/active workstreams with all deps finished
const _PEP = _openCount > 0
? openWs.filter(w => w.status === "active" && w.depends_on.every(d => _completedIds.has(d.workstream_id))).length / _openCount
? openWs.filter(w => ["ready", "active"].includes(normalizeWorkstreamStatus(w.status)) && w.depends_on.every(d => _closedIds.has(d.workstream_id))).length / _openCount
: 0;
// Cross-Domain Dependency Ratio
@@ -117,9 +119,9 @@ const _domainBreakdown = [...new Set(openWs.map(w => _idToDomain[w.id] ?? "unkno
const dd = oc > 0 ? te / oc : 0;
const br = oc > 0 ? nodes.filter(w => w.status === "blocked").length / oc : 0;
const pep = oc > 0 ? nodes.filter(w => {
if (w.status !== "active") return false;
if (!["ready", "active"].includes(normalizeWorkstreamStatus(w.status))) return false;
const intraDeps = w.depends_on.filter(d => (_idToDomain[d.workstream_id] ?? "unknown") === domain);
return intraDeps.every(d => _completedIds.has(d.workstream_id));
return intraDeps.every(d => _closedIds.has(d.workstream_id));
}).length / oc : 0;
const inb = {};
for (const e of edges) inb[e.to] = (inb[e.to] ?? 0) + 1;
@@ -222,7 +224,7 @@ const _domainsResp = await fetch(`${API}/domains/?status=active`).catch(() => nu
const DOMAINS = _domainsResp?.ok
? (await _domainsResp.json()).map(d => d.slug)
: ["custodian", "railiance", "markitect", "coulomb_social", "personhood", "foerster_capabilities"];
const STATUSES = ["active", "blocked", "completed", "archived"];
const STATUSES = WORKSTREAM_STATUSES;
// Create filter form without displaying — shown below the chart
const _filtersForm = Inputs.form(
@@ -357,7 +359,10 @@ if (wsWithDeps.length === 0) {
.dep-status { display: inline-block; font-size: 0.7rem; padding: 1px 6px; border-radius: 10px; margin-bottom: 0.5rem; text-transform: uppercase; }
.dep-status-active { background: #d4edda; color: #155724; }
.dep-status-blocked { background: #f8d7da; color: #721c24; }
.dep-status-completed { background: #cce5ff; color: #004085; }
.dep-status-proposed { background: #fef3c7; color: #92400e; }
.dep-status-ready { background: #e0f2fe; color: #075985; }
.dep-status-finished { background: #cce5ff; color: #004085; }
.dep-status-backlog { background: #f1f5f9; color: #64748b; }
.dep-row { font-size: 0.85rem; margin: 0.2rem 0 0 0.5rem; color: #444; }
.dep-on { color: #1a5276; }
.dep-block { color: #6e2f00; }