feat(atlas): Phase B — data-driven /api/atlas.json, CI stage generated from cd.yml
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Successful in 1s

The atlas no longer hand-maintains its content. Authored data lives in one place
(internal/atlas/atlas.json); the Go layer overlays sourced facts and serves the
result at /api/atlas.json; the frontend fetches + renders (inline arrays kept only
as an offline fallback). First generated source: the CI/CD stage's nodes are parsed
from the repo's own .gitea/workflows/cd.yml — so the viz shows the pipeline that
actually runs (guard/check/build/deploy), dropping the aspirational var-go/oath-gate
node that isn't wired yet. That's the point: it can't drift from the real pipeline.

New internal/atlas package (JobsFromWorkflow, Build) built test-first. Adds
gopkg.in/yaml.v3 (justified: parsing the workflow YAML; stdlib has no YAML).

Verified: go build/vet/lint(0)/test green; /api/atlas.json → 9 stages, CI = real
jobs; frontend renders from the fetch (screenshot).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 00:34:06 +02:00
co-authored by Claude Opus 4.8
parent c3fda9b26b
commit a9c72d6ca8
12 changed files with 375 additions and 24 deletions
+33 -16
View File
@@ -114,7 +114,7 @@
<body>
<header>
<h1><b>CAD</b> Atlas · From Signal to Pod</h1>
<span class="sub mono">one human gate · everything up- and downstream is agents · <em>v0.3 static snapshot (→ live in Phase C)</em></span>
<span class="sub mono">one human gate · everything up- and downstream is agents · <em>v0.4 · data-driven (CI stage generated from cd.yml)</em></span>
<div class="controls">
<button id="replay"><span class="dot"></span> Replay</button>
<button id="slowmo">Slow-mo · <span id="slowState">off</span></button>
@@ -145,20 +145,22 @@
<footer class="mono">
CAD → CI → CD · intent→specify→dispatch · build→test→validate · deploy→ship.
Dashed violet = feedback bus (stage 08 → TELOS: deploy outcome scored vs originating goal).
Data: static inventory from <code>brain</code> (2026-07-19). Phase C swaps these arrays for live reads of
<code>assessor-loop</code> ledger · <code>session_log</code> · Gitea run API · Flux events.
Data served from <code>/api/atlas.json</code> (authored <code>atlas.json</code> + CI stage generated from the live <code>cd.yml</code>).
Phase C plugs in live reads of <code>assessor-loop</code> ledger · <code>session_log</code> · Gitea run API · Flux events.
</footer>
<script>
const SUBSTRATE=[
// Inline data is an offline FALLBACK. Authoritative data is fetched from
// /api/atlas.json (authored atlas.json + CI stage generated from the real cd.yml).
let SUBSTRATE=[
{n:"koala", k:"RTX 5070 · k3s control-plane · Gitea · LiteLLM :30401 · llama-swap :31234 · searxng"},
{n:"iguana", k:"M2 Ultra · Ollama / mlx"},
{n:"flamingo",k:"daily driver · ~/dev"},
{n:"piguard",k:"NGINX reverse-proxy · ntfy"},
];
const NS="Tailscale mesh · ns: ai-stack · supervisor(→brain) · gitea-mcp · infra-mcp · council";
let NS="Tailscale mesh · ns: ai-stack · supervisor(→brain) · gitea-mcp · infra-mcp · council";
const STAGES=[
let STAGES=[
{no:"STAGE 00",cls:"",title:"Signals",path:"→ mathias/signals",nodes:[
{t:"Applied AI Radar",d:"Daily Tier-1 + weekly Tier-2 deep pass. Verified-primary bar (paper/benchmark/code/named-lab).",tags:["cron · daily/weekly","→ signals #126+"]},
{t:"Manual capture",d:"claude.ai strategic drop · brain capture tool.",tags:["ad-hoc"]},
@@ -200,14 +202,17 @@ const STAGES=[
]},
];
const sub=document.getElementById('substrate');
SUBSTRATE.forEach(h=>{const el=document.createElement('div');el.className='host';
el.innerHTML=`<b>${h.n}</b><span class="k mono">${h.k}</span>`;sub.appendChild(el);});
const mesh=document.createElement('div');mesh.className='host mesh mono';mesh.textContent=NS;sub.appendChild(mesh);
const track=document.getElementById('track');
const stageEls=[];
STAGES.forEach(s=>{
let stageEls=[];
function renderAtlas(){
const sub=document.getElementById('substrate');
sub.querySelectorAll('.host').forEach(el=>el.remove());
SUBSTRATE.forEach(h=>{const el=document.createElement('div');el.className='host';
el.innerHTML=`<b>${h.n}</b><span class="k mono">${h.k}</span>`;sub.appendChild(el);});
const mesh=document.createElement('div');mesh.className='host mesh mono';mesh.textContent=NS;sub.appendChild(mesh);
stageEls=[];
track.querySelectorAll('.stage').forEach(el=>el.remove());
STAGES.forEach(s=>{
const st=document.createElement('div');st.className='stage '+s.cls;
let h=`<div class="no mono">${s.no}</div><h2>${s.title}</h2><div class="path mono">${s.path||''}</div>`;
s.nodes.forEach(n=>{
@@ -219,7 +224,8 @@ STAGES.forEach(s=>{
h+=`<div class="node ${n.cls||''}">${inner}</div>`;
});
st.innerHTML=h;track.appendChild(st);stageEls.push(st);
});
});
}
/* ---- geometry ---- */
const spine=document.getElementById('spine'), spinePath=document.getElementById('spinePath'),
@@ -265,8 +271,19 @@ document.getElementById('replay').onclick=replay;
document.getElementById('slowmo').onclick=e=>{slow=!slow;e.currentTarget.classList.toggle('on',slow);
document.getElementById('slowState').textContent=slow?'on':'off';replay();};
window.addEventListener('resize',()=>{clearTimeout(window._r);window._r=setTimeout(replay,150);});
window.addEventListener('load',replay);
build();
async function init(){
try{
const r=await fetch('/api/atlas.json');
if(!r.ok) throw new Error('atlas.json '+r.status);
const data=await r.json();
if(Array.isArray(data.substrate)) SUBSTRATE=data.substrate;
if(typeof data.ns==='string') NS=data.ns;
if(Array.isArray(data.stages)) STAGES=data.stages;
}catch(e){ console.warn('atlas: using inline fallback —',e); }
renderAtlas();
replay();
}
window.addEventListener('load',init);
</script>
</body>
</html>