Phase C: the CI stage now shows the latest run's per-JOB status (Lint/Test,
Build, Deploy, …), each coloured by outcome, from the Gitea /actions/tasks
per-job entries — replacing the static cd.yml job-id list when live.
LatestRunJobs/RunNodes + RunSummary.State aggregate, all test-first.
Version: injected at build via -ldflags from `git describe --tags` (CI checkout
now fetch-depth:0 + --build-arg), served in /api/atlas.json, shown in the header.
No more hand-maintained version label drifting from the git tag.
Verified: build/vet/lint(0)/test green; version ldflag served correctly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>