feat(atlas): Phase B tail — live namespaces + trim inline fallback
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Successful in 1s

NamespaceSummary (test-first) renders the substrate ns line from live cluster
namespaces (system-filtered, sorted, capped). Handler now overlays both node
specs and the ns line via a single cached liveOverlay(). Removed the inline
SUBSTRATE/STAGES/NS data — /api/atlas.json is the single source; the page shows
an error banner on fetch failure instead of stale data.

GPU model naming intentionally NOT done: koala's node has no GPU product label
(only nvidia.com/gpu count), so "1× GPU" is the API's truth — naming the RTX 5070
would need GPU-feature-discovery, out of scope.

Verified: build/vet/lint(0)/test green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 00:56:40 +02:00
co-authored by Claude Opus 4.8
parent 39fd9b9adc
commit 633ba153f2
5 changed files with 131 additions and 77 deletions
+36
View File
@@ -2,6 +2,7 @@ package atlas_test
import (
"reflect"
"strings"
"testing"
"git.d-ma.be/mathias/cad-atlas/internal/atlas"
@@ -62,6 +63,41 @@ func TestMergeSubstrate_NoLiveReturnsAuthored(t *testing.T) {
}
}
func TestNamespaceSummary_FiltersSystemSortsAndJoins(t *testing.T) {
ns := []byte(`{"items":[
{"metadata":{"name":"gitea"}},
{"metadata":{"name":"kube-system"}},
{"metadata":{"name":"ai-stack"}},
{"metadata":{"name":"default"}},
{"metadata":{"name":"flux-system"}},
{"metadata":{"name":"brain"}}
]}`)
got, err := atlas.NamespaceSummary(ns)
if err != nil {
t.Fatalf("NamespaceSummary: %v", err)
}
if want := "ns: ai-stack · brain · gitea"; got != want {
t.Fatalf("summary = %q, want %q", got, want)
}
}
func TestNamespaceSummary_CapsWithMore(t *testing.T) {
var items []string
for i := 0; i < 15; i++ {
items = append(items, `{"metadata":{"name":"app`+string(rune('a'+i))+`"}}`)
}
ns := []byte(`{"items":[` + strings.Join(items, ",") + `]}`)
got, err := atlas.NamespaceSummary(ns)
if err != nil {
t.Fatalf("NamespaceSummary: %v", err)
}
if !strings.HasSuffix(got, "· +3 more") {
t.Fatalf("expected cap suffix, got %q", got)
}
}
func TestHostsFromNodes_ErrorsOnBadJSON(t *testing.T) {
if _, err := atlas.HostsFromNodes([]byte("{not json")); err == nil {
t.Fatal("expected error on bad JSON, got nil")