--- title: Repos --- ```js import {API} from "./components/config.js"; ``` ```js 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}/workstreams/`).then(r => r.ok ? r.json() : []), ]); } catch {} ``` ```js const repos = _repos ?? []; const domains = _domains ?? []; const sbom = _sbom ?? []; const eps = _eps ?? []; const tds = _tds ?? []; const workstreams = _workstreams ?? []; // 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]; return { _id: r.id, _domSlug: domSlug, _hasSbom: hasSbom, _integrating: integrating, 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; ``` # Repos ```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"); } ``` ```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`}No repos registered. Run make add-repo DOMAIN=<slug> SLUG=<slug> NAME="..." PATH=/path.
| Repo | Status | SBOM | Packages | Local path |
|---|---|---|---|---|
${r.repo} |
${r._integrating ? html`` : html`ready`} | ${r._hasSbom ? r.sbom : _sbomGap()} | ${r.pkgs} | ${r.path} |
git clone <remote-url> /path/to/repo
cd /path/to/repo custodian register-project --domain <slug>
The custodian writes CLAUDE.custodian.md, registers the repo, and creates 4 onboarding tasks in the domain's topic.
cd /path/to/repo && claude
Once Claude starts, run /init to trigger the integration. The repo agent reads CLAUDE.custodian.md, picks up the onboarding tasks, and integrates autonomously.
The ⚙ integrating badge clears when the repo agent completes all 4 onboarding tasks and closes the workstream.