Commit Graph
51 Commits
Author SHA1 Message Date
mathiasandClaude Sonnet 5 62955c998d fix(ci): authenticate go mod download against the private cad module
CD / Deploy via GitOps (push) Successful in 1s
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 6s
CD / var-go/oath (push) Skipped
CD / Build & Import (push) Successful in 7s
Build & Import (run #68) failed: mathias/cad is PRIVATE (unlike
mcp-chassis, the only other internal module a cad-* Dockerfile has fetched
so far, which is public) — 'go mod download' inside the Docker build had
no credential and died on 'terminal prompts disabled'.

Fix mirrors this repo's own existing GIT_ASKPASS pattern (cd.yml's
oathcandidate step, for the private swedsl dependency): a BuildKit secret
mount feeds a GIT_ASKPASS helper for the one RUN that needs it. The token
is never written to a persisted layer — the askpass script and its
reference to /run/secrets/gitea_token are created and removed within the
same RUN instruction. cd.yml writes the token to a file only for
build-image.sh's subprocess and passes it via BUILD_SECRETS (the script's
existing mechanism — 'the caller writes the secret to PATH itself').

Verified by running build-image.sh's actual buildctl invocation locally
against the real koala buildkitd (same daemon CI uses) with a real token —
'go mod download' completes in 1.9s, full build succeeds. Reproduced the
CI failure log before writing this fix, per house discipline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v0.7.0
2026-08-28 13:31:59 +02:00
mathiasandClaude Sonnet 5 97d0f56383 feat(stuck): stuck-state pipeline overlay (cad-atlas#11)
CD / Build & Import (push) Failing after 3s
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 5s
CD / var-go/oath (push) Skipped
CD / Deploy via GitOps (push) Skipped
Consumes mathias/cad#14's cad-stuck query directly — cad's app/domain
packages are public Go modules, so this reuses the exact tested
classification logic (import, not re-implementation) rather than
duplicating the taxonomy across two repos.

ApplyStuckOverlay (internal/atlas/stuck.go, fixture-tested) maps each
finding's category onto the existing 9-stage pipeline: armed_never_fired to
the human dispatch gate, claimed_never_ran/ceiling_hit/refire_loop/
near_attempt_cap to the one Execute stage (there is no separate Claim
stage), done_not_closed to the loop-back stage. Adds a StuckCount/
AwaitingCount badge per stage plus one Node per finding, linking out to the
underlying issue/comment — read-only, no controls, matching cad#14's own
constraint.

Two visual classes, kept deliberately distinct per the issue's own framing:
a coral 'N stuck' badge (needs intervention) vs a green 'N awaiting' badge
(a functioning control waiting on a human) — done_not_closed can never
render as a bottleneck.

Verified against the live estate: STAGE 05 shows 2 stuck (cobalt-dingo#30
ceiling_hit, cad-atlas#10 near_attempt_cap), STAGE 08 shows 5 awaiting
(cobalt-dingo #3/#7/#12/#16/#19 done_not_closed) — screenshotted via a
koala k3s Playwright job against a live-token server, matching cad#14's own
proven query output exactly.

go.mod: added git.d-ma.be/mathias/cad v0.10.0 (app/domain/adapters-gitearead
only — no mcp-chassis pulled in, that's only imported by cad's own cmd/cad).
Dockerfile: added the same GOPRIVATE/insteadOf fetch config mathias/cad's
own Dockerfile uses, now needed for this new private-module dependency.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 13:27:02 +02:00
mathiasandClaude Opus 5 4ab65a3b1b ci(deploy): refuse to patch a manifest with an empty IMAGE_TAG (infra#311)
CD / Detect unsubstituted template (push) Successful in 0s
CD / var-go/oath (push) Skipped
CD / Lint / Test / Vet (push) Successful in 6s
CD / Build & Import (push) Successful in 12s
CD / Deploy via GitOps (push) Successful in 1s
On 2026-08-25 a deploy job ran with an empty IMAGE_TAG, wrote
`image: localhost:5000/gitea-mcp:` into the infra repo and pushed it.
That is invalid YAML, so Flux failed the ENTIRE apps Kustomization --
every app stopped reconciling for about an hour, including three
unrelated deploys queued behind it.

This job's existing check could not catch it. It greps for
`image: <repo>:${IMAGE_TAG}` after the sed, and with IMAGE_TAG empty that
pattern matches the corrupted line itself, so the verification passes
because of the bug rather than despite it.

Asserting the input up front is the fix: an empty tag now fails the job
before anything is written, let alone committed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
2026-08-25 17:25:24 +02:00
mathiasandClaude Opus 5 c35c9699d4 ci: call the shared build-image script instead of an inline copy (infra#309)
CD / Detect unsubstituted template (push) Successful in 1s
CD / var-go/oath (push) Skipped
CD / Lint / Test / Vet (push) Successful in 6s
CD / Build & Import (push) Successful in 6s
CD / Deploy via GitOps (push) Successful in 0s
The buildctl/skopeo step here was one of nineteen near-identical copies
across the estate. That duplication is why moving them off rootless
buildah (infra#241) took eleven commits and then had to be rediscovered
in both repo templates and the gitea-ci skill.

The implementation now lives in .gitea/build-image.sh, byte-identical to
mathias/infra's ci-templates/build-image.sh and held there by a drift
gate. What used to be textual differences between copies -- labels, tags,
build-args, build target -- are environment inputs.

Behaviour is unchanged: same registry, same tags, same labels, same
buildctl-against-host-buildkitd path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
2026-08-25 11:29:53 +02:00
mathiasandClaude Opus 5 1fdd7d2e3d ci: build via buildctl instead of rootless buildah (infra#241)
CD / Detect unsubstituted template (push) Successful in 0s
CD / var-go/oath (push) Skipped
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Successful in 5s
CD / Deploy via GitOps (push) Successful in 0s
cad-atlas is the eighth repo to hit this wall, and it only surfaced now because
the build job had been unreachable behind a failing test job:

  error running container: from  creating container for
  [/bin/sh -c apk add --no-cache git]: : exec: no command

Root cause is the gitea-runner pod's securityContext, not this repo: it drops
ALL capabilities and sets allowPrivilegeEscalation:false, so newuidmap and
newgidmap cannot remap uids and rootless buildah gets a single non-remapped
mapping — not enough to set up a RUN step's user namespace.

buildctl talks to koala's host buildkitd over the socket the runner pod already
mounts, so the privileged layer work happens on the host and the pod keeps its
minimal posture. Same migration dispatch, tapir, brain-ingest-ntfy, parallax,
macro-research, cobalt-dingo, agentsquad (infra#233) and segment-embedder
(infra#243) have already made.

Note --opt build-arg:VERSION replaces buildah's --build-arg; the version label
this repo stamps into its binary depends on it, and dropping it silently would
have produced an image reporting the wrong version.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
2026-08-19 13:38:54 +02:00
mathiasandClaude Opus 5 99fb969d27 fix(test): stop asserting CI job names that the live overlay legitimately replaces
CD / Detect unsubstituted template (push) Successful in 0s
CD / var-go/oath (push) Skipped
CD / Lint / Test / Vet (push) Successful in 8s
CD / Build & Import (push) Failing after 2s
CD / Deploy via GitOps (push) Skipped
TestAtlasJSON_ServesAtlasWithGeneratedCIStage demanded STAGE 06 contain the
job names parsed from the embedded cd.yml (guard/check/build/deploy). But when
the forge is reachable, the handler deliberately REPLACES those nodes with the
latest real run — live per-job status, which is the whole point of that overlay.

So the test passed on a laptop with no route to Gitea and failed inside CI,
where the overlay works as designed:

  CI stage missing generated job "guard"
  (got map[Detect unsubstituted template:true Lint / Test / Vet:true
           ▶ run #62 · running:true])

It went red on a commit that touched only atlas.json — a test that depends on
whether the network is reachable will eventually fail on someone innocent, and
did.

The endpoint test now asserts the shape it serves — STAGE 06 exists, is
populated by whichever source won, and every node has a title. The
deterministic assertion already exists where it belongs, in
TestBuild_OverlaysCIStageNodesFromWorkflow, which feeds Build a fixed workflow
and never touches the network.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
2026-08-19 13:26:28 +02:00
mathiasandClaude Opus 5 294d9e2fc5 feat(atlas): stage 05 reflects the dispatch execution path
CD / Detect unsubstituted template (push) Successful in 1s
CD / var-go/oath (push) Skipped
CD / Lint / Test / Vet (push) Failing after 6s
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped
The atlas described stage 05 as agentsquad only, while headless single-issue
execution has run through mathias/dispatch for months and gained substantial
machinery in the 2026-08-17→19 session. Four nodes added, and the stage now
names both paths rather than one.

- dispatch · headless issue runs — the 1-minute poll over allow-listed repos,
  and the rule that CI-green on the pushed commit is the only done-signal.
- Two independent executors — claude or kimi (berget/Kimi-K2.6 via LiteLLM,
  EU-metered), routed per issue. Marked as a win, and as risk-bearing: it exists
  because a single provider's empty account stopped all CAD for six weeks.
- Fail-closed tool policy — one policy shared by both executors, writes confined
  to the checkout (symlink-resolved after an escape was found live), per-run
  turn and USD ceilings.
- Read-only PR review — status:review, no write tools, and the grounding rule
  that a review citing no changed file is dropped rather than published.

Deliberately NOT added: the risk-tiered agentic review with ntfy escalation.
That is designed (dispatch#48) and not built, and the atlas is a map of what
runs, not of what is planned.

Every node carries the plain-language layer the build test enforces.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
2026-08-19 12:00:17 +02:00
mathias 6967d12d1d feat(atlas): weight replay pacing on CI/CD stages by real job durations (#5)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 6s
CD / var-go/oath (push) Has been skipped
CD / Build & Import (push) Successful in 18s
CD / Deploy via GitOps (push) Has been skipped
TDD: Job.Seconds() + StageSeconds() derive real CI/CD dwell time from the
latest run's per-job created_at/updated_at (last job in pipeline order =
deploy/stage 07, everything before it = CI/stage 06).

Frontend: weightedSpineDist() redistributes the pixel-time-budget the
06/07 segments already had, splitting it by real CI:CD duration ratio
instead of raw pixel width. Falls back to the exact prior constant-speed
sweep when no run data is available (weights default to segment pixel
length) or when a job is skipped (0 duration) — no behavior change for
stages 00-05/08, which still have no live timing source (same gap as #5's
ledger item).

Verified: real duration values flow through /api/atlas.json (ci_duration_s:
18 observed against a real run), full page screenshot confirms no visual
regression.
v0.6.0
2026-07-20 23:22:53 +02:00
mathias b2761a4747 feat(gitea): surface mathias's own open Gitea issues on stage 03 (#4)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 5s
CD / var-go/oath (push) Has been skipped
CD / Build & Import (push) Successful in 12s
CD / Deploy via GitOps (push) Has been skipped
TDD: IssueNodes parses /repos/issues/search into stage nodes (title, repo
tag, clickable html_url). gitea.MyIssues() reads GITEA_TOKEN and skips
gracefully when unset, mirroring the existing liveOverlay fallback pattern.

Single-operator homelab, not per-visitor OAuth: a static read-only PAT
gates on "cleared Authentik forward-auth", not per-user token exchange —
see #4 discussion. GITEA_TOKEN provisioning in infra (ExternalSecret) is
a separate follow-up; without it the overlay is inert (no crash, just no
live nodes), so this ships safely ahead of that wiring.

Nodes with a url now render as clickable <a class="node"> instead of
<div class="node">.
v0.5.0
2026-07-20 23:04:44 +02:00
mathias 68ae01cb75 docs(project): drop stale branch-protection caveat, closed by #8
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 6s
CD / var-go/oath (push) Has been skipped
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Successful in 1s
2026-07-20 20:53:18 +00:00
mathias 2f5fca8513 docs(oath): mark S3 enforced now that branch protection requires var-go/oath (closes #8)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 6s
CD / var-go/oath (push) Has been skipped
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Successful in 1s
2026-07-20 20:51:35 +00:00
mathiasandClaude Sonnet 5 805b76d7c3 feat(oath): gate cad-atlas's own real candidate, not swedsl's toy stub (#8)
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Successful in 5s
CD / var-go/oath (push) Has been skipped
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Successful in 1s
oathcandidate/ is a separate Go module (mirrors swedsl's own
oath/testdata/selfcandidate pattern, keeping var-go's transitive deps
out of the deployed atlas binary) whose Build() parses the committed
.gitea/workflows/cd.yml and checks the "oath" job exists and invokes
cmd/vargo-gate. TDD: passes against the real file, fails closed on a
fixture missing the job.

Rewires the oath CI job to go-run vargo-gate from its real module path
(git.d-ma.be/mathias/swedsl/oath/cmd/vargo-gate@oath/v0.28.0, unblocked
by swedsl#35/#38) against VARGO_CANDIDATE_DIR=oathcandidate, instead of
checking out swedsl and gating its hardcoded toy fixture. Private-module
auth via a short-lived GIT_ASKPASS script (token never in argv, never
written to git config, matches act_runner's env:-block-with-secrets
gotcha).

Discovered along the way: var-go's parser needs single-line,
period-separated oath sentences with no Given/When/Then/And keyword
stripping — this repo's older oaths (incl. #1) used an unverified
multi-line keyword-prefixed style. #8's oath uses the proven format.

Still not required by branch protection pending a real-PR confirmation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 14:33:17 +02:00
mathiasandClaude Sonnet 5 346037c5c8 docs(oath): correct stale Executor framing after swedsl#27 closed
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 4s
CD / var-go/oath (push) Has been skipped
CD / Build & Import (push) Successful in 13s
CD / Deploy via GitOps (push) Has been skipped
swedsl#27 (var-go strategic-fit ADR) closed 2026-07-18 and killed the
Executor/Reviewer path entirely — var-go is gate-only by design, each
consuming repo supplies its own candidate. The real blocker for
enforcement here is swedsl/oath's non-importable module path
(swedsl#35), not a nonexistent Executor. Corrects PROJECT.md,
INCEPTION-OATH.md, and the cd.yml comment to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v0.4.1
2026-07-20 12:16:53 +02:00
mathiasandClaude Sonnet 5 f7a0281ca2 feat(ci): wire var-go/oath gate into CI (#1)
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Successful in 5s
CD / var-go/oath (push) Has been skipped
CD / Build & Import (push) Successful in 13s
CD / Deploy via GitOps (push) Has been skipped
Adds an oath job to cd.yml: on pull_request, checks out swedsl (the
vargo-gate source — its oath submodule isn't go-installable, module
path isn't a real import path) and runs cmd/vargo-gate against this
repo's linked issue, posting a var-go/oath commit status.

Deliberately NOT required by branch protection: vargo-gate's candidate
is still a hardcoded toy self-test registry (swedsl's own #9 fixture),
not a real PR-diff checker, so it fails closed against any real oath
until swedsl ships an Executor (swedsl#27). Requiring it now would
permanently block every cad-atlas PR. Disclosed in the CI config
comment, PROJECT.md, and docs/INCEPTION-OATH.md (honest-stub
discipline).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v0.4.0
2026-07-20 12:10:25 +02:00
mathiasandClaude Opus 4.8 60cc8894a2 feat(atlas): UX — overview rail + gate glyphs + pill reconcile (#3,#4,#5)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 12s
CD / Deploy via GitOps (push) Has been skipped
Closes the UX sprint's authored layer.
#3 Horizontal-scroll blindness → an always-visible "PIPELINE" overview rail:
9 colour-coded chips (00 Notice → 08 Learn) showing the whole shape at a glance,
each click-to-scroll to its stage. First-timers now see the arc + that more exists.
#4 Real gate glyph — 🔒 on the two checkpoint transitions (human @04, CI @06),
desktop spine + mobile rows.
#5 Reconcile legend with Plain: decorative node pills hidden in Plain, so colour
is reserved for live status (green/amber/coral) — exactly what the legend keys.
(#6 attached chips/grammar: the question-vs-statement label mix is meaningful —
decisions vs milestones — kept; SVG chip background skipped as low-value.)

New Stage.short (guarded by JSON validity via existing tests). build/vet/lint(0)/
test green; desktop Plain screenshot-verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.3.4
2026-07-20 10:46:08 +02:00
mathiasandClaude Opus 4.8 863c4c964b feat(atlas): UX — plain node titles + mobile transition rows (re-review #1,#2)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Has been skipped
Lap-2 review's top two findings:
#1 Node titles were still jargon (the lap-1 disease one level down). Every node
now has a plain_t ("var-go Oath" → "Definition of done", "Admission controller"
→ "Tamper-proof seal", …); Plain view leads with it and demotes the technical
name to a dim in-card subtitle — mirrors the stage-head pattern. plain_t on every
authored node is now guard-tested.
#2 Transition labels lived only in the SVG spine (display:none <820px) with a
hover-only rationale — invisible on phones. Added stacked-layout transition rows
(HTML, always-visible, full sentence, no hover) shown on mobile; desktop header
band scoped to ≥821px so mobile isn't stretched.

build/vet/lint(0)/test green; desktop Plain screenshot-verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.3.3
2026-07-20 10:14:53 +02:00
mathiasandClaude Opus 4.8 ac086b65b9 fix(atlas): UX polish — stage-06 plain nodes + shorter arrow labels (#7)
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Has been skipped
Stage 06 no longer renders bare in Plain: Build is now tolerant of a jobless/
absent workflow (keeps an authored plain placeholder instead of erroring), and
generated CI job nodes carry a plain hint. Shortened the two overlong transition
labels ("Order written, sealed, agent-ready" → "Sealed & agent-ready",
"Agents produced a change" → "Change proposed") so they stop clipping.

Build tolerance test-first. build/vet/lint(0)/test green; screenshot-verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.3.2
2026-07-20 09:46:42 +02:00
mathiasandClaude Opus 4.8 d992ca4a01 feat(atlas): UX polish — legend + feedback-bus honesty + Plain declutter (#6, #8)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Has been skipped
#6: always-visible legend keying the live-status colours (passed/running/failed),
the governance-gate colour, and the dashed feedback loop.
#8: the 08→TELOS loop is labelled "partly manual today" (honest, per PROJECT.md);
Plain view hides the jargon-dense substrate ribbon + technical footer, so a
non-technical viewer isn't shown koala/iguana/ns/assessor-loop proper nouns —
they remain in Technical view.

Frontend/CSS only; verified by screenshot. build/test/lint green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.3.1
2026-07-20 09:40:46 +02:00
mathiasandClaude Opus 4.8 5048450b79 feat(atlas): UX sprint — progressive disclosure (Plain default + transitions)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Successful in 18s
CD / Deploy via GitOps (push) Has been skipped
Makes the atlas self-explanatory. Every stage/node gains a plain-language layer
(plain_title + plain "what happens" + jargon-free node text); the previous
technical copy demotes to a subtitle + on-demand detail. A Plain⇄Technical
toggle (default Plain, persisted) flips the whole atlas. Biggest win: every
transition arrow is now LABELLED with "what must be true to advance" (the gated-
flow story that was invisible), gate hops (human @04, CI @06) styled distinctly.
Spine repositioned into a uniform header band so labels never collide with copy.

Copy grounded in a fresh-eyes UX review (docs/UX-REVIEW.md, reviewer≠implementer).
Data model: plain_title/plain/trans_label/trans on Stage, plain on Node — guarded
by a test (every stage has plain_title + a transition). Live overlays unchanged.

Verified: build/vet/lint(0)/test green; Plain render screenshot-checked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.3.0
2026-07-20 08:22:21 +02:00
mathiasandClaude Opus 4.8 1f7c9ab1eb feat(atlas): Phase C — live Flux reconcile status on stage 07
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Has been skipped
Stage 07 now also shows the Flux `apps` Kustomization state — reconciled/failed
+ last-applied revision (main@shortsha) — read in-cluster (new read-only Role in
flux-system). Sits alongside the live deploy node. FluxStatus/FluxNode test-first,
fallback-safe.

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

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.2.4
2026-07-20 07:56:42 +02:00
mathiasandClaude Opus 4.8 3e28dcf69f fix(atlas): treat skipped jobs as OK in run aggregate
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 13s
CD / Deploy via GitOps (push) Has been skipped
Tag-push runs skip the deploy job (deploy is main-only), so runs with a skipped
job were mislabelled "running" in the timeline. Skipped now counts as completed-
OK; only genuinely in-progress states aggregate to running. Test-first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.2.3
2026-07-20 07:48:30 +02:00
mathiasandClaude Opus 4.8 995e428eba feat(atlas): Phase C — recent-runs timeline
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Has been skipped
A strip of the last 12 runs (aggregate pass/fail/running per run) below the
substrate ribbon, coloured, newest-first, run # on hover. Parsed from the same
Gitea /actions/tasks fetch (RecentRuns, test-first; State refactored to share
the aggregate). No new RBAC. Hidden when no live data.

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

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.2.2
2026-07-20 07:45:59 +02:00
mathiasandClaude Opus 4.8 3d1f76997b feat(atlas): Phase C — live CD/deploy state on stage 07
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 13s
CD / Detect unsubstituted template (push) Successful in 0s
CD / Deploy via GitOps (push) Has been skipped
Stage 07 now shows the pod's own live deploy state — deployed image tag +
N/M replicas ready, green only when the rollout is fully ready — read from the
k8s Deployment in-cluster (new namespaced deployments-read Role). DeployState/
DeployNode test-first; prepended to the authored CD narrative, fallback-safe.

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

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.2.1
2026-07-20 07:39:01 +02:00
mathiasandClaude Opus 4.8 3ff922a4d5 feat(atlas): per-job CI status + build-injected version in the UI
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Successful in 18s
CD / Deploy via GitOps (push) Has been skipped
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>
v0.2.0
2026-07-20 07:21:52 +02:00
mathiasandClaude Opus 4.8 02a23a02dd feat(atlas): Phase C increment 1 — live CI runs on the pipeline
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 6s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Successful in 0s
The CI stage now shows the pipeline's latest real execution, read live from the
in-cluster Gitea Actions API (public read, no token, gitea-http.gitea.svc):
"▶ run #N · <state>" coloured by outcome, prepended to the generated job list.
LatestRun + RunNode built test-first; cached in the same 30s liveOverlay; falls
back cleanly when Gitea is unreachable.

assessor-loop ledger / session_log deferred: no live CAD data exists for this repo
yet (brain confirms). Gitea run history is the real available trace.

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

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 01:03:03 +02:00
mathiasandClaude Opus 4.8 633ba153f2 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>
2026-07-20 00:56:40 +02:00
mathiasandClaude Opus 4.8 39fd9b9adc feat(atlas): hybrid substrate — live specs for cluster nodes, authored rest
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 6s
CD / Build & Import (push) Successful in 14s
CD / Deploy via GitOps (push) Successful in 1s
MergeSubstrate overlays live node specs onto the authored machine list by name:
cluster nodes (koala) get fresh live specs, non-cluster machines (iguana/flamingo/
piguard) stay authored, new live nodes are appended. Test-first. Restores the full
homelab machine list while keeping cluster nodes truthful.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 00:47:53 +02:00
mathiasandClaude Opus 4.8 74dffc1ff3 feat(atlas): Phase B — substrate from the live cluster
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 0s
The substrate machines are now rendered from the live k3s nodes (arch, cpu,
memory, GPU, k3s version), read in-cluster via the mounted ServiceAccount with a
stdlib HTTP client (no client-go) and a 30s cache; falls back to the authored
substrate whenever the cluster is unreachable. Placement per the homelab decision
"in-cluster only for in-workload ops" — a running web app rendering live data fits.

HostsFromNodes parser built test-first. RBAC (read-only node-reader SA) shipped in
infra k3s/apps/cad-atlas/.

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

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 00:43:20 +02:00
mathiasandClaude Opus 4.8 a9c72d6ca8 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>
2026-07-20 00:34:06 +02:00
mathiasandClaude Opus 4.8 c3fda9b26b docs: wire INFRA_DEPLOY_KEY — CI now auto-deploys (#2)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 5s
CD / Build & Import (push) Successful in 12s
CD / Deploy via GitOps (push) Successful in 0s
Deploy job's INFRA_DEPLOY_KEY (write deploy-key cad-atlas-ci on infra) is set;
future main pushes auto-bump the infra image tag → Flux rolls. Also records the
live Authentik-gated endpoint. This commit is itself the first auto-deploy test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 23:57:01 +02:00
mathiasandClaude Opus 4.8 6a3ea77af5 docs: correct G3 (hollow CI runs), record live deployment
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Successful in 4s
CD / Build & Import (push) Successful in 12s
CD / Deploy via GitOps (push) Has been skipped
runs 16-18 were fake-green (template guard skipped all jobs, template-go-web#9);
CI genuinely green from run 19. cad-atlas now live on koala k3s via Flux
(infra k3s/apps/cad-atlas). CI deploy-job auto-deploy tracked in #2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.1.1
2026-07-19 16:09:18 +02:00
mathiasandClaude Opus 4.8 68adfe7e01 fix(ci): correct CD guard so real jobs run (F8)
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Successful in 7s
CD / Build & Import (push) Successful in 12s
CD / Deploy via GitOps (push) Failing after 0s
The guard grepped for the substituted module path, which always matches a
generated repo's own go.mod → is_template=true → check/build/deploy all
skipped (fake-green CI, nothing ever built/deployed). Detect leftover
__PLACEHOLDER__ tokens instead — verified: substituted repo runs CI, raw
template skips. Template-wide fix: template-go-web#9.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 16:01:32 +02:00
mathiasandClaude Opus 4.8 784ece65d0 docs: record Inception Sprint Oath; descope S3 (var-go enforcement) to #1
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Has been skipped
CD / Build & Import (push) Has been skipped
CD / Deploy via GitOps (push) Has been skipped
Add docs/INCEPTION-OATH.md — the sprint's acceptance contract (general +
cad-atlas-specific clauses, tagging as the closing act). S3 (var-go/oath
enforcing cad-atlas PRs) is descoped to a tracked fast-follow (#1): var-go v1's
candidate is a hardcoded self-test and its module is not cross-repo consumable,
so a green status would prove wiring, not verification. Honesty rule: a clause
blocked by an external dependency is descoped and tracked, never claimed.

Methodology persisted: brain wiki/homelab/decisions/inception-sprint-and-oath.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.1.0
2026-07-19 13:05:06 +02:00
mathiasandClaude Opus 4.8 506b428b2c docs: link genesis brain note from PROJECT context
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Has been skipped
CD / Build & Import (push) Has been skipped
CD / Deploy via GitOps (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:35:58 +02:00
mathiasandClaude Opus 4.8 5c6a4ab232 feat: Phase A — serve static CAD Atlas viz + self-contained context
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Has been skipped
CD / Build & Import (push) Has been skipped
CD / Deploy via GitOps (push) Has been skipped
Wire the reel-style CAD workflow atlas (signal→pod) as the served page via
go:embed. Fill PROJECT.md/README with the 9-stage workflow, three governance
gates (Ed25519 admission / dispatch-allow / var-go Oath), phase map A→C,
dogfooding model, brain deep-links and external references.

Fixes two template-go-web latent bugs surfaced by dogfooding:
- templ version skew: go.mod pinned v0.2.778 vs templ@latest generator
- .gitignore pattern *.templ.go did not match generated *_templ.go

Verified: go build · vet · golangci-lint (0 issues) · go test green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:34:23 +02:00
mathias e6cbf8a4e6 dispatch: mark project dispatch-eligible (dispatch#3)
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:48 +00:00
mathias 9ea65ef5d2 template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:48 +00:00
mathias 193425796f template: substitute placeholders
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Has been skipped
CD / Build & Import (push) Has been skipped
CD / Deploy via GitOps (push) Has been skipped
2026-07-19 08:29:48 +00:00
mathias 9b0bee58e9 template: drop placeholder path cmd/__PROJECT_NAME__/main.go
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:48 +00:00
mathias ccebcf8355 template: substitute + rename cmd/__PROJECT_NAME__/main.go -> cmd/cad-atlas/main.go
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:47 +00:00
mathias d4d7fd8a04 template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:47 +00:00
mathias 5a274caa3b template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:47 +00:00
mathias c812d70ab5 template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:47 +00:00
mathias 0efda88109 template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:47 +00:00
mathias bf1ec67960 template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:47 +00:00
mathias 3bf8e6a39f template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:47 +00:00
mathias 9acb65c97b template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:46 +00:00
mathias 6729e5495c template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:46 +00:00
mathias 20a6d79d74 template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:46 +00:00
mathias 11cf3b514e template: substitute placeholders
CD / Detect unsubstituted template (push) Has been cancelled
CD / Lint / Test / Vet (push) Has been cancelled
CD / Build & Import (push) Has been cancelled
CD / Deploy via GitOps (push) Has been cancelled
2026-07-19 08:29:46 +00:00