--- title: Dependencies --- ```js import {API, POLL_HEAVY, apiFetch, pollDelay, waitForVisible} from "./components/config.js"; import {normalizeWorkstreamStatus} from "./components/workplan-status.js"; ``` ```js // Fetch workstreams + topics + dep edges; /state/deps replaces the heavier // /state/summary which was only used here to extract dependency edges. const depState = (async function*() { let failures = 0; while (true) { let wsMap = {}, edges = [], ok = false; try { const [rw, rto, rr, rd] = await Promise.all([ apiFetch("/workplans/"), apiFetch("/topics/"), apiFetch("/repos/"), apiFetch("/state/deps"), ]); ok = rw.ok && rto.ok && rr.ok && rd.ok; if (ok) { const [wsList, topicList, repoList, depsList] = await Promise.all([ rw.json(), rto.json(), rr.json(), rd.json(), ]); const topicMap = Object.fromEntries(topicList.map(t => [t.id, t])); const repoMap = Object.fromEntries(repoList.map(r => [r.id, r])); wsMap = Object.fromEntries(wsList.map(w => [w.id, { ...w, status: normalizeWorkstreamStatus(w.status), // Prefer repo→domain (GEMS primary); fall back to topic→domain domain: repoMap[w.repo_id]?.domain_slug ?? topicMap[w.topic_id]?.domain_slug ?? "unknown", }])); for (const ow of depsList) { for (const depStub of (ow.depends_on ?? [])) { edges.push({from_id: ow.id, to_id: depStub}); } } } } catch {} failures = ok ? 0 : failures + 1; yield {wsMap, edges, ok, ts: new Date()}; await waitForVisible(pollDelay({ok, base: POLL_HEAVY, failures})); } })(); ``` ```js const wsMap = depState.wsMap ?? {}; const edges = depState.edges ?? []; const _ok = depState.ok ?? false; const _ts = depState.ts; ``` # Dependencies ```js import {injectTocTop} from "./components/toc-sidebar.js"; import {withDocHelp} from "./components/doc-overlay.js"; // ── KPI sidebar card ────────────────────────────────────────────────────────── const _wsWithDeps = new Set([...edges.map(e => e.from_id), ...edges.map(e => e.to_id)]); const _kpiBox = html`
Dependencies
edges
${edges.length}
workstreams involved
${_wsWithDeps.size}
`; const _liveEl = html`
${_ok ? `Live · updated ${_ts?.toLocaleTimeString()}` : html`Offline — run: make api`}
`; const _h1 = document.querySelector("#observablehq-main h1"); if (_h1) { _h1.style.position = "relative"; withDocHelp(_h1, "/docs/dependencies"); } injectTocTop("dep-kpi-box", _kpiBox); injectTocTop("live-indicator", _liveEl); ``` Directed edges between open workstreams. An edge **A → B** means A cannot fully proceed until B reaches a satisfactory state. ```js if (edges.length === 0) { display(html`

No dependency edges registered.

`); } else { const rows = edges.map(e => { const from = wsMap[e.from_id]; const to = wsMap[e.to_id]; return { from_domain: from?.domain ?? "—", from_title: from?.title ?? e.from_id, from_status: from?.status ?? "—", to_domain: to?.domain ?? "—", to_title: to?.title ?? e.to_id, to_status: to?.status ?? "—", }; }); display(html`${rows.map(r => html` `)}
Depends-on domain Depends-on workstream Blocked-by domain Blocked-by workstream Status
${r.from_domain} ${r.from_title} ${r.to_domain} ${r.to_title} ${r.to_status}
`); } ```