--- title: Repositories --- ```js import {API} from "./components/config.js"; ``` ```js // Fast data — page renders as soon as this resolves (~200ms) let _repos = [], _domains = [], _sbom = [], _eps = [], _tds = [], _workstreams = []; try { [_repos, _domains, _sbom, _eps, _tds, _workstreams] = await Promise.all([ fetch(`${API}/repos/`).then(r => r.ok ? r.json() : []), fetch(`${API}/domains/`).then(r => r.ok ? r.json() : []), fetch(`${API}/sbom/`).then(r => r.ok ? r.json() : []), fetch(`${API}/extension-points/`).then(r => r.ok ? r.json() : []), fetch(`${API}/technical-debt/`).then(r => r.ok ? r.json() : []), fetch(`${API}/workplans/`).then(r => r.ok ? r.json() : []), ]); } catch {} ``` ```js // DoI data — lazy-loaded. Starts as [] so the page renders immediately. // When the fetch resolves (~6s), doiData updates and DoI badges appear. import {Mutable} from "observablehq:stdlib"; const doiData = Mutable([]); const doiLoading = Mutable(true); fetch(`${API}/repos/doi/summary`) .then(r => r.ok ? r.json() : []) .catch(() => []) .then(data => { doiData.value = data; doiLoading.value = false; }); ``` ```js const repos = _repos ?? []; const domains = _domains ?? []; const sbom = _sbom ?? []; const eps = _eps ?? []; const tds = _tds ?? []; const workstreams = _workstreams ?? []; const doi = doiData; // reactive — updates when lazy fetch completes // DoI lookups const doiBySlug = Object.fromEntries(doi.map(d => [d.repo_slug, d])); const DOI_TIER_ORDER = {none: 0, core: 1, standard: 2, full: 3}; const DOI_TIER_COLOR = {none: "#ef4444", core: "#f97316", standard: "#eab308", full: "#22c55e"}; const DOI_TIER_BG = {none: "#fef2f2", core: "#fff7ed", standard: "#fefce8", full: "#f0fdf4"}; const DOI_TIER_LABEL = {none: "None", core: "Core", standard: "Standard", full: "Full"}; // Lookups const domainById = Object.fromEntries(domains.map(d => [d.id, d])); const domainBySlug = Object.fromEntries(domains.map(d => [d.slug, d])); // Active "repo-integration-{slug}" workstreams — signals onboarding in progress const integratingBySlug = Object.fromEntries( workstreams .filter(w => w.status === "active" && w.slug?.startsWith("repo-integration-")) .map(w => [w.slug.replace("repo-integration-", ""), w]) ); // Per-repo SBOM stats (from sbom entries) const sbomByRepo = {}; for (const e of sbom) { if (!sbomByRepo[e.repo_id]) sbomByRepo[e.repo_id] = { count: 0, snapshot_at: e.snapshot_at }; sbomByRepo[e.repo_id].count++; } // Per-domain counts const epByDomain = {}; const tdByDomain = {}; const contribByDomain = {}; // EPs are domain-scoped for (const ep of eps) { if (!ep.status || ep.status === "open" || ep.status === "in_progress") { epByDomain[ep.domain] = (epByDomain[ep.domain] ?? 0) + 1; } } for (const td of tds) { if (!td.status || td.status === "open" || td.status === "in_progress") { tdByDomain[td.domain] = (tdByDomain[td.domain] ?? 0) + 1; } } // Contributions: try to map via workstream → topic → domain (not available here; skip for now) // Use domain slug from contributions' related_workstream if available — fallback: count by type only // Build enriched repo rows const repoRows = repos .filter(r => r.status === "active") .map(r => { const domain = domainById[r.domain_id]; const domSlug = domain?.slug ?? "—"; const domName = domain?.name ?? "—"; const sbomData = sbomByRepo[r.id]; const hasSbom = !!sbomData || !!r.last_sbom_at; const pkgCount = sbomData?.count ?? 0; const lastScan = r.last_sbom_at ? new Date(r.last_sbom_at).toLocaleDateString() : (sbomData?.snapshot_at ? new Date(sbomData.snapshot_at).toLocaleDateString() : null); const integrating = !!integratingBySlug[r.slug]; const doiEntry = doiBySlug[r.slug] ?? null; const doiTier = doiEntry?.tier ?? "none"; return { _id: r.id, _domSlug: domSlug, _hasSbom: hasSbom, _integrating: integrating, _doiTier: doiTier, repo: r.slug, domain: domName, status: integrating ? "⚙ integrating" : "ready", path: r.local_path ?? "—", sbom: hasSbom ? `✓ ${lastScan}` : "⚠ not ingested", pkgs: pkgCount || (hasSbom ? "—" : 0), eps: epByDomain[domSlug] ?? 0, tds: tdByDomain[domSlug] ?? 0, }; }) .sort((a, b) => a._domSlug.localeCompare(b._domSlug) || a.repo.localeCompare(b.repo)); const gapCount = repoRows.filter(r => !r._hasSbom).length; const coveredCount = repoRows.filter(r => r._hasSbom).length; const integratingCount = repoRows.filter(r => r._integrating).length; const doiFullCount = repoRows.filter(r => r._doiTier === "full").length; const doiNoneCount = repoRows.filter(r => r._doiTier === "none").length; ``` # Repositories ```js import {withDocHelp} from "./components/doc-overlay.js"; const _h1 = document.querySelector("#observablehq-main h1"); if (_h1) { _h1.style.position = "relative"; withDocHelp(_h1, "/docs/repos"); } display(html`
DoI tiers: None → Core → Standard → Full — Definition of Integrated policy ↗ ${doiLoading ? html` Loading DoI tiers… ` : html`✓ DoI tiers loaded`}
`); ``` ```js // Summary KPIs display(html`${repoRows.length}
${new Set(repoRows.map(r => r._domSlug)).size}
${coveredCount} / ${repoRows.length}
${gapCount}
${gapCount === 0 ? "✓ All repos covered" : `⚠ ${gapCount} repo(s) not ingested`}${doiLoading ? html`` : `${doiFullCount} / ${repoRows.length}`}
${doiLoading ? "Loading…" : doiNoneCount > 0 ? `⚠ ${doiNoneCount} at tier None` : "✓ All pass Core tier"}No repos registered. Run make add-repo DOMAIN=<slug> SLUG=<slug> NAME="..." PATH=/path.
| Repo | DoI Tier | Status | SBOM | Packages | Local path |
|---|---|---|---|---|---|
${r.repo} |
${_doiBadge(r._doiTier)} | ${r._integrating ? html`` : html`ready`} | ${r._hasSbom ? r.sbom : _sbomGap()} | ${r.pkgs} | ${r.path} |
Register an accessible git working copy and write the starter files for the selected agent profile.
Paste the absolute path when the checkout is on the State Hub host or exposed via ops-bridge.
git clone <remote-url> /path/to/repo
The path must be visible from the State Hub API host, either as a local checkout or through an ops-bridge-exposed path.
Codex -> AGENTS.md + SCOPE.md Claude Code -> CLAUDE.md + .claude/rules/
The API keeps this as an agent profile so future native coding agents can get their own onboarding templates without changing the repo model.
scripts/register_project.sh <domain> /path/to/repo --codex
Use the Add Repo form above for the automatic path. The script verifies the domain, writes agent instructions, registers the repo, records host_paths for this machine, and logs a progress event.
Open the repo in the chosen coding agent, complete the generated TODO stubs, then use the Repositories and DoI views to track integration gaps.