generated from mathias/template-go-web
feat: Phase A — serve static CAD Atlas viz + self-contained context
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>
This commit is contained in:
+359
-2
@@ -1,3 +1,282 @@
|
||||
# Agent context — Mathias workspace
|
||||
|
||||
<!-- Canonical root context for all AI coding agents.
|
||||
Lives at: ~/dev/.context/AGENT.md
|
||||
Applies to every project under ~/dev/ unless overridden.
|
||||
|
||||
Run `task context:sync` from ~/dev/ to regenerate harness-specific files.
|
||||
Project-level context in .context/PROJECT.md layers on top of this. -->
|
||||
|
||||
## Who I am
|
||||
|
||||
I'm Mathias, a digital product manager and technology consultant based in Sweden.
|
||||
I build software, research emerging tech, and deliver consulting engagements
|
||||
for clients under NDA. I work across AI/ML, financial automation, web applications,
|
||||
and climate/sustainability tech.
|
||||
|
||||
## How I work with agents
|
||||
|
||||
- I think like a product manager — I care about *why* before *how*
|
||||
- I want agents to be opinionated and push back, not just execute blindly
|
||||
- I prefer concise responses; skip ceremony and get to the point
|
||||
- When I say "build this", I mean production-quality with tests, not a demo
|
||||
- Ask me before making irreversible changes or adding heavy dependencies
|
||||
- I work with confidential client data — never send it to cloud APIs unless I explicitly say it's OK
|
||||
|
||||
## Behavior rules
|
||||
|
||||
These rules apply to every task across every project, regardless of harness.
|
||||
|
||||
0. **Pre-task ritual — before ANY implementation (non-negotiable).** Run this before writing a single line:
|
||||
- **Query the brain** (`brain_query`) for the domain + symptom. If the result changes your approach, surface it before acting. 5 seconds beats 5 hours.
|
||||
- **Load the relevant skill** — see trigger table in *Engineering Skills* below.
|
||||
- **Write the failing test first.** Name the test before the function. If the target is untestable (e.g. `main()` wiring), extract the logic into a testable function first. No implementation without a red test.
|
||||
- **State the observable success criterion** — what specific behavior, output, or passing test proves this is done?
|
||||
|
||||
**TDD is non-negotiable.** "Tests pass" is not proof of correctness — only proof the tests ran. Write tests that would catch the bug before writing code that fixes it.
|
||||
|
||||
1. **No assumptions.** Don't hide confusion — surface it. Surface tradeoffs explicitly.
|
||||
Think before coding; if the problem is unclear, ask or state assumptions before acting.
|
||||
2. **Minimum viable code.** Solve with the smallest change that works. Nothing
|
||||
speculative, no "while we're here" cleanups, no premature abstractions. Simplicity first.
|
||||
3. **Surgical changes.** Touch only what the task requires. Leave unrelated code,
|
||||
files, and formatting alone. Diffs should be small and reviewable.
|
||||
4. **Goal-driven execution.** Define clear success criteria up front for every task.
|
||||
Loop — implement, verify, refine — until those criteria are met. Don't claim
|
||||
completion without evidence (tests pass, command output, observed behavior).
|
||||
5. **Trunk-Based Development — commit directly to main.** Every commit is one
|
||||
logical change (one tool, one fix, one test) with passing tests. Main is always
|
||||
deployable. Never create long-lived feature branches.
|
||||
|
||||
**Exception — parallel agents on same repo:** If another agent is known to be
|
||||
actively working on the same repo simultaneously, create a short-lived branch
|
||||
(`agent/<description>`), finish the task, and merge to main within the same
|
||||
session. Do not leave agent branches open between sessions.
|
||||
|
||||
**Exception — external contributor or client four-eyes requirement:** Use
|
||||
PR flow only when a human reviewer outside the project is required. Document
|
||||
the reason in PROJECT.md.
|
||||
|
||||
6. **Close the loop — every substantive task ends with the same ritual.** Shipping
|
||||
the code is not the end of the task; capturing it is. Run this unprompted:
|
||||
- **Tag + bump SemVer** on the change (annotated tag; minor for a feature or
|
||||
new/changed ADR, patch for a fix; docs in the same commit). Check the repo's
|
||||
actual last tag — stated versions in docs drift stale.
|
||||
- **Push** main and the tag (CI is the gate).
|
||||
- **Persist generalizable learnings to the brain** (`brain_write`, wing/hall) —
|
||||
the reusable patterns and the footguns that would bite anyone again, never
|
||||
project status. See *Knowledge base — when to write* below.
|
||||
- **File discovered-but-deferred work as tracker issues** on the project's own
|
||||
repo — token-budget gaps, recorded ADR limitations, v2 follow-ups. Don't let
|
||||
"out of scope, recorded" rot in a commit message; make it a ticket with a
|
||||
source pointer.
|
||||
- Surface the brain entries and issue numbers in the closing summary so the
|
||||
trail is auditable.
|
||||
|
||||
## Default stack
|
||||
|
||||
| Layer | Default | Fallback | Last resort |
|
||||
|-------|---------|----------|-------------|
|
||||
| Language | Go | Python | TypeScript, Java, C |
|
||||
| UI | HTMX + Templ | Server-rendered HTML | React (only if SPA is justified) |
|
||||
| Build | Task (taskfile.dev) | Make | — |
|
||||
| Containers | Docker Compose (dev), k3s (prod) | — | — |
|
||||
| DB | PostgreSQL + sqlc | SQLite | — |
|
||||
| Search | pgvector (vector), BM25 | Qdrant (when >1M vectors or hybrid retrieval) | — |
|
||||
| Logging | slog (structured) | — | — |
|
||||
| Testing | Table-driven, testify | — | — |
|
||||
| Agents (Go) | google.golang.org/adk + pkg/litellm adapter | — | — |
|
||||
|
||||
Exploratory: Rust, Zig — I'll tell you when I want these.
|
||||
|
||||
## Code conventions
|
||||
|
||||
- **Go style**: golines, gofumpt, golangci-lint
|
||||
- **Errors**: `fmt.Errorf("operation: %w", err)` — never naked, never log-and-return
|
||||
- **Naming**: stdlib conventions, no stuttering
|
||||
- **Architecture**: prefer stdlib over frameworks, constructor injection, env-var config parsed into typed structs
|
||||
- **Git**: conventional commits (`feat:`, `fix:`, `chore:`), commit directly to main,
|
||||
one logical change per commit, CI is the quality gate
|
||||
- **Never**: long-lived feature branches, PRs for solo work, direct push without
|
||||
passing `task check` locally first
|
||||
- **Security**: no secrets in code, govulncheck before adding deps, SOPS for encrypted config
|
||||
- **Dependencies**: prefer stdlib. testify, slog, templ, sqlc, google.golang.org/adk (agent projects only) are pre-approved; anything else needs justification in the commit message
|
||||
|
||||
## Secret handling (every harness, every command)
|
||||
|
||||
Tool output is persisted: terminal → `~/.claude/projects` transcripts →
|
||||
claudewatcher → brain/wiki → gitea history. A secret printed once is
|
||||
searchable forever, and clearing it means rotating the key. So:
|
||||
|
||||
1. **Never print, echo, log, or transform a secret to inspect it.** No
|
||||
`base64`/`xxd`/`cat` of a key, and never pipe a secret through a transform
|
||||
to defeat `op run`'s output masking (it masks raw values; base64 hides them
|
||||
from the mask — that exact trick leaked a key on 2026-06-11).
|
||||
2. **Secrets stay in the subprocess.** Reference them only as env vars consumed
|
||||
*inside* `op run --env-file ~/.op-env -- <cmd>`. Never place a literal secret
|
||||
in a command's argv (it lands in the tool call and the transcript).
|
||||
3. **Existence check without revealing the value:** `[ -n "$X" ] && echo set` —
|
||||
never `${X:-...}` (returns the value when set) and never echo a substring of it.
|
||||
4. **Cross-host secrets:** run the secret-consuming command on the host that has
|
||||
the secret; do not forward a raw key over ssh argv/stdout.
|
||||
5. If a secret does leak into output, say so immediately and flag it for rotation —
|
||||
don't bury it.
|
||||
|
||||
## Infrastructure
|
||||
|
||||
Three machines on Tailscale:
|
||||
|
||||
| Machine | Role | Key specs |
|
||||
|---------|------|-----------|
|
||||
| koala | GPU inference, heavy compute | RTX 5070, runs k3s + llama-swap + shared postgres18/pgvector |
|
||||
| iguana | Services, builds | M2 Ultra Mac |
|
||||
| flamingo | Daily driver, edge | Mac mini, ~/dev is here |
|
||||
|
||||
- **Model routing**: LiteLLM in front of llama-swap (local) + cloud APIs (when permitted)
|
||||
- **Orchestration**: k3s cluster across all three machines
|
||||
- **Networking**: Tailscale mesh
|
||||
|
||||
## Project landscape
|
||||
|
||||
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
||||
|
||||
Organized in thematic folders:
|
||||
|
||||
| Folder | Focus | Count |
|
||||
|--------|-------|-------|
|
||||
| `GO/` | Go web frameworks, API integrations, learning projects | ~10 |
|
||||
| `AI/` | ML research, AI frameworks (FinRL, DSPy, crawl4ai) | ~6 |
|
||||
| `AGENTS/` | Autonomous agents, coding agents, MCP servers, infra | ~15 |
|
||||
| `QKX/` | Invoice processing, financial automation, payment systems | ~13 |
|
||||
| `XT/` | Climate data, sustainability (Klimatkollen, Garbo) | ~2 |
|
||||
|
||||
See `~/dev/PROJECT_SUMMARY.md` for detailed descriptions of each project.
|
||||
|
||||
### Key active projects
|
||||
|
||||
- **super-koala** (`AGENTS/`) — multi-component agent stack with LangGraph, DSPy, MCP
|
||||
- **azure-tiger** (`QKX/`) — invoice extraction → ISO 20022 payment instructions
|
||||
- **gocrwl** (`AGENTS/`) — Go web crawler with containerized deployment
|
||||
- **koala-ai-stack** (`AGENTS/`) — local AI server infrastructure management
|
||||
- **klimatkollen** (`XT/`) — Swedish municipal climate data platform
|
||||
|
||||
## Knowledge base — actively use it
|
||||
|
||||
A persistent brain (BM25 search + LLM-synthesised Q&A) survives across sessions,
|
||||
hosts, and harnesses. It holds 100+ hard-won entries: infra incident postmortems,
|
||||
Go pitfalls, framework gotchas, design principles, ADRs. **It is not optional
|
||||
reference material — query it actively, not just when explicitly told.**
|
||||
|
||||
### When to query (treat as a reflex)
|
||||
|
||||
- **Before** starting a non-trivial task — search for prior art with the symptom
|
||||
AND the system component ("how did we solve X in Y?"). 5 seconds beats 5 hours.
|
||||
- **When debugging** — search for the error string, the stack frame, the affected
|
||||
service. Past you may have already paid this tax.
|
||||
- **Before adopting** a pattern, library, framework, or model name — check if it
|
||||
was tried and rejected, or what the integration footguns are.
|
||||
- **When making architectural decisions** — search for the domain + "ADR" or
|
||||
"decision" to find prior reasoning before re-deriving it.
|
||||
- **When a recommendation feels novel** — challenge yourself: "has this been
|
||||
documented?" The brain often has it.
|
||||
|
||||
### When to write
|
||||
|
||||
After you discover something that **future-you would forget** and that **isn't
|
||||
recoverable from the code, git log, or PR description alone**:
|
||||
|
||||
- Bugs whose root cause is non-obvious and generalisable beyond this project.
|
||||
- Framework / library / model-name quirks that bit you and would bite anyone.
|
||||
- Design principles validated under fire (e.g. "every `_get` needs a `_list`").
|
||||
- Postmortems for incidents: what broke, why, how diagnosed, what to do next time.
|
||||
|
||||
DON'T write project status, sprint progress, PR summaries, or "what I did this
|
||||
session" — those rot fast and the originals are in git/gitea anyway. Brain
|
||||
entries that age well are about *why*, *how to avoid*, and *what to do when*.
|
||||
|
||||
### How to access (per harness)
|
||||
|
||||
| Harness | Query | Write |
|
||||
|---------|-------|-------|
|
||||
| **Claude Code, Claude Desktop** | `brain_query` (BM25), `brain_answer` (LLM-synth + sources) MCP tools | `brain_write` MCP tool |
|
||||
| **Crush, Pi, Antigravity, other MCP-capable** | same MCP server: `ingestion-brain` (via the `mcp__*_brain__*` namespace once authenticated) | same |
|
||||
| **Anything HTTP-only (curl, scripts)** | `POST https://brain-mcp.d-ma.be/query` with `{"query":"..."}` (auth via `BRAIN_MCP_TOKEN`) | `POST .../write` with `{"content":"...","filename":"..."}` |
|
||||
| **Browser / human inspection** | `https://git.d-ma.be/mathias/hyperguild` → `knowledge/` and `wiki/` markdown files |
|
||||
|
||||
- **Scoping**: defaults to `public` collection; client projects filter to `{client}` + `public`.
|
||||
- **Routing**: brain_answer's LLM uses berget.ai as primary, iguana ollama as
|
||||
fallback. Both are configurable in the `supervisor/ingestion-deployment.yaml`
|
||||
on the koala k3s cluster; don't hardcode local-only model names into the
|
||||
berget URL (see knowledge entry on namespace mismatches).
|
||||
|
||||
### Quick reflex checks
|
||||
|
||||
If you find yourself about to say any of these out loud, you owe yourself a brain query first:
|
||||
|
||||
- "I think the issue might be..."
|
||||
- "Let me try X and see..."
|
||||
- "I'll just write a script to..."
|
||||
- "This is probably a new bug..."
|
||||
- "Has anyone done this before?" — *yes, probably, go check.*
|
||||
|
||||
## Client work rules
|
||||
|
||||
When working on a project tagged with a client name:
|
||||
1. Never send code, data, or context to cloud APIs — use local models only
|
||||
2. Never reference other client projects or their data
|
||||
3. Keep all artifacts within the client's git org / directory
|
||||
4. Treat everything as confidential unless told otherwise
|
||||
|
||||
## Harness-agnostic principles
|
||||
|
||||
This context is designed to work with any AI coding tool:
|
||||
- Claude Code, Cursor, Aider, Open WebUI, Charmbracelet Mods/Crush
|
||||
- Pi Coding Agent, Mistral Vibe, Antigravity
|
||||
- Any tool that accepts a system prompt or reads a markdown context file
|
||||
|
||||
The canonical source is always `.context/AGENT.md` (root) and `.context/PROJECT.md` (per-project).
|
||||
Derived files are committed (see *How context propagates* below) so a `git pull` on any host yields full agent context with no setup.
|
||||
|
||||
## How context propagates
|
||||
|
||||
Canonical sources of truth:
|
||||
- Universal: `~/dev/.context/AGENT.md` (this file)
|
||||
- Project: `<repo>/.context/PROJECT.md` (per-repo)
|
||||
|
||||
Derived files (committed, regenerated by `task context:sync`):
|
||||
- `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.aider.conventions.md`,
|
||||
`.context/system-prompt.txt`
|
||||
|
||||
Workflow:
|
||||
1. Edit a canonical file. Run `task context:sync`. Commit canonical and
|
||||
derived together. Push.
|
||||
2. On any other host, `git pull` brings both. Claude Code (tree-walking)
|
||||
uses `CLAUDE.md`; Crush / Pi / Antigravity (cwd-only) use `AGENTS.md`;
|
||||
Cursor uses `.cursorrules`; Aider uses `.aider.conventions.md`.
|
||||
3. `task check` runs `context:sync` then asserts `git status --porcelain`
|
||||
is empty over the derived files (catches both modified-tracked drift
|
||||
and missing-untracked adapters). A drift fails the check with a
|
||||
message telling you to stage the regenerated files.
|
||||
|
||||
Behavior rules in this file and per-project rules in `PROJECT.md` apply
|
||||
unconditionally on every host, every harness.
|
||||
|
||||
## Engineering Skills
|
||||
|
||||
Shared engineering skills live in the **`mathias/skills`** repo (`git.d-ma.be/mathias/skills`). Clone it to `~/dev/skills/` and run `SKILLS_CHECKOUT_DIR="$PWD" bash install.sh` there to wire every skill into your harnesses (Claude Code, Crush, Antigravity, Mistral Vibe) as native, on-demand skills. (Use `install.sh`, not `task install` — the latter is currently broken, skills#7.) Load at task start — not "on demand" but on schedule, before writing code. Browse `~/dev/skills/SKILLS_INDEX.md` for the full list.
|
||||
|
||||
**Skill trigger table — load before starting, not after getting stuck:**
|
||||
|
||||
| Task type | Load |
|
||||
|-----------|------|
|
||||
| Any feature or bug fix | `tdd` |
|
||||
| Refactor or design | `clean-code` or `solid` |
|
||||
| Debug | `problem-analysis` |
|
||||
| Review code or PRs | `code-review` |
|
||||
| Frame a problem before coding | `problem-analysis` |
|
||||
|
||||
---
|
||||
|
||||
# cad-atlas
|
||||
|
||||
## Identity
|
||||
@@ -7,7 +286,85 @@
|
||||
- **Client**: personal
|
||||
- **Repo**: git.d-ma.be/mathias/cad-atlas
|
||||
- **Status**: active
|
||||
- **Stack**: Go + Templ + HTMX + CDN Tailwind (template-go-web). Cross-project conventions: `~/dev/.context/AGENT.md`.
|
||||
|
||||
## Stack
|
||||
## What this is
|
||||
|
||||
Go + Templ + HTMX + CDN Tailwind. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
||||
A visual **atlas of the Continuous Agentic Development (CAD) workflow** — the full path
|
||||
from a captured signal to a deployed k3s pod, one screen, reel-style ("From Signal to Pod").
|
||||
It exists to (a) make the homelab's agentic delivery pipeline legible to a human, and
|
||||
(b) render the CAD **audit chain** — which doubles as the regulated-industry audit artifact.
|
||||
|
||||
> **Core thesis:** the CAD audit chain *is* the visualization data.
|
||||
> `TELOS → goal → spec → issue → execution → attestation → deploy` is both the trace and
|
||||
> the audit package. Phase C renders it once and serves two masters (observability + compliance).
|
||||
|
||||
## Phases
|
||||
|
||||
- **Phase A — static hero viz** (current). Self-contained `internal/web/static/cad-atlas.html`,
|
||||
data-driven from a hand-authored `STAGES` array (ground-truth snapshot from brain, 2026-07-19).
|
||||
Served at `/` by `internal/web/handler.go` via `go:embed`. Reel-parity: SVG spine with
|
||||
arrowheads, animated pulse, dashed **feedback bus** (stage 08 → TELOS), replay + slow-mo.
|
||||
- **Phase B — generated-from-source**. Parse brain docs + `.gitea/workflows` + infra manifests
|
||||
→ render the graph so it can't drift from config.
|
||||
- **Phase C — live trace viewer**. Replace the static `STAGES` array with live reads of the
|
||||
`assessor-loop` attestation ledger + brain `session_log` + Gitea run API + Flux events.
|
||||
This is the prize: a real signal→pod trace viewer that is also the audit package.
|
||||
|
||||
## The workflow it visualizes (9 stages)
|
||||
|
||||
`00 Signals` (Applied AI Radar → mathias/signals) → `01 TELOS` (intention substrate) →
|
||||
`02 Strategic session` (claude.ai frontier + LLM Council + Autoresearch Council) →
|
||||
`03 Spec → Gitea issue` (agent-ready contract; Ed25519 admission #36; **var-go Oath**) →
|
||||
`04 Human dispatch gate` (the only checkpoint; session-dispatch bridge → cad-dispatch.yml) →
|
||||
`05 Execute · agentsquad` (serve/taskqueue, exec+review loop, risk LOW/MED/HIGH, dma-cli routing,
|
||||
assessor-loop ledger) → `06 PR → CI` (go test/vet/lint/govulncheck + **var-go/oath gate**) →
|
||||
`07 CD → pod` (Flux GitOps → k3s on koala) → `08 Loop back` (outcome scored vs TELOS goal).
|
||||
|
||||
### Three orthogonal governance gates
|
||||
|
||||
| Gate | Guards | Where |
|
||||
|---|---|---|
|
||||
| Ed25519 admission controller (#36) | spec **integrity** (issue untampered) | stage 03 |
|
||||
| dispatch-allow (`.dispatch-allow` + `mathias/dispatch` allowlist) | repo **eligibility** (may agents run here) | stage 04/05 |
|
||||
| **var-go Oath** (`cmd/vargo-gate`, commit status `var-go/oath`) | output **correctness** (PR satisfies the Oath; floor over reviewer, anti-rubber-stamp #55) | stage 06 |
|
||||
|
||||
## Dogfooding
|
||||
|
||||
This repo is built *through* the workflow it depicts. It is `dispatch-allow`-enabled, and its
|
||||
own build increments are governed by a **var-go Oath** embedded in their spec issues (see the
|
||||
Stage-03 tracking issue). Bootstrapping honesty (per swedsl honest-stub discipline): the Oath is
|
||||
**defined** but `cmd/vargo-gate` is **not yet wired** into this repo's CI — until it is, the Oath
|
||||
is advisory here. Wiring it is a first tracked task; disclosed in code, this doc, and CI config.
|
||||
|
||||
## Brain references (source of truth — `brain_get <path>`)
|
||||
|
||||
- `knowledge/workflow-idea-to-running-service.md` — Double Diamond idea→service workflow
|
||||
- `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16.md` — CAD definition
|
||||
- `wiki/agentsquad/decisions/cad-dispatch-bridge.md` — claude.ai → agentsquad trigger path
|
||||
- `wiki/agentsquad/facts/llm-council-design-and-first-runs-2026-06-21.md` — LLM Council
|
||||
- `wiki/agentsquad/decisions/autoresearch-council-sibling-pipe.md` — Autoresearch Council
|
||||
- `wiki/agentsquad/decisions/serve-http-task-api.md` — agentsquad serve/taskqueue
|
||||
- `knowledge/var-go-anchor-to-span-spike-verdict.md` — var-go runner + CAD gate seam
|
||||
- `knowledge/swedsl-vargo-sprint1-enforcement-teeth-verdict.md` — vargo-gate enforcement teeth
|
||||
- `wiki/assessor-loop/decisions/assessor-loop-genesis.md` — attestation ledger (Phase C source)
|
||||
- `wiki/homelab/facts/homelab-network-topology-reference.md` — koala/iguana/flamingo/piguard
|
||||
|
||||
## External references
|
||||
|
||||
- Inspiration reel — "From Inbox to Shipped" pipeline viz: https://www.instagram.com/reel/DY92L7bu27j/
|
||||
- karpathy/llm-council — origin of the Council pattern
|
||||
- Double Diamond design process (Discover/Define/Develop/Deliver)
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
task check # lint + vet + test (CI gate)
|
||||
task run # build + serve at http://localhost:8080 → the atlas
|
||||
```
|
||||
|
||||
## Deploy note
|
||||
|
||||
CD (`.gitea/workflows/cd.yml`) deploys to k3s namespace `cad-atlas` via Flux. Per the known
|
||||
template-go-agent CD gap: the `deploy` job stays RED until `mathias/infra` has
|
||||
`k3s/apps/cad-atlas/deployment.yaml`. `check` + `build` are the real bootstrap gate.
|
||||
|
||||
+80
-2
@@ -7,7 +7,85 @@
|
||||
- **Client**: personal
|
||||
- **Repo**: git.d-ma.be/mathias/cad-atlas
|
||||
- **Status**: active
|
||||
- **Stack**: Go + Templ + HTMX + CDN Tailwind (template-go-web). Cross-project conventions: `~/dev/.context/AGENT.md`.
|
||||
|
||||
## Stack
|
||||
## What this is
|
||||
|
||||
Go + Templ + HTMX + CDN Tailwind. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
||||
A visual **atlas of the Continuous Agentic Development (CAD) workflow** — the full path
|
||||
from a captured signal to a deployed k3s pod, one screen, reel-style ("From Signal to Pod").
|
||||
It exists to (a) make the homelab's agentic delivery pipeline legible to a human, and
|
||||
(b) render the CAD **audit chain** — which doubles as the regulated-industry audit artifact.
|
||||
|
||||
> **Core thesis:** the CAD audit chain *is* the visualization data.
|
||||
> `TELOS → goal → spec → issue → execution → attestation → deploy` is both the trace and
|
||||
> the audit package. Phase C renders it once and serves two masters (observability + compliance).
|
||||
|
||||
## Phases
|
||||
|
||||
- **Phase A — static hero viz** (current). Self-contained `internal/web/static/cad-atlas.html`,
|
||||
data-driven from a hand-authored `STAGES` array (ground-truth snapshot from brain, 2026-07-19).
|
||||
Served at `/` by `internal/web/handler.go` via `go:embed`. Reel-parity: SVG spine with
|
||||
arrowheads, animated pulse, dashed **feedback bus** (stage 08 → TELOS), replay + slow-mo.
|
||||
- **Phase B — generated-from-source**. Parse brain docs + `.gitea/workflows` + infra manifests
|
||||
→ render the graph so it can't drift from config.
|
||||
- **Phase C — live trace viewer**. Replace the static `STAGES` array with live reads of the
|
||||
`assessor-loop` attestation ledger + brain `session_log` + Gitea run API + Flux events.
|
||||
This is the prize: a real signal→pod trace viewer that is also the audit package.
|
||||
|
||||
## The workflow it visualizes (9 stages)
|
||||
|
||||
`00 Signals` (Applied AI Radar → mathias/signals) → `01 TELOS` (intention substrate) →
|
||||
`02 Strategic session` (claude.ai frontier + LLM Council + Autoresearch Council) →
|
||||
`03 Spec → Gitea issue` (agent-ready contract; Ed25519 admission #36; **var-go Oath**) →
|
||||
`04 Human dispatch gate` (the only checkpoint; session-dispatch bridge → cad-dispatch.yml) →
|
||||
`05 Execute · agentsquad` (serve/taskqueue, exec+review loop, risk LOW/MED/HIGH, dma-cli routing,
|
||||
assessor-loop ledger) → `06 PR → CI` (go test/vet/lint/govulncheck + **var-go/oath gate**) →
|
||||
`07 CD → pod` (Flux GitOps → k3s on koala) → `08 Loop back` (outcome scored vs TELOS goal).
|
||||
|
||||
### Three orthogonal governance gates
|
||||
|
||||
| Gate | Guards | Where |
|
||||
|---|---|---|
|
||||
| Ed25519 admission controller (#36) | spec **integrity** (issue untampered) | stage 03 |
|
||||
| dispatch-allow (`.dispatch-allow` + `mathias/dispatch` allowlist) | repo **eligibility** (may agents run here) | stage 04/05 |
|
||||
| **var-go Oath** (`cmd/vargo-gate`, commit status `var-go/oath`) | output **correctness** (PR satisfies the Oath; floor over reviewer, anti-rubber-stamp #55) | stage 06 |
|
||||
|
||||
## Dogfooding
|
||||
|
||||
This repo is built *through* the workflow it depicts. It is `dispatch-allow`-enabled, and its
|
||||
own build increments are governed by a **var-go Oath** embedded in their spec issues (see the
|
||||
Stage-03 tracking issue). Bootstrapping honesty (per swedsl honest-stub discipline): the Oath is
|
||||
**defined** but `cmd/vargo-gate` is **not yet wired** into this repo's CI — until it is, the Oath
|
||||
is advisory here. Wiring it is a first tracked task; disclosed in code, this doc, and CI config.
|
||||
|
||||
## Brain references (source of truth — `brain_get <path>`)
|
||||
|
||||
- `knowledge/workflow-idea-to-running-service.md` — Double Diamond idea→service workflow
|
||||
- `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16.md` — CAD definition
|
||||
- `wiki/agentsquad/decisions/cad-dispatch-bridge.md` — claude.ai → agentsquad trigger path
|
||||
- `wiki/agentsquad/facts/llm-council-design-and-first-runs-2026-06-21.md` — LLM Council
|
||||
- `wiki/agentsquad/decisions/autoresearch-council-sibling-pipe.md` — Autoresearch Council
|
||||
- `wiki/agentsquad/decisions/serve-http-task-api.md` — agentsquad serve/taskqueue
|
||||
- `knowledge/var-go-anchor-to-span-spike-verdict.md` — var-go runner + CAD gate seam
|
||||
- `knowledge/swedsl-vargo-sprint1-enforcement-teeth-verdict.md` — vargo-gate enforcement teeth
|
||||
- `wiki/assessor-loop/decisions/assessor-loop-genesis.md` — attestation ledger (Phase C source)
|
||||
- `wiki/homelab/facts/homelab-network-topology-reference.md` — koala/iguana/flamingo/piguard
|
||||
|
||||
## External references
|
||||
|
||||
- Inspiration reel — "From Inbox to Shipped" pipeline viz: https://www.instagram.com/reel/DY92L7bu27j/
|
||||
- karpathy/llm-council — origin of the Council pattern
|
||||
- Double Diamond design process (Discover/Define/Develop/Deliver)
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
task check # lint + vet + test (CI gate)
|
||||
task run # build + serve at http://localhost:8080 → the atlas
|
||||
```
|
||||
|
||||
## Deploy note
|
||||
|
||||
CD (`.gitea/workflows/cd.yml`) deploys to k3s namespace `cad-atlas` via Flux. Per the known
|
||||
template-go-agent CD gap: the `deploy` job stays RED until `mathias/infra` has
|
||||
`k3s/apps/cad-atlas/deployment.yaml`. `check` + `build` are the real bootstrap gate.
|
||||
|
||||
@@ -3,6 +3,24 @@
|
||||
"knowledge": {
|
||||
"url": "http://localhost:3100/mcp",
|
||||
"description": "Project knowledge base — vector + graph retrieval"
|
||||
},
|
||||
"brain": {
|
||||
"type": "http",
|
||||
"url": "https://brain-mcp.d-ma.be/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ${BRAIN_MCP_TOKEN}"
|
||||
}
|
||||
},
|
||||
"gitea": {
|
||||
"type": "http",
|
||||
"url": "https://git-mcp.d-ma.be/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ${GITEA_MCP_TOKEN}"
|
||||
}
|
||||
},
|
||||
"infra": {
|
||||
"type": "http",
|
||||
"url": "https://infra-mcp.d-ma.be/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+359
-2
@@ -3,6 +3,285 @@ Follow all conventions from both the root agent context and project context.
|
||||
|
||||
---
|
||||
|
||||
# Agent context — Mathias workspace
|
||||
|
||||
<!-- Canonical root context for all AI coding agents.
|
||||
Lives at: ~/dev/.context/AGENT.md
|
||||
Applies to every project under ~/dev/ unless overridden.
|
||||
|
||||
Run `task context:sync` from ~/dev/ to regenerate harness-specific files.
|
||||
Project-level context in .context/PROJECT.md layers on top of this. -->
|
||||
|
||||
## Who I am
|
||||
|
||||
I'm Mathias, a digital product manager and technology consultant based in Sweden.
|
||||
I build software, research emerging tech, and deliver consulting engagements
|
||||
for clients under NDA. I work across AI/ML, financial automation, web applications,
|
||||
and climate/sustainability tech.
|
||||
|
||||
## How I work with agents
|
||||
|
||||
- I think like a product manager — I care about *why* before *how*
|
||||
- I want agents to be opinionated and push back, not just execute blindly
|
||||
- I prefer concise responses; skip ceremony and get to the point
|
||||
- When I say "build this", I mean production-quality with tests, not a demo
|
||||
- Ask me before making irreversible changes or adding heavy dependencies
|
||||
- I work with confidential client data — never send it to cloud APIs unless I explicitly say it's OK
|
||||
|
||||
## Behavior rules
|
||||
|
||||
These rules apply to every task across every project, regardless of harness.
|
||||
|
||||
0. **Pre-task ritual — before ANY implementation (non-negotiable).** Run this before writing a single line:
|
||||
- **Query the brain** (`brain_query`) for the domain + symptom. If the result changes your approach, surface it before acting. 5 seconds beats 5 hours.
|
||||
- **Load the relevant skill** — see trigger table in *Engineering Skills* below.
|
||||
- **Write the failing test first.** Name the test before the function. If the target is untestable (e.g. `main()` wiring), extract the logic into a testable function first. No implementation without a red test.
|
||||
- **State the observable success criterion** — what specific behavior, output, or passing test proves this is done?
|
||||
|
||||
**TDD is non-negotiable.** "Tests pass" is not proof of correctness — only proof the tests ran. Write tests that would catch the bug before writing code that fixes it.
|
||||
|
||||
1. **No assumptions.** Don't hide confusion — surface it. Surface tradeoffs explicitly.
|
||||
Think before coding; if the problem is unclear, ask or state assumptions before acting.
|
||||
2. **Minimum viable code.** Solve with the smallest change that works. Nothing
|
||||
speculative, no "while we're here" cleanups, no premature abstractions. Simplicity first.
|
||||
3. **Surgical changes.** Touch only what the task requires. Leave unrelated code,
|
||||
files, and formatting alone. Diffs should be small and reviewable.
|
||||
4. **Goal-driven execution.** Define clear success criteria up front for every task.
|
||||
Loop — implement, verify, refine — until those criteria are met. Don't claim
|
||||
completion without evidence (tests pass, command output, observed behavior).
|
||||
5. **Trunk-Based Development — commit directly to main.** Every commit is one
|
||||
logical change (one tool, one fix, one test) with passing tests. Main is always
|
||||
deployable. Never create long-lived feature branches.
|
||||
|
||||
**Exception — parallel agents on same repo:** If another agent is known to be
|
||||
actively working on the same repo simultaneously, create a short-lived branch
|
||||
(`agent/<description>`), finish the task, and merge to main within the same
|
||||
session. Do not leave agent branches open between sessions.
|
||||
|
||||
**Exception — external contributor or client four-eyes requirement:** Use
|
||||
PR flow only when a human reviewer outside the project is required. Document
|
||||
the reason in PROJECT.md.
|
||||
|
||||
6. **Close the loop — every substantive task ends with the same ritual.** Shipping
|
||||
the code is not the end of the task; capturing it is. Run this unprompted:
|
||||
- **Tag + bump SemVer** on the change (annotated tag; minor for a feature or
|
||||
new/changed ADR, patch for a fix; docs in the same commit). Check the repo's
|
||||
actual last tag — stated versions in docs drift stale.
|
||||
- **Push** main and the tag (CI is the gate).
|
||||
- **Persist generalizable learnings to the brain** (`brain_write`, wing/hall) —
|
||||
the reusable patterns and the footguns that would bite anyone again, never
|
||||
project status. See *Knowledge base — when to write* below.
|
||||
- **File discovered-but-deferred work as tracker issues** on the project's own
|
||||
repo — token-budget gaps, recorded ADR limitations, v2 follow-ups. Don't let
|
||||
"out of scope, recorded" rot in a commit message; make it a ticket with a
|
||||
source pointer.
|
||||
- Surface the brain entries and issue numbers in the closing summary so the
|
||||
trail is auditable.
|
||||
|
||||
## Default stack
|
||||
|
||||
| Layer | Default | Fallback | Last resort |
|
||||
|-------|---------|----------|-------------|
|
||||
| Language | Go | Python | TypeScript, Java, C |
|
||||
| UI | HTMX + Templ | Server-rendered HTML | React (only if SPA is justified) |
|
||||
| Build | Task (taskfile.dev) | Make | — |
|
||||
| Containers | Docker Compose (dev), k3s (prod) | — | — |
|
||||
| DB | PostgreSQL + sqlc | SQLite | — |
|
||||
| Search | pgvector (vector), BM25 | Qdrant (when >1M vectors or hybrid retrieval) | — |
|
||||
| Logging | slog (structured) | — | — |
|
||||
| Testing | Table-driven, testify | — | — |
|
||||
| Agents (Go) | google.golang.org/adk + pkg/litellm adapter | — | — |
|
||||
|
||||
Exploratory: Rust, Zig — I'll tell you when I want these.
|
||||
|
||||
## Code conventions
|
||||
|
||||
- **Go style**: golines, gofumpt, golangci-lint
|
||||
- **Errors**: `fmt.Errorf("operation: %w", err)` — never naked, never log-and-return
|
||||
- **Naming**: stdlib conventions, no stuttering
|
||||
- **Architecture**: prefer stdlib over frameworks, constructor injection, env-var config parsed into typed structs
|
||||
- **Git**: conventional commits (`feat:`, `fix:`, `chore:`), commit directly to main,
|
||||
one logical change per commit, CI is the quality gate
|
||||
- **Never**: long-lived feature branches, PRs for solo work, direct push without
|
||||
passing `task check` locally first
|
||||
- **Security**: no secrets in code, govulncheck before adding deps, SOPS for encrypted config
|
||||
- **Dependencies**: prefer stdlib. testify, slog, templ, sqlc, google.golang.org/adk (agent projects only) are pre-approved; anything else needs justification in the commit message
|
||||
|
||||
## Secret handling (every harness, every command)
|
||||
|
||||
Tool output is persisted: terminal → `~/.claude/projects` transcripts →
|
||||
claudewatcher → brain/wiki → gitea history. A secret printed once is
|
||||
searchable forever, and clearing it means rotating the key. So:
|
||||
|
||||
1. **Never print, echo, log, or transform a secret to inspect it.** No
|
||||
`base64`/`xxd`/`cat` of a key, and never pipe a secret through a transform
|
||||
to defeat `op run`'s output masking (it masks raw values; base64 hides them
|
||||
from the mask — that exact trick leaked a key on 2026-06-11).
|
||||
2. **Secrets stay in the subprocess.** Reference them only as env vars consumed
|
||||
*inside* `op run --env-file ~/.op-env -- <cmd>`. Never place a literal secret
|
||||
in a command's argv (it lands in the tool call and the transcript).
|
||||
3. **Existence check without revealing the value:** `[ -n "$X" ] && echo set` —
|
||||
never `${X:-...}` (returns the value when set) and never echo a substring of it.
|
||||
4. **Cross-host secrets:** run the secret-consuming command on the host that has
|
||||
the secret; do not forward a raw key over ssh argv/stdout.
|
||||
5. If a secret does leak into output, say so immediately and flag it for rotation —
|
||||
don't bury it.
|
||||
|
||||
## Infrastructure
|
||||
|
||||
Three machines on Tailscale:
|
||||
|
||||
| Machine | Role | Key specs |
|
||||
|---------|------|-----------|
|
||||
| koala | GPU inference, heavy compute | RTX 5070, runs k3s + llama-swap + shared postgres18/pgvector |
|
||||
| iguana | Services, builds | M2 Ultra Mac |
|
||||
| flamingo | Daily driver, edge | Mac mini, ~/dev is here |
|
||||
|
||||
- **Model routing**: LiteLLM in front of llama-swap (local) + cloud APIs (when permitted)
|
||||
- **Orchestration**: k3s cluster across all three machines
|
||||
- **Networking**: Tailscale mesh
|
||||
|
||||
## Project landscape
|
||||
|
||||
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
||||
|
||||
Organized in thematic folders:
|
||||
|
||||
| Folder | Focus | Count |
|
||||
|--------|-------|-------|
|
||||
| `GO/` | Go web frameworks, API integrations, learning projects | ~10 |
|
||||
| `AI/` | ML research, AI frameworks (FinRL, DSPy, crawl4ai) | ~6 |
|
||||
| `AGENTS/` | Autonomous agents, coding agents, MCP servers, infra | ~15 |
|
||||
| `QKX/` | Invoice processing, financial automation, payment systems | ~13 |
|
||||
| `XT/` | Climate data, sustainability (Klimatkollen, Garbo) | ~2 |
|
||||
|
||||
See `~/dev/PROJECT_SUMMARY.md` for detailed descriptions of each project.
|
||||
|
||||
### Key active projects
|
||||
|
||||
- **super-koala** (`AGENTS/`) — multi-component agent stack with LangGraph, DSPy, MCP
|
||||
- **azure-tiger** (`QKX/`) — invoice extraction → ISO 20022 payment instructions
|
||||
- **gocrwl** (`AGENTS/`) — Go web crawler with containerized deployment
|
||||
- **koala-ai-stack** (`AGENTS/`) — local AI server infrastructure management
|
||||
- **klimatkollen** (`XT/`) — Swedish municipal climate data platform
|
||||
|
||||
## Knowledge base — actively use it
|
||||
|
||||
A persistent brain (BM25 search + LLM-synthesised Q&A) survives across sessions,
|
||||
hosts, and harnesses. It holds 100+ hard-won entries: infra incident postmortems,
|
||||
Go pitfalls, framework gotchas, design principles, ADRs. **It is not optional
|
||||
reference material — query it actively, not just when explicitly told.**
|
||||
|
||||
### When to query (treat as a reflex)
|
||||
|
||||
- **Before** starting a non-trivial task — search for prior art with the symptom
|
||||
AND the system component ("how did we solve X in Y?"). 5 seconds beats 5 hours.
|
||||
- **When debugging** — search for the error string, the stack frame, the affected
|
||||
service. Past you may have already paid this tax.
|
||||
- **Before adopting** a pattern, library, framework, or model name — check if it
|
||||
was tried and rejected, or what the integration footguns are.
|
||||
- **When making architectural decisions** — search for the domain + "ADR" or
|
||||
"decision" to find prior reasoning before re-deriving it.
|
||||
- **When a recommendation feels novel** — challenge yourself: "has this been
|
||||
documented?" The brain often has it.
|
||||
|
||||
### When to write
|
||||
|
||||
After you discover something that **future-you would forget** and that **isn't
|
||||
recoverable from the code, git log, or PR description alone**:
|
||||
|
||||
- Bugs whose root cause is non-obvious and generalisable beyond this project.
|
||||
- Framework / library / model-name quirks that bit you and would bite anyone.
|
||||
- Design principles validated under fire (e.g. "every `_get` needs a `_list`").
|
||||
- Postmortems for incidents: what broke, why, how diagnosed, what to do next time.
|
||||
|
||||
DON'T write project status, sprint progress, PR summaries, or "what I did this
|
||||
session" — those rot fast and the originals are in git/gitea anyway. Brain
|
||||
entries that age well are about *why*, *how to avoid*, and *what to do when*.
|
||||
|
||||
### How to access (per harness)
|
||||
|
||||
| Harness | Query | Write |
|
||||
|---------|-------|-------|
|
||||
| **Claude Code, Claude Desktop** | `brain_query` (BM25), `brain_answer` (LLM-synth + sources) MCP tools | `brain_write` MCP tool |
|
||||
| **Crush, Pi, Antigravity, other MCP-capable** | same MCP server: `ingestion-brain` (via the `mcp__*_brain__*` namespace once authenticated) | same |
|
||||
| **Anything HTTP-only (curl, scripts)** | `POST https://brain-mcp.d-ma.be/query` with `{"query":"..."}` (auth via `BRAIN_MCP_TOKEN`) | `POST .../write` with `{"content":"...","filename":"..."}` |
|
||||
| **Browser / human inspection** | `https://git.d-ma.be/mathias/hyperguild` → `knowledge/` and `wiki/` markdown files |
|
||||
|
||||
- **Scoping**: defaults to `public` collection; client projects filter to `{client}` + `public`.
|
||||
- **Routing**: brain_answer's LLM uses berget.ai as primary, iguana ollama as
|
||||
fallback. Both are configurable in the `supervisor/ingestion-deployment.yaml`
|
||||
on the koala k3s cluster; don't hardcode local-only model names into the
|
||||
berget URL (see knowledge entry on namespace mismatches).
|
||||
|
||||
### Quick reflex checks
|
||||
|
||||
If you find yourself about to say any of these out loud, you owe yourself a brain query first:
|
||||
|
||||
- "I think the issue might be..."
|
||||
- "Let me try X and see..."
|
||||
- "I'll just write a script to..."
|
||||
- "This is probably a new bug..."
|
||||
- "Has anyone done this before?" — *yes, probably, go check.*
|
||||
|
||||
## Client work rules
|
||||
|
||||
When working on a project tagged with a client name:
|
||||
1. Never send code, data, or context to cloud APIs — use local models only
|
||||
2. Never reference other client projects or their data
|
||||
3. Keep all artifacts within the client's git org / directory
|
||||
4. Treat everything as confidential unless told otherwise
|
||||
|
||||
## Harness-agnostic principles
|
||||
|
||||
This context is designed to work with any AI coding tool:
|
||||
- Claude Code, Cursor, Aider, Open WebUI, Charmbracelet Mods/Crush
|
||||
- Pi Coding Agent, Mistral Vibe, Antigravity
|
||||
- Any tool that accepts a system prompt or reads a markdown context file
|
||||
|
||||
The canonical source is always `.context/AGENT.md` (root) and `.context/PROJECT.md` (per-project).
|
||||
Derived files are committed (see *How context propagates* below) so a `git pull` on any host yields full agent context with no setup.
|
||||
|
||||
## How context propagates
|
||||
|
||||
Canonical sources of truth:
|
||||
- Universal: `~/dev/.context/AGENT.md` (this file)
|
||||
- Project: `<repo>/.context/PROJECT.md` (per-repo)
|
||||
|
||||
Derived files (committed, regenerated by `task context:sync`):
|
||||
- `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.aider.conventions.md`,
|
||||
`.context/system-prompt.txt`
|
||||
|
||||
Workflow:
|
||||
1. Edit a canonical file. Run `task context:sync`. Commit canonical and
|
||||
derived together. Push.
|
||||
2. On any other host, `git pull` brings both. Claude Code (tree-walking)
|
||||
uses `CLAUDE.md`; Crush / Pi / Antigravity (cwd-only) use `AGENTS.md`;
|
||||
Cursor uses `.cursorrules`; Aider uses `.aider.conventions.md`.
|
||||
3. `task check` runs `context:sync` then asserts `git status --porcelain`
|
||||
is empty over the derived files (catches both modified-tracked drift
|
||||
and missing-untracked adapters). A drift fails the check with a
|
||||
message telling you to stage the regenerated files.
|
||||
|
||||
Behavior rules in this file and per-project rules in `PROJECT.md` apply
|
||||
unconditionally on every host, every harness.
|
||||
|
||||
## Engineering Skills
|
||||
|
||||
Shared engineering skills live in the **`mathias/skills`** repo (`git.d-ma.be/mathias/skills`). Clone it to `~/dev/skills/` and run `SKILLS_CHECKOUT_DIR="$PWD" bash install.sh` there to wire every skill into your harnesses (Claude Code, Crush, Antigravity, Mistral Vibe) as native, on-demand skills. (Use `install.sh`, not `task install` — the latter is currently broken, skills#7.) Load at task start — not "on demand" but on schedule, before writing code. Browse `~/dev/skills/SKILLS_INDEX.md` for the full list.
|
||||
|
||||
**Skill trigger table — load before starting, not after getting stuck:**
|
||||
|
||||
| Task type | Load |
|
||||
|-----------|------|
|
||||
| Any feature or bug fix | `tdd` |
|
||||
| Refactor or design | `clean-code` or `solid` |
|
||||
| Debug | `problem-analysis` |
|
||||
| Review code or PRs | `code-review` |
|
||||
| Frame a problem before coding | `problem-analysis` |
|
||||
|
||||
---
|
||||
|
||||
# cad-atlas
|
||||
|
||||
## Identity
|
||||
@@ -12,9 +291,87 @@ Follow all conventions from both the root agent context and project context.
|
||||
- **Client**: personal
|
||||
- **Repo**: git.d-ma.be/mathias/cad-atlas
|
||||
- **Status**: active
|
||||
- **Stack**: Go + Templ + HTMX + CDN Tailwind (template-go-web). Cross-project conventions: `~/dev/.context/AGENT.md`.
|
||||
|
||||
## Stack
|
||||
## What this is
|
||||
|
||||
Go + Templ + HTMX + CDN Tailwind. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
||||
A visual **atlas of the Continuous Agentic Development (CAD) workflow** — the full path
|
||||
from a captured signal to a deployed k3s pod, one screen, reel-style ("From Signal to Pod").
|
||||
It exists to (a) make the homelab's agentic delivery pipeline legible to a human, and
|
||||
(b) render the CAD **audit chain** — which doubles as the regulated-industry audit artifact.
|
||||
|
||||
> **Core thesis:** the CAD audit chain *is* the visualization data.
|
||||
> `TELOS → goal → spec → issue → execution → attestation → deploy` is both the trace and
|
||||
> the audit package. Phase C renders it once and serves two masters (observability + compliance).
|
||||
|
||||
## Phases
|
||||
|
||||
- **Phase A — static hero viz** (current). Self-contained `internal/web/static/cad-atlas.html`,
|
||||
data-driven from a hand-authored `STAGES` array (ground-truth snapshot from brain, 2026-07-19).
|
||||
Served at `/` by `internal/web/handler.go` via `go:embed`. Reel-parity: SVG spine with
|
||||
arrowheads, animated pulse, dashed **feedback bus** (stage 08 → TELOS), replay + slow-mo.
|
||||
- **Phase B — generated-from-source**. Parse brain docs + `.gitea/workflows` + infra manifests
|
||||
→ render the graph so it can't drift from config.
|
||||
- **Phase C — live trace viewer**. Replace the static `STAGES` array with live reads of the
|
||||
`assessor-loop` attestation ledger + brain `session_log` + Gitea run API + Flux events.
|
||||
This is the prize: a real signal→pod trace viewer that is also the audit package.
|
||||
|
||||
## The workflow it visualizes (9 stages)
|
||||
|
||||
`00 Signals` (Applied AI Radar → mathias/signals) → `01 TELOS` (intention substrate) →
|
||||
`02 Strategic session` (claude.ai frontier + LLM Council + Autoresearch Council) →
|
||||
`03 Spec → Gitea issue` (agent-ready contract; Ed25519 admission #36; **var-go Oath**) →
|
||||
`04 Human dispatch gate` (the only checkpoint; session-dispatch bridge → cad-dispatch.yml) →
|
||||
`05 Execute · agentsquad` (serve/taskqueue, exec+review loop, risk LOW/MED/HIGH, dma-cli routing,
|
||||
assessor-loop ledger) → `06 PR → CI` (go test/vet/lint/govulncheck + **var-go/oath gate**) →
|
||||
`07 CD → pod` (Flux GitOps → k3s on koala) → `08 Loop back` (outcome scored vs TELOS goal).
|
||||
|
||||
### Three orthogonal governance gates
|
||||
|
||||
| Gate | Guards | Where |
|
||||
|---|---|---|
|
||||
| Ed25519 admission controller (#36) | spec **integrity** (issue untampered) | stage 03 |
|
||||
| dispatch-allow (`.dispatch-allow` + `mathias/dispatch` allowlist) | repo **eligibility** (may agents run here) | stage 04/05 |
|
||||
| **var-go Oath** (`cmd/vargo-gate`, commit status `var-go/oath`) | output **correctness** (PR satisfies the Oath; floor over reviewer, anti-rubber-stamp #55) | stage 06 |
|
||||
|
||||
## Dogfooding
|
||||
|
||||
This repo is built *through* the workflow it depicts. It is `dispatch-allow`-enabled, and its
|
||||
own build increments are governed by a **var-go Oath** embedded in their spec issues (see the
|
||||
Stage-03 tracking issue). Bootstrapping honesty (per swedsl honest-stub discipline): the Oath is
|
||||
**defined** but `cmd/vargo-gate` is **not yet wired** into this repo's CI — until it is, the Oath
|
||||
is advisory here. Wiring it is a first tracked task; disclosed in code, this doc, and CI config.
|
||||
|
||||
## Brain references (source of truth — `brain_get <path>`)
|
||||
|
||||
- `knowledge/workflow-idea-to-running-service.md` — Double Diamond idea→service workflow
|
||||
- `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16.md` — CAD definition
|
||||
- `wiki/agentsquad/decisions/cad-dispatch-bridge.md` — claude.ai → agentsquad trigger path
|
||||
- `wiki/agentsquad/facts/llm-council-design-and-first-runs-2026-06-21.md` — LLM Council
|
||||
- `wiki/agentsquad/decisions/autoresearch-council-sibling-pipe.md` — Autoresearch Council
|
||||
- `wiki/agentsquad/decisions/serve-http-task-api.md` — agentsquad serve/taskqueue
|
||||
- `knowledge/var-go-anchor-to-span-spike-verdict.md` — var-go runner + CAD gate seam
|
||||
- `knowledge/swedsl-vargo-sprint1-enforcement-teeth-verdict.md` — vargo-gate enforcement teeth
|
||||
- `wiki/assessor-loop/decisions/assessor-loop-genesis.md` — attestation ledger (Phase C source)
|
||||
- `wiki/homelab/facts/homelab-network-topology-reference.md` — koala/iguana/flamingo/piguard
|
||||
|
||||
## External references
|
||||
|
||||
- Inspiration reel — "From Inbox to Shipped" pipeline viz: https://www.instagram.com/reel/DY92L7bu27j/
|
||||
- karpathy/llm-council — origin of the Council pattern
|
||||
- Double Diamond design process (Discover/Define/Develop/Deliver)
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
task check # lint + vet + test (CI gate)
|
||||
task run # build + serve at http://localhost:8080 → the atlas
|
||||
```
|
||||
|
||||
## Deploy note
|
||||
|
||||
CD (`.gitea/workflows/cd.yml`) deploys to k3s namespace `cad-atlas` via Flux. Per the known
|
||||
template-go-agent CD gap: the `deploy` job stays RED until `mathias/infra` has
|
||||
`k3s/apps/cad-atlas/deployment.yaml`. `check` + `build` are the real bootstrap gate.
|
||||
|
||||
---
|
||||
|
||||
+359
-2
@@ -1,6 +1,285 @@
|
||||
# Cursor rules — auto-generated
|
||||
# Do not edit. Run: task context:sync
|
||||
|
||||
# Agent context — Mathias workspace
|
||||
|
||||
<!-- Canonical root context for all AI coding agents.
|
||||
Lives at: ~/dev/.context/AGENT.md
|
||||
Applies to every project under ~/dev/ unless overridden.
|
||||
|
||||
Run `task context:sync` from ~/dev/ to regenerate harness-specific files.
|
||||
Project-level context in .context/PROJECT.md layers on top of this. -->
|
||||
|
||||
## Who I am
|
||||
|
||||
I'm Mathias, a digital product manager and technology consultant based in Sweden.
|
||||
I build software, research emerging tech, and deliver consulting engagements
|
||||
for clients under NDA. I work across AI/ML, financial automation, web applications,
|
||||
and climate/sustainability tech.
|
||||
|
||||
## How I work with agents
|
||||
|
||||
- I think like a product manager — I care about *why* before *how*
|
||||
- I want agents to be opinionated and push back, not just execute blindly
|
||||
- I prefer concise responses; skip ceremony and get to the point
|
||||
- When I say "build this", I mean production-quality with tests, not a demo
|
||||
- Ask me before making irreversible changes or adding heavy dependencies
|
||||
- I work with confidential client data — never send it to cloud APIs unless I explicitly say it's OK
|
||||
|
||||
## Behavior rules
|
||||
|
||||
These rules apply to every task across every project, regardless of harness.
|
||||
|
||||
0. **Pre-task ritual — before ANY implementation (non-negotiable).** Run this before writing a single line:
|
||||
- **Query the brain** (`brain_query`) for the domain + symptom. If the result changes your approach, surface it before acting. 5 seconds beats 5 hours.
|
||||
- **Load the relevant skill** — see trigger table in *Engineering Skills* below.
|
||||
- **Write the failing test first.** Name the test before the function. If the target is untestable (e.g. `main()` wiring), extract the logic into a testable function first. No implementation without a red test.
|
||||
- **State the observable success criterion** — what specific behavior, output, or passing test proves this is done?
|
||||
|
||||
**TDD is non-negotiable.** "Tests pass" is not proof of correctness — only proof the tests ran. Write tests that would catch the bug before writing code that fixes it.
|
||||
|
||||
1. **No assumptions.** Don't hide confusion — surface it. Surface tradeoffs explicitly.
|
||||
Think before coding; if the problem is unclear, ask or state assumptions before acting.
|
||||
2. **Minimum viable code.** Solve with the smallest change that works. Nothing
|
||||
speculative, no "while we're here" cleanups, no premature abstractions. Simplicity first.
|
||||
3. **Surgical changes.** Touch only what the task requires. Leave unrelated code,
|
||||
files, and formatting alone. Diffs should be small and reviewable.
|
||||
4. **Goal-driven execution.** Define clear success criteria up front for every task.
|
||||
Loop — implement, verify, refine — until those criteria are met. Don't claim
|
||||
completion without evidence (tests pass, command output, observed behavior).
|
||||
5. **Trunk-Based Development — commit directly to main.** Every commit is one
|
||||
logical change (one tool, one fix, one test) with passing tests. Main is always
|
||||
deployable. Never create long-lived feature branches.
|
||||
|
||||
**Exception — parallel agents on same repo:** If another agent is known to be
|
||||
actively working on the same repo simultaneously, create a short-lived branch
|
||||
(`agent/<description>`), finish the task, and merge to main within the same
|
||||
session. Do not leave agent branches open between sessions.
|
||||
|
||||
**Exception — external contributor or client four-eyes requirement:** Use
|
||||
PR flow only when a human reviewer outside the project is required. Document
|
||||
the reason in PROJECT.md.
|
||||
|
||||
6. **Close the loop — every substantive task ends with the same ritual.** Shipping
|
||||
the code is not the end of the task; capturing it is. Run this unprompted:
|
||||
- **Tag + bump SemVer** on the change (annotated tag; minor for a feature or
|
||||
new/changed ADR, patch for a fix; docs in the same commit). Check the repo's
|
||||
actual last tag — stated versions in docs drift stale.
|
||||
- **Push** main and the tag (CI is the gate).
|
||||
- **Persist generalizable learnings to the brain** (`brain_write`, wing/hall) —
|
||||
the reusable patterns and the footguns that would bite anyone again, never
|
||||
project status. See *Knowledge base — when to write* below.
|
||||
- **File discovered-but-deferred work as tracker issues** on the project's own
|
||||
repo — token-budget gaps, recorded ADR limitations, v2 follow-ups. Don't let
|
||||
"out of scope, recorded" rot in a commit message; make it a ticket with a
|
||||
source pointer.
|
||||
- Surface the brain entries and issue numbers in the closing summary so the
|
||||
trail is auditable.
|
||||
|
||||
## Default stack
|
||||
|
||||
| Layer | Default | Fallback | Last resort |
|
||||
|-------|---------|----------|-------------|
|
||||
| Language | Go | Python | TypeScript, Java, C |
|
||||
| UI | HTMX + Templ | Server-rendered HTML | React (only if SPA is justified) |
|
||||
| Build | Task (taskfile.dev) | Make | — |
|
||||
| Containers | Docker Compose (dev), k3s (prod) | — | — |
|
||||
| DB | PostgreSQL + sqlc | SQLite | — |
|
||||
| Search | pgvector (vector), BM25 | Qdrant (when >1M vectors or hybrid retrieval) | — |
|
||||
| Logging | slog (structured) | — | — |
|
||||
| Testing | Table-driven, testify | — | — |
|
||||
| Agents (Go) | google.golang.org/adk + pkg/litellm adapter | — | — |
|
||||
|
||||
Exploratory: Rust, Zig — I'll tell you when I want these.
|
||||
|
||||
## Code conventions
|
||||
|
||||
- **Go style**: golines, gofumpt, golangci-lint
|
||||
- **Errors**: `fmt.Errorf("operation: %w", err)` — never naked, never log-and-return
|
||||
- **Naming**: stdlib conventions, no stuttering
|
||||
- **Architecture**: prefer stdlib over frameworks, constructor injection, env-var config parsed into typed structs
|
||||
- **Git**: conventional commits (`feat:`, `fix:`, `chore:`), commit directly to main,
|
||||
one logical change per commit, CI is the quality gate
|
||||
- **Never**: long-lived feature branches, PRs for solo work, direct push without
|
||||
passing `task check` locally first
|
||||
- **Security**: no secrets in code, govulncheck before adding deps, SOPS for encrypted config
|
||||
- **Dependencies**: prefer stdlib. testify, slog, templ, sqlc, google.golang.org/adk (agent projects only) are pre-approved; anything else needs justification in the commit message
|
||||
|
||||
## Secret handling (every harness, every command)
|
||||
|
||||
Tool output is persisted: terminal → `~/.claude/projects` transcripts →
|
||||
claudewatcher → brain/wiki → gitea history. A secret printed once is
|
||||
searchable forever, and clearing it means rotating the key. So:
|
||||
|
||||
1. **Never print, echo, log, or transform a secret to inspect it.** No
|
||||
`base64`/`xxd`/`cat` of a key, and never pipe a secret through a transform
|
||||
to defeat `op run`'s output masking (it masks raw values; base64 hides them
|
||||
from the mask — that exact trick leaked a key on 2026-06-11).
|
||||
2. **Secrets stay in the subprocess.** Reference them only as env vars consumed
|
||||
*inside* `op run --env-file ~/.op-env -- <cmd>`. Never place a literal secret
|
||||
in a command's argv (it lands in the tool call and the transcript).
|
||||
3. **Existence check without revealing the value:** `[ -n "$X" ] && echo set` —
|
||||
never `${X:-...}` (returns the value when set) and never echo a substring of it.
|
||||
4. **Cross-host secrets:** run the secret-consuming command on the host that has
|
||||
the secret; do not forward a raw key over ssh argv/stdout.
|
||||
5. If a secret does leak into output, say so immediately and flag it for rotation —
|
||||
don't bury it.
|
||||
|
||||
## Infrastructure
|
||||
|
||||
Three machines on Tailscale:
|
||||
|
||||
| Machine | Role | Key specs |
|
||||
|---------|------|-----------|
|
||||
| koala | GPU inference, heavy compute | RTX 5070, runs k3s + llama-swap + shared postgres18/pgvector |
|
||||
| iguana | Services, builds | M2 Ultra Mac |
|
||||
| flamingo | Daily driver, edge | Mac mini, ~/dev is here |
|
||||
|
||||
- **Model routing**: LiteLLM in front of llama-swap (local) + cloud APIs (when permitted)
|
||||
- **Orchestration**: k3s cluster across all three machines
|
||||
- **Networking**: Tailscale mesh
|
||||
|
||||
## Project landscape
|
||||
|
||||
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
||||
|
||||
Organized in thematic folders:
|
||||
|
||||
| Folder | Focus | Count |
|
||||
|--------|-------|-------|
|
||||
| `GO/` | Go web frameworks, API integrations, learning projects | ~10 |
|
||||
| `AI/` | ML research, AI frameworks (FinRL, DSPy, crawl4ai) | ~6 |
|
||||
| `AGENTS/` | Autonomous agents, coding agents, MCP servers, infra | ~15 |
|
||||
| `QKX/` | Invoice processing, financial automation, payment systems | ~13 |
|
||||
| `XT/` | Climate data, sustainability (Klimatkollen, Garbo) | ~2 |
|
||||
|
||||
See `~/dev/PROJECT_SUMMARY.md` for detailed descriptions of each project.
|
||||
|
||||
### Key active projects
|
||||
|
||||
- **super-koala** (`AGENTS/`) — multi-component agent stack with LangGraph, DSPy, MCP
|
||||
- **azure-tiger** (`QKX/`) — invoice extraction → ISO 20022 payment instructions
|
||||
- **gocrwl** (`AGENTS/`) — Go web crawler with containerized deployment
|
||||
- **koala-ai-stack** (`AGENTS/`) — local AI server infrastructure management
|
||||
- **klimatkollen** (`XT/`) — Swedish municipal climate data platform
|
||||
|
||||
## Knowledge base — actively use it
|
||||
|
||||
A persistent brain (BM25 search + LLM-synthesised Q&A) survives across sessions,
|
||||
hosts, and harnesses. It holds 100+ hard-won entries: infra incident postmortems,
|
||||
Go pitfalls, framework gotchas, design principles, ADRs. **It is not optional
|
||||
reference material — query it actively, not just when explicitly told.**
|
||||
|
||||
### When to query (treat as a reflex)
|
||||
|
||||
- **Before** starting a non-trivial task — search for prior art with the symptom
|
||||
AND the system component ("how did we solve X in Y?"). 5 seconds beats 5 hours.
|
||||
- **When debugging** — search for the error string, the stack frame, the affected
|
||||
service. Past you may have already paid this tax.
|
||||
- **Before adopting** a pattern, library, framework, or model name — check if it
|
||||
was tried and rejected, or what the integration footguns are.
|
||||
- **When making architectural decisions** — search for the domain + "ADR" or
|
||||
"decision" to find prior reasoning before re-deriving it.
|
||||
- **When a recommendation feels novel** — challenge yourself: "has this been
|
||||
documented?" The brain often has it.
|
||||
|
||||
### When to write
|
||||
|
||||
After you discover something that **future-you would forget** and that **isn't
|
||||
recoverable from the code, git log, or PR description alone**:
|
||||
|
||||
- Bugs whose root cause is non-obvious and generalisable beyond this project.
|
||||
- Framework / library / model-name quirks that bit you and would bite anyone.
|
||||
- Design principles validated under fire (e.g. "every `_get` needs a `_list`").
|
||||
- Postmortems for incidents: what broke, why, how diagnosed, what to do next time.
|
||||
|
||||
DON'T write project status, sprint progress, PR summaries, or "what I did this
|
||||
session" — those rot fast and the originals are in git/gitea anyway. Brain
|
||||
entries that age well are about *why*, *how to avoid*, and *what to do when*.
|
||||
|
||||
### How to access (per harness)
|
||||
|
||||
| Harness | Query | Write |
|
||||
|---------|-------|-------|
|
||||
| **Claude Code, Claude Desktop** | `brain_query` (BM25), `brain_answer` (LLM-synth + sources) MCP tools | `brain_write` MCP tool |
|
||||
| **Crush, Pi, Antigravity, other MCP-capable** | same MCP server: `ingestion-brain` (via the `mcp__*_brain__*` namespace once authenticated) | same |
|
||||
| **Anything HTTP-only (curl, scripts)** | `POST https://brain-mcp.d-ma.be/query` with `{"query":"..."}` (auth via `BRAIN_MCP_TOKEN`) | `POST .../write` with `{"content":"...","filename":"..."}` |
|
||||
| **Browser / human inspection** | `https://git.d-ma.be/mathias/hyperguild` → `knowledge/` and `wiki/` markdown files |
|
||||
|
||||
- **Scoping**: defaults to `public` collection; client projects filter to `{client}` + `public`.
|
||||
- **Routing**: brain_answer's LLM uses berget.ai as primary, iguana ollama as
|
||||
fallback. Both are configurable in the `supervisor/ingestion-deployment.yaml`
|
||||
on the koala k3s cluster; don't hardcode local-only model names into the
|
||||
berget URL (see knowledge entry on namespace mismatches).
|
||||
|
||||
### Quick reflex checks
|
||||
|
||||
If you find yourself about to say any of these out loud, you owe yourself a brain query first:
|
||||
|
||||
- "I think the issue might be..."
|
||||
- "Let me try X and see..."
|
||||
- "I'll just write a script to..."
|
||||
- "This is probably a new bug..."
|
||||
- "Has anyone done this before?" — *yes, probably, go check.*
|
||||
|
||||
## Client work rules
|
||||
|
||||
When working on a project tagged with a client name:
|
||||
1. Never send code, data, or context to cloud APIs — use local models only
|
||||
2. Never reference other client projects or their data
|
||||
3. Keep all artifacts within the client's git org / directory
|
||||
4. Treat everything as confidential unless told otherwise
|
||||
|
||||
## Harness-agnostic principles
|
||||
|
||||
This context is designed to work with any AI coding tool:
|
||||
- Claude Code, Cursor, Aider, Open WebUI, Charmbracelet Mods/Crush
|
||||
- Pi Coding Agent, Mistral Vibe, Antigravity
|
||||
- Any tool that accepts a system prompt or reads a markdown context file
|
||||
|
||||
The canonical source is always `.context/AGENT.md` (root) and `.context/PROJECT.md` (per-project).
|
||||
Derived files are committed (see *How context propagates* below) so a `git pull` on any host yields full agent context with no setup.
|
||||
|
||||
## How context propagates
|
||||
|
||||
Canonical sources of truth:
|
||||
- Universal: `~/dev/.context/AGENT.md` (this file)
|
||||
- Project: `<repo>/.context/PROJECT.md` (per-repo)
|
||||
|
||||
Derived files (committed, regenerated by `task context:sync`):
|
||||
- `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.aider.conventions.md`,
|
||||
`.context/system-prompt.txt`
|
||||
|
||||
Workflow:
|
||||
1. Edit a canonical file. Run `task context:sync`. Commit canonical and
|
||||
derived together. Push.
|
||||
2. On any other host, `git pull` brings both. Claude Code (tree-walking)
|
||||
uses `CLAUDE.md`; Crush / Pi / Antigravity (cwd-only) use `AGENTS.md`;
|
||||
Cursor uses `.cursorrules`; Aider uses `.aider.conventions.md`.
|
||||
3. `task check` runs `context:sync` then asserts `git status --porcelain`
|
||||
is empty over the derived files (catches both modified-tracked drift
|
||||
and missing-untracked adapters). A drift fails the check with a
|
||||
message telling you to stage the regenerated files.
|
||||
|
||||
Behavior rules in this file and per-project rules in `PROJECT.md` apply
|
||||
unconditionally on every host, every harness.
|
||||
|
||||
## Engineering Skills
|
||||
|
||||
Shared engineering skills live in the **`mathias/skills`** repo (`git.d-ma.be/mathias/skills`). Clone it to `~/dev/skills/` and run `SKILLS_CHECKOUT_DIR="$PWD" bash install.sh` there to wire every skill into your harnesses (Claude Code, Crush, Antigravity, Mistral Vibe) as native, on-demand skills. (Use `install.sh`, not `task install` — the latter is currently broken, skills#7.) Load at task start — not "on demand" but on schedule, before writing code. Browse `~/dev/skills/SKILLS_INDEX.md` for the full list.
|
||||
|
||||
**Skill trigger table — load before starting, not after getting stuck:**
|
||||
|
||||
| Task type | Load |
|
||||
|-----------|------|
|
||||
| Any feature or bug fix | `tdd` |
|
||||
| Refactor or design | `clean-code` or `solid` |
|
||||
| Debug | `problem-analysis` |
|
||||
| Review code or PRs | `code-review` |
|
||||
| Frame a problem before coding | `problem-analysis` |
|
||||
|
||||
---
|
||||
|
||||
# cad-atlas
|
||||
|
||||
## Identity
|
||||
@@ -10,7 +289,85 @@
|
||||
- **Client**: personal
|
||||
- **Repo**: git.d-ma.be/mathias/cad-atlas
|
||||
- **Status**: active
|
||||
- **Stack**: Go + Templ + HTMX + CDN Tailwind (template-go-web). Cross-project conventions: `~/dev/.context/AGENT.md`.
|
||||
|
||||
## Stack
|
||||
## What this is
|
||||
|
||||
Go + Templ + HTMX + CDN Tailwind. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
||||
A visual **atlas of the Continuous Agentic Development (CAD) workflow** — the full path
|
||||
from a captured signal to a deployed k3s pod, one screen, reel-style ("From Signal to Pod").
|
||||
It exists to (a) make the homelab's agentic delivery pipeline legible to a human, and
|
||||
(b) render the CAD **audit chain** — which doubles as the regulated-industry audit artifact.
|
||||
|
||||
> **Core thesis:** the CAD audit chain *is* the visualization data.
|
||||
> `TELOS → goal → spec → issue → execution → attestation → deploy` is both the trace and
|
||||
> the audit package. Phase C renders it once and serves two masters (observability + compliance).
|
||||
|
||||
## Phases
|
||||
|
||||
- **Phase A — static hero viz** (current). Self-contained `internal/web/static/cad-atlas.html`,
|
||||
data-driven from a hand-authored `STAGES` array (ground-truth snapshot from brain, 2026-07-19).
|
||||
Served at `/` by `internal/web/handler.go` via `go:embed`. Reel-parity: SVG spine with
|
||||
arrowheads, animated pulse, dashed **feedback bus** (stage 08 → TELOS), replay + slow-mo.
|
||||
- **Phase B — generated-from-source**. Parse brain docs + `.gitea/workflows` + infra manifests
|
||||
→ render the graph so it can't drift from config.
|
||||
- **Phase C — live trace viewer**. Replace the static `STAGES` array with live reads of the
|
||||
`assessor-loop` attestation ledger + brain `session_log` + Gitea run API + Flux events.
|
||||
This is the prize: a real signal→pod trace viewer that is also the audit package.
|
||||
|
||||
## The workflow it visualizes (9 stages)
|
||||
|
||||
`00 Signals` (Applied AI Radar → mathias/signals) → `01 TELOS` (intention substrate) →
|
||||
`02 Strategic session` (claude.ai frontier + LLM Council + Autoresearch Council) →
|
||||
`03 Spec → Gitea issue` (agent-ready contract; Ed25519 admission #36; **var-go Oath**) →
|
||||
`04 Human dispatch gate` (the only checkpoint; session-dispatch bridge → cad-dispatch.yml) →
|
||||
`05 Execute · agentsquad` (serve/taskqueue, exec+review loop, risk LOW/MED/HIGH, dma-cli routing,
|
||||
assessor-loop ledger) → `06 PR → CI` (go test/vet/lint/govulncheck + **var-go/oath gate**) →
|
||||
`07 CD → pod` (Flux GitOps → k3s on koala) → `08 Loop back` (outcome scored vs TELOS goal).
|
||||
|
||||
### Three orthogonal governance gates
|
||||
|
||||
| Gate | Guards | Where |
|
||||
|---|---|---|
|
||||
| Ed25519 admission controller (#36) | spec **integrity** (issue untampered) | stage 03 |
|
||||
| dispatch-allow (`.dispatch-allow` + `mathias/dispatch` allowlist) | repo **eligibility** (may agents run here) | stage 04/05 |
|
||||
| **var-go Oath** (`cmd/vargo-gate`, commit status `var-go/oath`) | output **correctness** (PR satisfies the Oath; floor over reviewer, anti-rubber-stamp #55) | stage 06 |
|
||||
|
||||
## Dogfooding
|
||||
|
||||
This repo is built *through* the workflow it depicts. It is `dispatch-allow`-enabled, and its
|
||||
own build increments are governed by a **var-go Oath** embedded in their spec issues (see the
|
||||
Stage-03 tracking issue). Bootstrapping honesty (per swedsl honest-stub discipline): the Oath is
|
||||
**defined** but `cmd/vargo-gate` is **not yet wired** into this repo's CI — until it is, the Oath
|
||||
is advisory here. Wiring it is a first tracked task; disclosed in code, this doc, and CI config.
|
||||
|
||||
## Brain references (source of truth — `brain_get <path>`)
|
||||
|
||||
- `knowledge/workflow-idea-to-running-service.md` — Double Diamond idea→service workflow
|
||||
- `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16.md` — CAD definition
|
||||
- `wiki/agentsquad/decisions/cad-dispatch-bridge.md` — claude.ai → agentsquad trigger path
|
||||
- `wiki/agentsquad/facts/llm-council-design-and-first-runs-2026-06-21.md` — LLM Council
|
||||
- `wiki/agentsquad/decisions/autoresearch-council-sibling-pipe.md` — Autoresearch Council
|
||||
- `wiki/agentsquad/decisions/serve-http-task-api.md` — agentsquad serve/taskqueue
|
||||
- `knowledge/var-go-anchor-to-span-spike-verdict.md` — var-go runner + CAD gate seam
|
||||
- `knowledge/swedsl-vargo-sprint1-enforcement-teeth-verdict.md` — vargo-gate enforcement teeth
|
||||
- `wiki/assessor-loop/decisions/assessor-loop-genesis.md` — attestation ledger (Phase C source)
|
||||
- `wiki/homelab/facts/homelab-network-topology-reference.md` — koala/iguana/flamingo/piguard
|
||||
|
||||
## External references
|
||||
|
||||
- Inspiration reel — "From Inbox to Shipped" pipeline viz: https://www.instagram.com/reel/DY92L7bu27j/
|
||||
- karpathy/llm-council — origin of the Council pattern
|
||||
- Double Diamond design process (Discover/Define/Develop/Deliver)
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
task check # lint + vet + test (CI gate)
|
||||
task run # build + serve at http://localhost:8080 → the atlas
|
||||
```
|
||||
|
||||
## Deploy note
|
||||
|
||||
CD (`.gitea/workflows/cd.yml`) deploys to k3s namespace `cad-atlas` via Flux. Per the known
|
||||
template-go-agent CD gap: the `deploy` job stays RED until `mathias/infra` has
|
||||
`k3s/apps/cad-atlas/deployment.yaml`. `check` + `build` are the real bootstrap gate.
|
||||
|
||||
+1
-1
@@ -27,4 +27,4 @@ go.work.sum
|
||||
|
||||
# Project-specific
|
||||
bin/
|
||||
*.templ.go
|
||||
*_templ.go
|
||||
|
||||
@@ -1,3 +1,282 @@
|
||||
# Agent context — Mathias workspace
|
||||
|
||||
<!-- Canonical root context for all AI coding agents.
|
||||
Lives at: ~/dev/.context/AGENT.md
|
||||
Applies to every project under ~/dev/ unless overridden.
|
||||
|
||||
Run `task context:sync` from ~/dev/ to regenerate harness-specific files.
|
||||
Project-level context in .context/PROJECT.md layers on top of this. -->
|
||||
|
||||
## Who I am
|
||||
|
||||
I'm Mathias, a digital product manager and technology consultant based in Sweden.
|
||||
I build software, research emerging tech, and deliver consulting engagements
|
||||
for clients under NDA. I work across AI/ML, financial automation, web applications,
|
||||
and climate/sustainability tech.
|
||||
|
||||
## How I work with agents
|
||||
|
||||
- I think like a product manager — I care about *why* before *how*
|
||||
- I want agents to be opinionated and push back, not just execute blindly
|
||||
- I prefer concise responses; skip ceremony and get to the point
|
||||
- When I say "build this", I mean production-quality with tests, not a demo
|
||||
- Ask me before making irreversible changes or adding heavy dependencies
|
||||
- I work with confidential client data — never send it to cloud APIs unless I explicitly say it's OK
|
||||
|
||||
## Behavior rules
|
||||
|
||||
These rules apply to every task across every project, regardless of harness.
|
||||
|
||||
0. **Pre-task ritual — before ANY implementation (non-negotiable).** Run this before writing a single line:
|
||||
- **Query the brain** (`brain_query`) for the domain + symptom. If the result changes your approach, surface it before acting. 5 seconds beats 5 hours.
|
||||
- **Load the relevant skill** — see trigger table in *Engineering Skills* below.
|
||||
- **Write the failing test first.** Name the test before the function. If the target is untestable (e.g. `main()` wiring), extract the logic into a testable function first. No implementation without a red test.
|
||||
- **State the observable success criterion** — what specific behavior, output, or passing test proves this is done?
|
||||
|
||||
**TDD is non-negotiable.** "Tests pass" is not proof of correctness — only proof the tests ran. Write tests that would catch the bug before writing code that fixes it.
|
||||
|
||||
1. **No assumptions.** Don't hide confusion — surface it. Surface tradeoffs explicitly.
|
||||
Think before coding; if the problem is unclear, ask or state assumptions before acting.
|
||||
2. **Minimum viable code.** Solve with the smallest change that works. Nothing
|
||||
speculative, no "while we're here" cleanups, no premature abstractions. Simplicity first.
|
||||
3. **Surgical changes.** Touch only what the task requires. Leave unrelated code,
|
||||
files, and formatting alone. Diffs should be small and reviewable.
|
||||
4. **Goal-driven execution.** Define clear success criteria up front for every task.
|
||||
Loop — implement, verify, refine — until those criteria are met. Don't claim
|
||||
completion without evidence (tests pass, command output, observed behavior).
|
||||
5. **Trunk-Based Development — commit directly to main.** Every commit is one
|
||||
logical change (one tool, one fix, one test) with passing tests. Main is always
|
||||
deployable. Never create long-lived feature branches.
|
||||
|
||||
**Exception — parallel agents on same repo:** If another agent is known to be
|
||||
actively working on the same repo simultaneously, create a short-lived branch
|
||||
(`agent/<description>`), finish the task, and merge to main within the same
|
||||
session. Do not leave agent branches open between sessions.
|
||||
|
||||
**Exception — external contributor or client four-eyes requirement:** Use
|
||||
PR flow only when a human reviewer outside the project is required. Document
|
||||
the reason in PROJECT.md.
|
||||
|
||||
6. **Close the loop — every substantive task ends with the same ritual.** Shipping
|
||||
the code is not the end of the task; capturing it is. Run this unprompted:
|
||||
- **Tag + bump SemVer** on the change (annotated tag; minor for a feature or
|
||||
new/changed ADR, patch for a fix; docs in the same commit). Check the repo's
|
||||
actual last tag — stated versions in docs drift stale.
|
||||
- **Push** main and the tag (CI is the gate).
|
||||
- **Persist generalizable learnings to the brain** (`brain_write`, wing/hall) —
|
||||
the reusable patterns and the footguns that would bite anyone again, never
|
||||
project status. See *Knowledge base — when to write* below.
|
||||
- **File discovered-but-deferred work as tracker issues** on the project's own
|
||||
repo — token-budget gaps, recorded ADR limitations, v2 follow-ups. Don't let
|
||||
"out of scope, recorded" rot in a commit message; make it a ticket with a
|
||||
source pointer.
|
||||
- Surface the brain entries and issue numbers in the closing summary so the
|
||||
trail is auditable.
|
||||
|
||||
## Default stack
|
||||
|
||||
| Layer | Default | Fallback | Last resort |
|
||||
|-------|---------|----------|-------------|
|
||||
| Language | Go | Python | TypeScript, Java, C |
|
||||
| UI | HTMX + Templ | Server-rendered HTML | React (only if SPA is justified) |
|
||||
| Build | Task (taskfile.dev) | Make | — |
|
||||
| Containers | Docker Compose (dev), k3s (prod) | — | — |
|
||||
| DB | PostgreSQL + sqlc | SQLite | — |
|
||||
| Search | pgvector (vector), BM25 | Qdrant (when >1M vectors or hybrid retrieval) | — |
|
||||
| Logging | slog (structured) | — | — |
|
||||
| Testing | Table-driven, testify | — | — |
|
||||
| Agents (Go) | google.golang.org/adk + pkg/litellm adapter | — | — |
|
||||
|
||||
Exploratory: Rust, Zig — I'll tell you when I want these.
|
||||
|
||||
## Code conventions
|
||||
|
||||
- **Go style**: golines, gofumpt, golangci-lint
|
||||
- **Errors**: `fmt.Errorf("operation: %w", err)` — never naked, never log-and-return
|
||||
- **Naming**: stdlib conventions, no stuttering
|
||||
- **Architecture**: prefer stdlib over frameworks, constructor injection, env-var config parsed into typed structs
|
||||
- **Git**: conventional commits (`feat:`, `fix:`, `chore:`), commit directly to main,
|
||||
one logical change per commit, CI is the quality gate
|
||||
- **Never**: long-lived feature branches, PRs for solo work, direct push without
|
||||
passing `task check` locally first
|
||||
- **Security**: no secrets in code, govulncheck before adding deps, SOPS for encrypted config
|
||||
- **Dependencies**: prefer stdlib. testify, slog, templ, sqlc, google.golang.org/adk (agent projects only) are pre-approved; anything else needs justification in the commit message
|
||||
|
||||
## Secret handling (every harness, every command)
|
||||
|
||||
Tool output is persisted: terminal → `~/.claude/projects` transcripts →
|
||||
claudewatcher → brain/wiki → gitea history. A secret printed once is
|
||||
searchable forever, and clearing it means rotating the key. So:
|
||||
|
||||
1. **Never print, echo, log, or transform a secret to inspect it.** No
|
||||
`base64`/`xxd`/`cat` of a key, and never pipe a secret through a transform
|
||||
to defeat `op run`'s output masking (it masks raw values; base64 hides them
|
||||
from the mask — that exact trick leaked a key on 2026-06-11).
|
||||
2. **Secrets stay in the subprocess.** Reference them only as env vars consumed
|
||||
*inside* `op run --env-file ~/.op-env -- <cmd>`. Never place a literal secret
|
||||
in a command's argv (it lands in the tool call and the transcript).
|
||||
3. **Existence check without revealing the value:** `[ -n "$X" ] && echo set` —
|
||||
never `${X:-...}` (returns the value when set) and never echo a substring of it.
|
||||
4. **Cross-host secrets:** run the secret-consuming command on the host that has
|
||||
the secret; do not forward a raw key over ssh argv/stdout.
|
||||
5. If a secret does leak into output, say so immediately and flag it for rotation —
|
||||
don't bury it.
|
||||
|
||||
## Infrastructure
|
||||
|
||||
Three machines on Tailscale:
|
||||
|
||||
| Machine | Role | Key specs |
|
||||
|---------|------|-----------|
|
||||
| koala | GPU inference, heavy compute | RTX 5070, runs k3s + llama-swap + shared postgres18/pgvector |
|
||||
| iguana | Services, builds | M2 Ultra Mac |
|
||||
| flamingo | Daily driver, edge | Mac mini, ~/dev is here |
|
||||
|
||||
- **Model routing**: LiteLLM in front of llama-swap (local) + cloud APIs (when permitted)
|
||||
- **Orchestration**: k3s cluster across all three machines
|
||||
- **Networking**: Tailscale mesh
|
||||
|
||||
## Project landscape
|
||||
|
||||
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
||||
|
||||
Organized in thematic folders:
|
||||
|
||||
| Folder | Focus | Count |
|
||||
|--------|-------|-------|
|
||||
| `GO/` | Go web frameworks, API integrations, learning projects | ~10 |
|
||||
| `AI/` | ML research, AI frameworks (FinRL, DSPy, crawl4ai) | ~6 |
|
||||
| `AGENTS/` | Autonomous agents, coding agents, MCP servers, infra | ~15 |
|
||||
| `QKX/` | Invoice processing, financial automation, payment systems | ~13 |
|
||||
| `XT/` | Climate data, sustainability (Klimatkollen, Garbo) | ~2 |
|
||||
|
||||
See `~/dev/PROJECT_SUMMARY.md` for detailed descriptions of each project.
|
||||
|
||||
### Key active projects
|
||||
|
||||
- **super-koala** (`AGENTS/`) — multi-component agent stack with LangGraph, DSPy, MCP
|
||||
- **azure-tiger** (`QKX/`) — invoice extraction → ISO 20022 payment instructions
|
||||
- **gocrwl** (`AGENTS/`) — Go web crawler with containerized deployment
|
||||
- **koala-ai-stack** (`AGENTS/`) — local AI server infrastructure management
|
||||
- **klimatkollen** (`XT/`) — Swedish municipal climate data platform
|
||||
|
||||
## Knowledge base — actively use it
|
||||
|
||||
A persistent brain (BM25 search + LLM-synthesised Q&A) survives across sessions,
|
||||
hosts, and harnesses. It holds 100+ hard-won entries: infra incident postmortems,
|
||||
Go pitfalls, framework gotchas, design principles, ADRs. **It is not optional
|
||||
reference material — query it actively, not just when explicitly told.**
|
||||
|
||||
### When to query (treat as a reflex)
|
||||
|
||||
- **Before** starting a non-trivial task — search for prior art with the symptom
|
||||
AND the system component ("how did we solve X in Y?"). 5 seconds beats 5 hours.
|
||||
- **When debugging** — search for the error string, the stack frame, the affected
|
||||
service. Past you may have already paid this tax.
|
||||
- **Before adopting** a pattern, library, framework, or model name — check if it
|
||||
was tried and rejected, or what the integration footguns are.
|
||||
- **When making architectural decisions** — search for the domain + "ADR" or
|
||||
"decision" to find prior reasoning before re-deriving it.
|
||||
- **When a recommendation feels novel** — challenge yourself: "has this been
|
||||
documented?" The brain often has it.
|
||||
|
||||
### When to write
|
||||
|
||||
After you discover something that **future-you would forget** and that **isn't
|
||||
recoverable from the code, git log, or PR description alone**:
|
||||
|
||||
- Bugs whose root cause is non-obvious and generalisable beyond this project.
|
||||
- Framework / library / model-name quirks that bit you and would bite anyone.
|
||||
- Design principles validated under fire (e.g. "every `_get` needs a `_list`").
|
||||
- Postmortems for incidents: what broke, why, how diagnosed, what to do next time.
|
||||
|
||||
DON'T write project status, sprint progress, PR summaries, or "what I did this
|
||||
session" — those rot fast and the originals are in git/gitea anyway. Brain
|
||||
entries that age well are about *why*, *how to avoid*, and *what to do when*.
|
||||
|
||||
### How to access (per harness)
|
||||
|
||||
| Harness | Query | Write |
|
||||
|---------|-------|-------|
|
||||
| **Claude Code, Claude Desktop** | `brain_query` (BM25), `brain_answer` (LLM-synth + sources) MCP tools | `brain_write` MCP tool |
|
||||
| **Crush, Pi, Antigravity, other MCP-capable** | same MCP server: `ingestion-brain` (via the `mcp__*_brain__*` namespace once authenticated) | same |
|
||||
| **Anything HTTP-only (curl, scripts)** | `POST https://brain-mcp.d-ma.be/query` with `{"query":"..."}` (auth via `BRAIN_MCP_TOKEN`) | `POST .../write` with `{"content":"...","filename":"..."}` |
|
||||
| **Browser / human inspection** | `https://git.d-ma.be/mathias/hyperguild` → `knowledge/` and `wiki/` markdown files |
|
||||
|
||||
- **Scoping**: defaults to `public` collection; client projects filter to `{client}` + `public`.
|
||||
- **Routing**: brain_answer's LLM uses berget.ai as primary, iguana ollama as
|
||||
fallback. Both are configurable in the `supervisor/ingestion-deployment.yaml`
|
||||
on the koala k3s cluster; don't hardcode local-only model names into the
|
||||
berget URL (see knowledge entry on namespace mismatches).
|
||||
|
||||
### Quick reflex checks
|
||||
|
||||
If you find yourself about to say any of these out loud, you owe yourself a brain query first:
|
||||
|
||||
- "I think the issue might be..."
|
||||
- "Let me try X and see..."
|
||||
- "I'll just write a script to..."
|
||||
- "This is probably a new bug..."
|
||||
- "Has anyone done this before?" — *yes, probably, go check.*
|
||||
|
||||
## Client work rules
|
||||
|
||||
When working on a project tagged with a client name:
|
||||
1. Never send code, data, or context to cloud APIs — use local models only
|
||||
2. Never reference other client projects or their data
|
||||
3. Keep all artifacts within the client's git org / directory
|
||||
4. Treat everything as confidential unless told otherwise
|
||||
|
||||
## Harness-agnostic principles
|
||||
|
||||
This context is designed to work with any AI coding tool:
|
||||
- Claude Code, Cursor, Aider, Open WebUI, Charmbracelet Mods/Crush
|
||||
- Pi Coding Agent, Mistral Vibe, Antigravity
|
||||
- Any tool that accepts a system prompt or reads a markdown context file
|
||||
|
||||
The canonical source is always `.context/AGENT.md` (root) and `.context/PROJECT.md` (per-project).
|
||||
Derived files are committed (see *How context propagates* below) so a `git pull` on any host yields full agent context with no setup.
|
||||
|
||||
## How context propagates
|
||||
|
||||
Canonical sources of truth:
|
||||
- Universal: `~/dev/.context/AGENT.md` (this file)
|
||||
- Project: `<repo>/.context/PROJECT.md` (per-repo)
|
||||
|
||||
Derived files (committed, regenerated by `task context:sync`):
|
||||
- `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, `.aider.conventions.md`,
|
||||
`.context/system-prompt.txt`
|
||||
|
||||
Workflow:
|
||||
1. Edit a canonical file. Run `task context:sync`. Commit canonical and
|
||||
derived together. Push.
|
||||
2. On any other host, `git pull` brings both. Claude Code (tree-walking)
|
||||
uses `CLAUDE.md`; Crush / Pi / Antigravity (cwd-only) use `AGENTS.md`;
|
||||
Cursor uses `.cursorrules`; Aider uses `.aider.conventions.md`.
|
||||
3. `task check` runs `context:sync` then asserts `git status --porcelain`
|
||||
is empty over the derived files (catches both modified-tracked drift
|
||||
and missing-untracked adapters). A drift fails the check with a
|
||||
message telling you to stage the regenerated files.
|
||||
|
||||
Behavior rules in this file and per-project rules in `PROJECT.md` apply
|
||||
unconditionally on every host, every harness.
|
||||
|
||||
## Engineering Skills
|
||||
|
||||
Shared engineering skills live in the **`mathias/skills`** repo (`git.d-ma.be/mathias/skills`). Clone it to `~/dev/skills/` and run `SKILLS_CHECKOUT_DIR="$PWD" bash install.sh` there to wire every skill into your harnesses (Claude Code, Crush, Antigravity, Mistral Vibe) as native, on-demand skills. (Use `install.sh`, not `task install` — the latter is currently broken, skills#7.) Load at task start — not "on demand" but on schedule, before writing code. Browse `~/dev/skills/SKILLS_INDEX.md` for the full list.
|
||||
|
||||
**Skill trigger table — load before starting, not after getting stuck:**
|
||||
|
||||
| Task type | Load |
|
||||
|-----------|------|
|
||||
| Any feature or bug fix | `tdd` |
|
||||
| Refactor or design | `clean-code` or `solid` |
|
||||
| Debug | `problem-analysis` |
|
||||
| Review code or PRs | `code-review` |
|
||||
| Frame a problem before coding | `problem-analysis` |
|
||||
|
||||
---
|
||||
|
||||
# cad-atlas
|
||||
|
||||
## Identity
|
||||
@@ -7,7 +286,85 @@
|
||||
- **Client**: personal
|
||||
- **Repo**: git.d-ma.be/mathias/cad-atlas
|
||||
- **Status**: active
|
||||
- **Stack**: Go + Templ + HTMX + CDN Tailwind (template-go-web). Cross-project conventions: `~/dev/.context/AGENT.md`.
|
||||
|
||||
## Stack
|
||||
## What this is
|
||||
|
||||
Go + Templ + HTMX + CDN Tailwind. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
||||
A visual **atlas of the Continuous Agentic Development (CAD) workflow** — the full path
|
||||
from a captured signal to a deployed k3s pod, one screen, reel-style ("From Signal to Pod").
|
||||
It exists to (a) make the homelab's agentic delivery pipeline legible to a human, and
|
||||
(b) render the CAD **audit chain** — which doubles as the regulated-industry audit artifact.
|
||||
|
||||
> **Core thesis:** the CAD audit chain *is* the visualization data.
|
||||
> `TELOS → goal → spec → issue → execution → attestation → deploy` is both the trace and
|
||||
> the audit package. Phase C renders it once and serves two masters (observability + compliance).
|
||||
|
||||
## Phases
|
||||
|
||||
- **Phase A — static hero viz** (current). Self-contained `internal/web/static/cad-atlas.html`,
|
||||
data-driven from a hand-authored `STAGES` array (ground-truth snapshot from brain, 2026-07-19).
|
||||
Served at `/` by `internal/web/handler.go` via `go:embed`. Reel-parity: SVG spine with
|
||||
arrowheads, animated pulse, dashed **feedback bus** (stage 08 → TELOS), replay + slow-mo.
|
||||
- **Phase B — generated-from-source**. Parse brain docs + `.gitea/workflows` + infra manifests
|
||||
→ render the graph so it can't drift from config.
|
||||
- **Phase C — live trace viewer**. Replace the static `STAGES` array with live reads of the
|
||||
`assessor-loop` attestation ledger + brain `session_log` + Gitea run API + Flux events.
|
||||
This is the prize: a real signal→pod trace viewer that is also the audit package.
|
||||
|
||||
## The workflow it visualizes (9 stages)
|
||||
|
||||
`00 Signals` (Applied AI Radar → mathias/signals) → `01 TELOS` (intention substrate) →
|
||||
`02 Strategic session` (claude.ai frontier + LLM Council + Autoresearch Council) →
|
||||
`03 Spec → Gitea issue` (agent-ready contract; Ed25519 admission #36; **var-go Oath**) →
|
||||
`04 Human dispatch gate` (the only checkpoint; session-dispatch bridge → cad-dispatch.yml) →
|
||||
`05 Execute · agentsquad` (serve/taskqueue, exec+review loop, risk LOW/MED/HIGH, dma-cli routing,
|
||||
assessor-loop ledger) → `06 PR → CI` (go test/vet/lint/govulncheck + **var-go/oath gate**) →
|
||||
`07 CD → pod` (Flux GitOps → k3s on koala) → `08 Loop back` (outcome scored vs TELOS goal).
|
||||
|
||||
### Three orthogonal governance gates
|
||||
|
||||
| Gate | Guards | Where |
|
||||
|---|---|---|
|
||||
| Ed25519 admission controller (#36) | spec **integrity** (issue untampered) | stage 03 |
|
||||
| dispatch-allow (`.dispatch-allow` + `mathias/dispatch` allowlist) | repo **eligibility** (may agents run here) | stage 04/05 |
|
||||
| **var-go Oath** (`cmd/vargo-gate`, commit status `var-go/oath`) | output **correctness** (PR satisfies the Oath; floor over reviewer, anti-rubber-stamp #55) | stage 06 |
|
||||
|
||||
## Dogfooding
|
||||
|
||||
This repo is built *through* the workflow it depicts. It is `dispatch-allow`-enabled, and its
|
||||
own build increments are governed by a **var-go Oath** embedded in their spec issues (see the
|
||||
Stage-03 tracking issue). Bootstrapping honesty (per swedsl honest-stub discipline): the Oath is
|
||||
**defined** but `cmd/vargo-gate` is **not yet wired** into this repo's CI — until it is, the Oath
|
||||
is advisory here. Wiring it is a first tracked task; disclosed in code, this doc, and CI config.
|
||||
|
||||
## Brain references (source of truth — `brain_get <path>`)
|
||||
|
||||
- `knowledge/workflow-idea-to-running-service.md` — Double Diamond idea→service workflow
|
||||
- `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16.md` — CAD definition
|
||||
- `wiki/agentsquad/decisions/cad-dispatch-bridge.md` — claude.ai → agentsquad trigger path
|
||||
- `wiki/agentsquad/facts/llm-council-design-and-first-runs-2026-06-21.md` — LLM Council
|
||||
- `wiki/agentsquad/decisions/autoresearch-council-sibling-pipe.md` — Autoresearch Council
|
||||
- `wiki/agentsquad/decisions/serve-http-task-api.md` — agentsquad serve/taskqueue
|
||||
- `knowledge/var-go-anchor-to-span-spike-verdict.md` — var-go runner + CAD gate seam
|
||||
- `knowledge/swedsl-vargo-sprint1-enforcement-teeth-verdict.md` — vargo-gate enforcement teeth
|
||||
- `wiki/assessor-loop/decisions/assessor-loop-genesis.md` — attestation ledger (Phase C source)
|
||||
- `wiki/homelab/facts/homelab-network-topology-reference.md` — koala/iguana/flamingo/piguard
|
||||
|
||||
## External references
|
||||
|
||||
- Inspiration reel — "From Inbox to Shipped" pipeline viz: https://www.instagram.com/reel/DY92L7bu27j/
|
||||
- karpathy/llm-council — origin of the Council pattern
|
||||
- Double Diamond design process (Discover/Define/Develop/Deliver)
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
task check # lint + vet + test (CI gate)
|
||||
task run # build + serve at http://localhost:8080 → the atlas
|
||||
```
|
||||
|
||||
## Deploy note
|
||||
|
||||
CD (`.gitea/workflows/cd.yml`) deploys to k3s namespace `cad-atlas` via Flux. Per the known
|
||||
template-go-agent CD gap: the `deploy` job stays RED until `mathias/infra` has
|
||||
`k3s/apps/cad-atlas/deployment.yaml`. `check` + `build` are the real bootstrap gate.
|
||||
|
||||
@@ -7,7 +7,85 @@
|
||||
- **Client**: personal
|
||||
- **Repo**: git.d-ma.be/mathias/cad-atlas
|
||||
- **Status**: active
|
||||
- **Stack**: Go + Templ + HTMX + CDN Tailwind (template-go-web). Cross-project conventions: `~/dev/.context/AGENT.md`.
|
||||
|
||||
## Stack
|
||||
## What this is
|
||||
|
||||
Go + Templ + HTMX + CDN Tailwind. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
||||
A visual **atlas of the Continuous Agentic Development (CAD) workflow** — the full path
|
||||
from a captured signal to a deployed k3s pod, one screen, reel-style ("From Signal to Pod").
|
||||
It exists to (a) make the homelab's agentic delivery pipeline legible to a human, and
|
||||
(b) render the CAD **audit chain** — which doubles as the regulated-industry audit artifact.
|
||||
|
||||
> **Core thesis:** the CAD audit chain *is* the visualization data.
|
||||
> `TELOS → goal → spec → issue → execution → attestation → deploy` is both the trace and
|
||||
> the audit package. Phase C renders it once and serves two masters (observability + compliance).
|
||||
|
||||
## Phases
|
||||
|
||||
- **Phase A — static hero viz** (current). Self-contained `internal/web/static/cad-atlas.html`,
|
||||
data-driven from a hand-authored `STAGES` array (ground-truth snapshot from brain, 2026-07-19).
|
||||
Served at `/` by `internal/web/handler.go` via `go:embed`. Reel-parity: SVG spine with
|
||||
arrowheads, animated pulse, dashed **feedback bus** (stage 08 → TELOS), replay + slow-mo.
|
||||
- **Phase B — generated-from-source**. Parse brain docs + `.gitea/workflows` + infra manifests
|
||||
→ render the graph so it can't drift from config.
|
||||
- **Phase C — live trace viewer**. Replace the static `STAGES` array with live reads of the
|
||||
`assessor-loop` attestation ledger + brain `session_log` + Gitea run API + Flux events.
|
||||
This is the prize: a real signal→pod trace viewer that is also the audit package.
|
||||
|
||||
## The workflow it visualizes (9 stages)
|
||||
|
||||
`00 Signals` (Applied AI Radar → mathias/signals) → `01 TELOS` (intention substrate) →
|
||||
`02 Strategic session` (claude.ai frontier + LLM Council + Autoresearch Council) →
|
||||
`03 Spec → Gitea issue` (agent-ready contract; Ed25519 admission #36; **var-go Oath**) →
|
||||
`04 Human dispatch gate` (the only checkpoint; session-dispatch bridge → cad-dispatch.yml) →
|
||||
`05 Execute · agentsquad` (serve/taskqueue, exec+review loop, risk LOW/MED/HIGH, dma-cli routing,
|
||||
assessor-loop ledger) → `06 PR → CI` (go test/vet/lint/govulncheck + **var-go/oath gate**) →
|
||||
`07 CD → pod` (Flux GitOps → k3s on koala) → `08 Loop back` (outcome scored vs TELOS goal).
|
||||
|
||||
### Three orthogonal governance gates
|
||||
|
||||
| Gate | Guards | Where |
|
||||
|---|---|---|
|
||||
| Ed25519 admission controller (#36) | spec **integrity** (issue untampered) | stage 03 |
|
||||
| dispatch-allow (`.dispatch-allow` + `mathias/dispatch` allowlist) | repo **eligibility** (may agents run here) | stage 04/05 |
|
||||
| **var-go Oath** (`cmd/vargo-gate`, commit status `var-go/oath`) | output **correctness** (PR satisfies the Oath; floor over reviewer, anti-rubber-stamp #55) | stage 06 |
|
||||
|
||||
## Dogfooding
|
||||
|
||||
This repo is built *through* the workflow it depicts. It is `dispatch-allow`-enabled, and its
|
||||
own build increments are governed by a **var-go Oath** embedded in their spec issues (see the
|
||||
Stage-03 tracking issue). Bootstrapping honesty (per swedsl honest-stub discipline): the Oath is
|
||||
**defined** but `cmd/vargo-gate` is **not yet wired** into this repo's CI — until it is, the Oath
|
||||
is advisory here. Wiring it is a first tracked task; disclosed in code, this doc, and CI config.
|
||||
|
||||
## Brain references (source of truth — `brain_get <path>`)
|
||||
|
||||
- `knowledge/workflow-idea-to-running-service.md` — Double Diamond idea→service workflow
|
||||
- `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16.md` — CAD definition
|
||||
- `wiki/agentsquad/decisions/cad-dispatch-bridge.md` — claude.ai → agentsquad trigger path
|
||||
- `wiki/agentsquad/facts/llm-council-design-and-first-runs-2026-06-21.md` — LLM Council
|
||||
- `wiki/agentsquad/decisions/autoresearch-council-sibling-pipe.md` — Autoresearch Council
|
||||
- `wiki/agentsquad/decisions/serve-http-task-api.md` — agentsquad serve/taskqueue
|
||||
- `knowledge/var-go-anchor-to-span-spike-verdict.md` — var-go runner + CAD gate seam
|
||||
- `knowledge/swedsl-vargo-sprint1-enforcement-teeth-verdict.md` — vargo-gate enforcement teeth
|
||||
- `wiki/assessor-loop/decisions/assessor-loop-genesis.md` — attestation ledger (Phase C source)
|
||||
- `wiki/homelab/facts/homelab-network-topology-reference.md` — koala/iguana/flamingo/piguard
|
||||
|
||||
## External references
|
||||
|
||||
- Inspiration reel — "From Inbox to Shipped" pipeline viz: https://www.instagram.com/reel/DY92L7bu27j/
|
||||
- karpathy/llm-council — origin of the Council pattern
|
||||
- Double Diamond design process (Discover/Define/Develop/Deliver)
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
task check # lint + vet + test (CI gate)
|
||||
task run # build + serve at http://localhost:8080 → the atlas
|
||||
```
|
||||
|
||||
## Deploy note
|
||||
|
||||
CD (`.gitea/workflows/cd.yml`) deploys to k3s namespace `cad-atlas` via Flux. Per the known
|
||||
template-go-agent CD gap: the `deploy` job stays RED until `mathias/infra` has
|
||||
`k3s/apps/cad-atlas/deployment.yaml`. `check` + `build` are the real bootstrap gate.
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
# cad-atlas
|
||||
|
||||
> Generated from `mathias/template-go-web`.
|
||||
**A visual atlas of the Continuous Agentic Development (CAD) workflow — from a captured signal to a deployed k3s pod.**
|
||||
|
||||
## Bootstrap
|
||||
One screen, reel-style: `Signals → TELOS → Strategic session → Spec/Oath → Human gate → agentsquad → CI → CD → pod`, looping back to TELOS. It renders the CAD **audit chain**, which doubles as the regulated-industry audit artifact.
|
||||
|
||||
After creating from template, run:
|
||||
> The CAD audit chain *is* the visualization data. Phase C renders it once and serves two masters: observability + compliance.
|
||||
|
||||
## Phases
|
||||
|
||||
- **A — static hero viz** (current): self-contained `internal/web/static/cad-atlas.html`, served at `/`. SVG spine, animated pulse, dashed feedback bus, replay/slow-mo.
|
||||
- **B — generated-from-source**: render from brain docs + workflows + infra manifests (no drift).
|
||||
- **C — live trace viewer**: hydrate from the `assessor-loop` ledger + `session_log` + Gitea run API + Flux events.
|
||||
|
||||
## Quickstart
|
||||
|
||||
```bash
|
||||
go mod tidy # regenerate go.sum with real module path
|
||||
task generate # generate templ files
|
||||
task build # build the binary
|
||||
task check # lint + vet + test (CI gate)
|
||||
task run # → http://localhost:8080
|
||||
```
|
||||
|
||||
## Context
|
||||
|
||||
Full project context, the 9-stage workflow, the three governance gates, the dogfooding model, and all **brain deep-links + external references** live in [`.context/PROJECT.md`](.context/PROJECT.md). Any clean agent session should read that first (`brain_get <path>` for the linked notes).
|
||||
|
||||
## Governance (dogfooded)
|
||||
|
||||
This repo is built *through* the workflow it depicts: `dispatch-allow`-enabled, build increments governed by a **var-go Oath** in their spec issues. Bootstrapping honesty: the Oath is defined but `cmd/vargo-gate` is not yet wired into this repo's CI — advisory until it is. See PROJECT.md.
|
||||
|
||||
@@ -2,6 +2,4 @@ module git.d-ma.be/mathias/cad-atlas
|
||||
|
||||
go 1.26
|
||||
|
||||
require (
|
||||
github.com/a-h/templ v0.2.778
|
||||
)
|
||||
require github.com/a-h/templ v0.3.1020
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw=
|
||||
github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
+16
-1
@@ -2,13 +2,28 @@ package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// atlasHTML is the Phase-A static hero visualization. Phase C replaces this
|
||||
// self-contained file with a Templ view hydrated from live CAD trace data
|
||||
// (assessor-loop ledger, session_log, Gitea run API, Flux events).
|
||||
//
|
||||
//go:embed static/cad-atlas.html
|
||||
var atlasHTML []byte
|
||||
|
||||
// NewHandler serves the CAD Atlas. Root ("/") returns the static atlas;
|
||||
// /api/hello is a leftover template probe kept until Phase C wires real endpoints.
|
||||
func NewHandler() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
_ = Index().Render(context.Background(), w)
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
_, _ = w.Write(atlasHTML)
|
||||
})
|
||||
mux.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
|
||||
_ = Hello("world").Render(context.Background(), w)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRootServesAtlas(t *testing.T) {
|
||||
srv := httptest.NewServer(NewHandler())
|
||||
defer srv.Close()
|
||||
|
||||
resp, err := http.Get(srv.URL + "/")
|
||||
if err != nil {
|
||||
t.Fatalf("GET /: %v", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("GET / status = %d, want 200", resp.StatusCode)
|
||||
}
|
||||
buf := make([]byte, 4096)
|
||||
n, _ := resp.Body.Read(buf)
|
||||
if !strings.Contains(string(buf[:n]), "CAD") {
|
||||
t.Fatalf("GET / body missing atlas marker %q", "CAD")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownPath404(t *testing.T) {
|
||||
srv := httptest.NewServer(NewHandler())
|
||||
defer srv.Close()
|
||||
|
||||
resp, err := http.Get(srv.URL + "/nope")
|
||||
if err != nil {
|
||||
t.Fatalf("GET /nope: %v", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusNotFound {
|
||||
t.Fatalf("GET /nope status = %d, want 404", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>CAD Atlas · From Signal to Pod</title>
|
||||
<style>
|
||||
:root{
|
||||
--bg:#080b12; --panel:#0e1420; --panel2:#121a2b; --line:#1e2b44;
|
||||
--ink:#cdd9ef; --dim:#7f92b5; --mono:#8fb4ff;
|
||||
--blue:#4aa8ff; --amber:#f5b942; --coral:#ff7a5c; --green:#4ad07a; --violet:#9b8cff; --gold:#e6c15a;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
html,body{margin:0;height:100%}
|
||||
body{
|
||||
background:
|
||||
radial-gradient(circle at 1px 1px,#16213a 1px,transparent 0) 0 0/26px 26px,
|
||||
var(--bg);
|
||||
color:var(--ink);
|
||||
font:14px/1.5 ui-sans-serif,system-ui,Segoe UI,Roboto,sans-serif;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
||||
|
||||
header{
|
||||
position:sticky;top:0;z-index:30;backdrop-filter:blur(8px);
|
||||
background:linear-gradient(180deg,rgba(8,11,18,.94),rgba(8,11,18,.72));
|
||||
border-bottom:1px solid var(--line);
|
||||
display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;padding:14px 22px;
|
||||
}
|
||||
header h1{font-size:19px;margin:0}
|
||||
header h1 b{color:var(--blue)}
|
||||
header .sub{color:var(--dim);font-size:12px}
|
||||
header .sub em{color:var(--amber);font-style:normal}
|
||||
.controls{margin-left:auto;display:flex;gap:8px}
|
||||
button{
|
||||
font:inherit;font-size:12px;color:var(--ink);cursor:pointer;
|
||||
background:var(--panel2);border:1px solid var(--line);border-radius:8px;
|
||||
padding:7px 13px;display:inline-flex;align-items:center;gap:7px;
|
||||
}
|
||||
button:hover{border-color:var(--blue)}
|
||||
button.on{border-color:var(--amber);color:var(--amber)}
|
||||
button .dot{width:7px;height:7px;border-radius:50%;background:var(--blue)}
|
||||
button.on .dot{background:var(--amber)}
|
||||
|
||||
.substrate{display:flex;gap:10px;flex-wrap:wrap;align-items:center;
|
||||
padding:10px 22px;border-bottom:1px solid var(--line);background:var(--panel)}
|
||||
.substrate .lbl{color:var(--dim);font-size:11px;letter-spacing:1.5px;margin-right:4px}
|
||||
.host{border:1px solid var(--line);border-radius:8px;padding:6px 11px;
|
||||
background:var(--panel2);font-size:12px;display:flex;gap:8px;align-items:center}
|
||||
.host b{color:var(--blue)}
|
||||
.host .k{color:var(--dim);font-size:11px}
|
||||
.host.mesh{border-style:dashed;color:var(--dim)}
|
||||
|
||||
.scroll{overflow-x:auto;padding:24px 22px 20px}
|
||||
.track{position:relative;display:flex;align-items:flex-start;min-width:max-content}
|
||||
svg.spine{position:absolute;left:0;top:0;z-index:0;pointer-events:none;overflow:visible}
|
||||
.pulse{position:absolute;top:0;left:0;width:13px;height:13px;border-radius:50%;
|
||||
background:var(--amber);box-shadow:0 0 15px 4px rgba(245,185,66,.75);
|
||||
transform:translate(-6.5px,-6.5px);z-index:6}
|
||||
|
||||
.stage{width:300px;flex:0 0 300px;padding:0 14px;position:relative;z-index:2}
|
||||
.stage .no{color:var(--dim);font-size:11px;letter-spacing:2px}
|
||||
.stage h2{font-size:17px;margin:6px 0 2px}
|
||||
.stage .path{color:var(--mono);font-size:11.5px;margin-bottom:6px;min-height:16px}
|
||||
.node{border:1px solid var(--line);border-radius:11px;background:var(--panel);
|
||||
padding:12px 13px;margin-top:12px;position:relative;
|
||||
transition:border-color .25s,box-shadow .25s,transform .25s}
|
||||
.node .t{font-weight:600;margin-bottom:3px;display:flex;align-items:center;gap:7px}
|
||||
.node .d{color:var(--dim);font-size:12px}
|
||||
.node .tag{display:inline-block;font-size:10.5px;padding:2px 7px;border-radius:20px;
|
||||
border:1px solid var(--line);color:var(--dim);margin:6px 6px 0 0}
|
||||
.pill{width:8px;height:8px;border-radius:50%;flex:0 0 8px}
|
||||
|
||||
.stage.telos h2{color:var(--violet)}
|
||||
.stage.gate h2{color:var(--amber)}
|
||||
.stage.exec h2{color:var(--coral)}
|
||||
.stage.cd h2{color:var(--green)}
|
||||
.node.win{border-color:var(--coral);box-shadow:0 0 0 1px rgba(255,122,92,.25)}
|
||||
.node.gateway{border-color:var(--amber);background:linear-gradient(180deg,rgba(245,185,66,.06),transparent)}
|
||||
.node.council{border-color:var(--violet)}
|
||||
.node.bridge{border-color:var(--blue);border-style:dashed}
|
||||
.node.oath{border-color:var(--gold);border-style:dashed;background:linear-gradient(180deg,rgba(230,193,90,.05),transparent)}
|
||||
|
||||
.stage.active h2{text-shadow:0 0 18px currentColor}
|
||||
.stage.active .node{border-color:var(--amber);
|
||||
box-shadow:0 0 0 1px rgba(245,185,66,.35),0 10px 30px -12px rgba(245,185,66,.4);transform:translateY(-2px)}
|
||||
|
||||
.risk{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}
|
||||
.risk span{font-size:10.5px;padding:2px 7px;border-radius:6px;border:1px solid var(--line)}
|
||||
.risk .lo{color:var(--green);border-color:rgba(74,208,122,.4)}
|
||||
.risk .md{color:var(--amber);border-color:rgba(245,185,66,.4)}
|
||||
.risk .hi{color:var(--coral);border-color:rgba(255,122,92,.4)}
|
||||
.gatebtns{display:flex;gap:8px;margin-top:10px}
|
||||
.gatebtns .g{flex:1;text-align:center;padding:8px;border-radius:8px;font-size:12px;border:1px solid}
|
||||
.gatebtns .ok{border-color:rgba(74,208,122,.5);color:var(--green)}
|
||||
.gatebtns .no{border-color:rgba(255,122,92,.5);color:var(--coral)}
|
||||
|
||||
footer{padding:14px 22px 30px;color:var(--dim);font-size:11px;border-top:1px solid var(--line)}
|
||||
footer code{color:var(--mono)}
|
||||
|
||||
/* ---- responsive: stack vertically, drop the SVG spine ---- */
|
||||
@media(max-width:820px){
|
||||
.scroll{overflow-x:visible;padding:16px}
|
||||
.track{flex-direction:column;min-width:0}
|
||||
svg.spine,.pulse{display:none}
|
||||
.stage{width:100%;flex:auto;padding:0;border-left:2px solid var(--line);margin-left:6px;
|
||||
padding-left:16px;padding-bottom:8px}
|
||||
.stage.telos{border-color:var(--violet)} .stage.gate{border-color:var(--amber)}
|
||||
.stage.exec{border-color:var(--coral)} .stage.cd{border-color:var(--green)}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<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>
|
||||
<div class="controls">
|
||||
<button id="replay"><span class="dot"></span> Replay</button>
|
||||
<button id="slowmo">Slow-mo · <span id="slowState">off</span></button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="substrate" id="substrate"><span class="lbl mono">SUBSTRATE</span></div>
|
||||
|
||||
<div class="scroll">
|
||||
<div class="track" id="track">
|
||||
<svg class="spine" id="spine">
|
||||
<defs>
|
||||
<marker id="arw" markerWidth="9" markerHeight="9" refX="6" refY="3" orient="auto">
|
||||
<path d="M0,0 L6,3 L0,6 Z" fill="#33507f"></path>
|
||||
</marker>
|
||||
</defs>
|
||||
<path id="spinePath" fill="none" stroke="#33507f" stroke-width="2"
|
||||
marker-mid="url(#arw)" marker-end="url(#arw)"></path>
|
||||
<path id="loopPath" fill="none" stroke="#9b8cff" stroke-width="1.6"
|
||||
stroke-dasharray="5 5" opacity=".7"></path>
|
||||
<text id="loopLbl" fill="#9b8cff" font-size="11"
|
||||
font-family="ui-monospace,monospace" opacity=".85"></text>
|
||||
</svg>
|
||||
<div class="pulse" id="pulse"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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.
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
const 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";
|
||||
|
||||
const 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 #1–26+"]},
|
||||
{t:"Manual capture",d:"claude.ai strategic drop · brain capture tool.",tags:["ad-hoc"]},
|
||||
{t:"Aspirational surfaces",pill:"var(--dim)",d:"Telegram / voice / URL → inbox. NOT built.",tags:["gap"]},
|
||||
]},
|
||||
{no:"STAGE 01",cls:"telos",title:"TELOS",path:"wiki/telos/",nodes:[
|
||||
{t:"Intention substrate",pill:"var(--violet)",d:"Mission · goals · problems · strategies · status. Every downstream item traces to a goal.",tags:["brain_query wing=telos"]},
|
||||
]},
|
||||
{no:"STAGE 02",cls:"",title:"Strategic session",path:"claude.ai frontier + brain MCP",nodes:[
|
||||
{t:"Design · ADRs · specs",d:"Human + frontier model. ISC acceptance criteria written here.",tags:["Define / converge"]},
|
||||
{t:"🏛️ LLM Council",cls:"council",pill:"var(--violet)",d:"fan-out → anonymous cross-review → chairman synth. glm-4.7-flash · qwen36-35b · gemma4-31b (chair).",tags:["hard strategic Q","chat.d-ma.be"]},
|
||||
{t:"Autoresearch Council",cls:"council",pill:"var(--violet)",d:"Sibling pipe — ratifies research before the gate.",tags:["proposed: → standalone svc"]},
|
||||
]},
|
||||
{no:"STAGE 03",cls:"",title:"Spec → Gitea issue",path:"agent-ready contract",nodes:[
|
||||
{t:"Contract enforced",d:"Binary ISC · declared risk tier · reg-risk assessment · no open human deps.",tags:["LOW / MED / HIGH"]},
|
||||
{t:"Admission controller",d:"Ed25519-sign issue body at creation (#36). Verify sig + PR alignment at infra boundary.",tags:["chain of custody"]},
|
||||
{t:"⚖️ var-go Oath",cls:"oath",pill:"var(--gold)",d:"Acceptance contract embedded in the issue as a ```var fenced block. Exactly one — zero/multiple fail closed. Prose → typed steps; failures anchored to byte spans.",tags:["swedsl · var-go","defined here → enforced @06"]},
|
||||
]},
|
||||
{no:"STAGE 04",cls:"gate",title:"Human dispatch gate",path:"the only checkpoint",nodes:[
|
||||
{t:"Human triggers execution",cls:"gateway",pill:"var(--amber)",d:"Ratify proposed-plan + risk tier, then dispatch.",gate:true},
|
||||
{t:"Session-Dispatch bridge",cls:"bridge",pill:"var(--blue)",d:"claude.ai MCP → gitea:workflow_run_trigger → cad-dispatch.yml → agentsquad. The final design→execution bridge.",tags:["workflow_dispatch"]},
|
||||
]},
|
||||
{no:"STAGE 05",cls:"exec",title:"Execute · agentsquad",path:"koala · cmd/agentsquad-serve",nodes:[
|
||||
{t:"Task API",pill:"var(--coral)",d:"POST /tasks → job id · GET /tasks/{id}. taskqueue + serve (v0.12+).",tags:["single agentsquad.yaml"]},
|
||||
{t:"Executor + reviewer loop",cls:"win",pill:"var(--coral)",d:"ADK Go + LiteLLM. Frontier models (local qwen spirals). Reviewer on distinct tier — echo-chamber prevention.",risk:true},
|
||||
{t:"dma-cli · routing + scope",cls:"bridge",pill:"var(--blue)",d:"Harness-config arm: routes agents to the right LLM backend. Three-layer scope policy + confirmation gate = CAD guardrail.",tags:["backend routing","scope guardrail"]},
|
||||
{t:"assessor-loop ledger",d:"Attestation ledger (audit trail) + brain session_log on completion.",tags:["audit package"]},
|
||||
]},
|
||||
{no:"STAGE 06",cls:"",title:"PR → CI",path:"Gitea Actions",nodes:[
|
||||
{t:"PR + label",d:"Gitea PR · agent-done / agent-blocked label.",tags:[]},
|
||||
{t:"Mechanical gate",d:"go test · vet · lint · govulncheck. ISC verified mechanically.",tags:["green = proceed"]},
|
||||
{t:"⚖️ var-go/oath gate",cls:"oath",pill:"var(--gold)",d:"cmd/vargo-gate runs in CI → posts commit status context=var-go/oath. Authoritative FLOOR: failed Oath blocks regardless of reviewer approval (#55 anti-rubber-stamp).",tags:["branch-protection req","enforces @03 Oath"]},
|
||||
]},
|
||||
{no:"STAGE 07",cls:"cd",title:"CD → pod",path:"Flux GitOps → k3s",nodes:[
|
||||
{t:"Deploy on green",pill:"var(--green)",d:"Flux reconciles image → k3s pod on koala. Push ≠ deploy: bump tag in mathias/infra.",tags:["ntfy on deploy"]},
|
||||
]},
|
||||
{no:"STAGE 08",cls:"telos",title:"Loop back",path:"→ TELOS (feedback bus)",nodes:[
|
||||
{t:"Close the loop",pill:"var(--violet)",d:"session_log + attestation → brain. Score deploy outcome vs originating goal. (arc partly manual — improvement target.)",tags:["continuous"]},
|
||||
]},
|
||||
];
|
||||
|
||||
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=>{
|
||||
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=>{
|
||||
const pill=n.pill?`<span class="pill" style="background:${n.pill}"></span>`:'';
|
||||
let inner=`<div class="t">${pill}${n.t}</div><div class="d">${n.d}</div>`;
|
||||
if(n.tags&&n.tags.length)inner+=n.tags.map(t=>`<span class="tag mono">${t}</span>`).join('');
|
||||
if(n.risk)inner+=`<div class="risk mono"><span class="lo">LOW · auto</span><span class="md">MED · ntfy gate</span><span class="hi">HIGH · blocked</span></div>`;
|
||||
if(n.gate)inner+=`<div class="gatebtns mono"><div class="g ok">✓ approve</div><div class="g no">✕ reject</div></div>`;
|
||||
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'),
|
||||
loopPath=document.getElementById('loopPath'), loopLbl=document.getElementById('loopLbl'),
|
||||
pulse=document.getElementById('pulse');
|
||||
const RAILY=70;
|
||||
let cs=[],loopY=0,spineLen=0,loopLen=0,slow=false,raf=null,t0=null,mobile=false;
|
||||
|
||||
function build(){
|
||||
mobile=window.matchMedia('(max-width:820px)').matches;
|
||||
if(mobile)return;
|
||||
cs=stageEls.map(s=>s.offsetLeft+s.offsetWidth/2);
|
||||
const maxBottom=Math.max(...stageEls.map(s=>s.offsetTop+s.offsetHeight));
|
||||
loopY=maxBottom+40;
|
||||
spine.setAttribute('width',track.scrollWidth);
|
||||
spine.setAttribute('height',loopY+70);
|
||||
track.style.minHeight=(loopY+70)+'px';
|
||||
spinePath.setAttribute('d','M '+cs[0]+' '+RAILY+cs.slice(1).map(x=>' L '+x+' '+RAILY).join(''));
|
||||
const lastX=cs[cs.length-1], telosX=cs[1];
|
||||
loopPath.setAttribute('d',`M ${lastX} ${RAILY} L ${lastX} ${loopY} L ${telosX} ${loopY} L ${telosX} ${RAILY}`);
|
||||
loopLbl.setAttribute('x',(telosX+lastX)/2-90);loopLbl.setAttribute('y',loopY-8);
|
||||
loopLbl.textContent='feedback bus · outcome → goal';
|
||||
spineLen=spinePath.getTotalLength();loopLen=loopPath.getTotalLength();
|
||||
}
|
||||
function run(ts){
|
||||
if(mobile)return;
|
||||
if(!t0)t0=ts;
|
||||
const dur=slow?16000:7000;
|
||||
const p=Math.min((ts-t0)/dur,1);
|
||||
const total=spineLen+loopLen, dist=total*p;
|
||||
let pt,onLoop=dist>spineLen;
|
||||
pt=onLoop?loopPath.getPointAtLength(dist-spineLen):spinePath.getPointAtLength(dist);
|
||||
pulse.style.left=pt.x+'px';pulse.style.top=pt.y+'px';
|
||||
pulse.style.background=onLoop?'var(--violet)':'var(--amber)';
|
||||
pulse.style.boxShadow=onLoop?'0 0 15px 4px rgba(155,140,255,.75)':'0 0 15px 4px rgba(245,185,66,.75)';
|
||||
let act=onLoop?1:0; // during loop, highlight TELOS
|
||||
if(!onLoop)cs.forEach((c,i)=>{if(pt.x>=c-150)act=i;});
|
||||
stageEls.forEach((s,i)=>s.classList.toggle('active',i===act));
|
||||
if(p<1)raf=requestAnimationFrame(run);
|
||||
}
|
||||
function replay(){cancelAnimationFrame(raf);t0=null;build();if(!mobile)raf=requestAnimationFrame(run);}
|
||||
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();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user