Template
refactor(template): match single-harness (hyperguild) architecture (infra#178)
The template carried the old multi-tool/agentsquad-era CAD-executor scaffold. Refresh it to the consolidated single-harness reality (hyperguild#75/#76): Claude Code + hyperguild, session-based, brain + gitea MCP. No dispatch automation added (out of scope — dispatch stays manual until real friction warrants it). Removed (multi-tool + dead generator + deployed-agent-era): - .aider.conf.yml, .aider.conventions.md, .cursorrules - .context/ (mcp.json, PROJECT.md, system-prompt.txt) - agent-policy.yaml (k8s NetworkPolicy scaffold) - scripts/context-sync.sh (generated the above from .context/PROJECT.md — now input-less) + its context:sync* Taskfile tasks Added / updated: - .mcp.json (root, hyperguild-shaped: brain + gitea, Bearer env tokens) - CLAUDE.md / AGENTS.md / README.md → single-harness workflow (issue → hyperguild session → PR → report-back comment → brain capture) - AGENT_BOUNDARIES.md kept (harness-agnostic egress/scope guidance); repointed its two references to the removed agent-policy.yaml Left alone: cd.yml, Dockerfile, Taskfile (build/test), go.mod, cmd/, internal/, pkg/, .claude/. No dangling refs to removed files (verified). Refs infra#178. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,2 +0,0 @@
|
|||||||
read: .aider.conventions.md
|
|
||||||
auto-commits: false
|
|
||||||
@@ -1,255 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 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
|
|
||||||
|
|
||||||
## 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://gitea.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 are available in `~/dev/.skills/`. Load on demand via the index.
|
|
||||||
|
|
||||||
See `~/dev/.skills/SKILLS_INDEX.md` for the full list with descriptions and "use when" triggers.
|
|
||||||
|
|
||||||
Key skills:
|
|
||||||
- **TDD**: always write tests first — load `tdd` skill
|
|
||||||
- **Code Review**: load `code-review` skill before any review
|
|
||||||
- **SOLID/Clean Code**: load `solid` or `clean-code` skill for design work
|
|
||||||
- **Problem first**: load `problem-analysis` skill before coding non-trivial features
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# __PROJECT_NAME__
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
|
|
||||||
- **Name**: __PROJECT_NAME__
|
|
||||||
- **Owner**: Mathias
|
|
||||||
- **Client**: personal
|
|
||||||
- **Repo**: gitea.d-ma.be/mathias/__PROJECT_NAME__
|
|
||||||
- **Status**: active
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
Go + ADK + LiteLLM. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
|
||||||
|
|
||||||
## Agent
|
|
||||||
|
|
||||||
TODO: describe what this agent does, what tools it has, and what it's responsible for.
|
|
||||||
|
|
||||||
## Observability
|
|
||||||
|
|
||||||
Traces → Jaeger via `OTLP_ENDPOINT`. Set `ADK_SERVICE_NAME=__PROJECT_NAME__` per deployment.
|
|
||||||
Spans emitted: `invoke_agent`, `generate_content`. Tool spans require custom callbacks.
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# __PROJECT_NAME__
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
|
|
||||||
- **Name**: __PROJECT_NAME__
|
|
||||||
- **Owner**: Mathias
|
|
||||||
- **Client**: personal
|
|
||||||
- **Repo**: gitea.d-ma.be/mathias/__PROJECT_NAME__
|
|
||||||
- **Status**: active
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
Go + ADK + LiteLLM. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
|
||||||
|
|
||||||
## Agent
|
|
||||||
|
|
||||||
TODO: describe what this agent does, what tools it has, and what it's responsible for.
|
|
||||||
|
|
||||||
## Observability
|
|
||||||
|
|
||||||
Traces → Jaeger via `OTLP_ENDPOINT`. Set `ADK_SERVICE_NAME=__PROJECT_NAME__` per deployment.
|
|
||||||
Spans emitted: `invoke_agent`, `generate_content`. Tool spans require custom callbacks.
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
You are a coding assistant working on a specific project.
|
|
||||||
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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 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
|
|
||||||
|
|
||||||
## 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://gitea.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 are available in `~/dev/.skills/`. Load on demand via the index.
|
|
||||||
|
|
||||||
See `~/dev/.skills/SKILLS_INDEX.md` for the full list with descriptions and "use when" triggers.
|
|
||||||
|
|
||||||
Key skills:
|
|
||||||
- **TDD**: always write tests first — load `tdd` skill
|
|
||||||
- **Code Review**: load `code-review` skill before any review
|
|
||||||
- **SOLID/Clean Code**: load `solid` or `clean-code` skill for design work
|
|
||||||
- **Problem first**: load `problem-analysis` skill before coding non-trivial features
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# __PROJECT_NAME__
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
|
|
||||||
- **Name**: __PROJECT_NAME__
|
|
||||||
- **Owner**: Mathias
|
|
||||||
- **Client**: personal
|
|
||||||
- **Repo**: gitea.d-ma.be/mathias/__PROJECT_NAME__
|
|
||||||
- **Status**: active
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
Go + ADK + LiteLLM. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
|
||||||
|
|
||||||
## Agent
|
|
||||||
|
|
||||||
TODO: describe what this agent does, what tools it has, and what it's responsible for.
|
|
||||||
|
|
||||||
## Observability
|
|
||||||
|
|
||||||
Traces → Jaeger via `OTLP_ENDPOINT`. Set `ADK_SERVICE_NAME=__PROJECT_NAME__` per deployment.
|
|
||||||
Spans emitted: `invoke_agent`, `generate_content`. Tool spans require custom callbacks.
|
|
||||||
|
|
||||||
---
|
|
||||||
-258
@@ -1,258 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 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
|
|
||||||
|
|
||||||
## 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://gitea.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 are available in `~/dev/.skills/`. Load on demand via the index.
|
|
||||||
|
|
||||||
See `~/dev/.skills/SKILLS_INDEX.md` for the full list with descriptions and "use when" triggers.
|
|
||||||
|
|
||||||
Key skills:
|
|
||||||
- **TDD**: always write tests first — load `tdd` skill
|
|
||||||
- **Code Review**: load `code-review` skill before any review
|
|
||||||
- **SOLID/Clean Code**: load `solid` or `clean-code` skill for design work
|
|
||||||
- **Problem first**: load `problem-analysis` skill before coding non-trivial features
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# __PROJECT_NAME__
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
|
|
||||||
- **Name**: __PROJECT_NAME__
|
|
||||||
- **Owner**: Mathias
|
|
||||||
- **Client**: personal
|
|
||||||
- **Repo**: gitea.d-ma.be/mathias/__PROJECT_NAME__
|
|
||||||
- **Status**: active
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
Go + ADK + LiteLLM. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
|
||||||
|
|
||||||
## Agent
|
|
||||||
|
|
||||||
TODO: describe what this agent does, what tools it has, and what it's responsible for.
|
|
||||||
|
|
||||||
## Observability
|
|
||||||
|
|
||||||
Traces → Jaeger via `OTLP_ENDPOINT`. Set `ADK_SERVICE_NAME=__PROJECT_NAME__` per deployment.
|
|
||||||
Spans emitted: `invoke_agent`, `generate_content`. Tool spans require custom callbacks.
|
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"knowledge": {
|
|
||||||
"url": "http://localhost:3100/mcp",
|
|
||||||
"description": "Project knowledge base — vector + graph retrieval"
|
|
||||||
},
|
|
||||||
"brain": {
|
"brain": {
|
||||||
"type": "http",
|
"type": "http",
|
||||||
"url": "https://brain-mcp.d-ma.be/mcp",
|
"url": "https://brain-mcp.d-ma.be/mcp",
|
||||||
@@ -17,10 +13,6 @@
|
|||||||
"headers": {
|
"headers": {
|
||||||
"Authorization": "Bearer ${GITEA_MCP_TOKEN}"
|
"Authorization": "Bearer ${GITEA_MCP_TOKEN}"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"infra": {
|
|
||||||
"type": "http",
|
|
||||||
"url": "https://infra-mcp.d-ma.be/mcp"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,255 +1,44 @@
|
|||||||
# Agent context — Mathias workspace
|
# __PROJECT_NAME__ — agent context
|
||||||
|
|
||||||
<!-- Canonical root context for all AI coding agents.
|
Standalone context for agents that read `AGENTS.md` from the repo root. Claude Code uses
|
||||||
Lives at: ~/dev/.context/AGENT.md
|
`CLAUDE.md` (and tree-walks to `~/dev/CLAUDE.md`); this file mirrors the same essentials for
|
||||||
Applies to every project under ~/dev/ unless overridden.
|
any other harness.
|
||||||
|
|
||||||
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
|
## Project
|
||||||
|
|
||||||
I'm Mathias, a digital product manager and technology consultant based in Sweden.
|
- **Name**: __PROJECT_NAME__ — a Go agent (ADK + LiteLLM).
|
||||||
I build software, research emerging tech, and deliver consulting engagements
|
- **Owner**: Mathias · **Client**: personal · **Repo**: git.d-ma.be/mathias/__PROJECT_NAME__
|
||||||
for clients under NDA. I work across AI/ML, financial automation, web applications,
|
|
||||||
and climate/sustainability tech.
|
|
||||||
|
|
||||||
## How I work with agents
|
## Harness
|
||||||
|
|
||||||
- I think like a product manager — I care about *why* before *how*
|
Single harness: **Claude Code + hyperguild** — session-based (start a session, it works, it
|
||||||
- I want agents to be opinionated and push back, not just execute blindly
|
stops). There is **no** push-triggered dispatch, listener, or scheduled poller, and none should
|
||||||
- I prefer concise responses; skip ceremony and get to the point
|
be added without a fresh, friction-driven decision. MCP connections in `.mcp.json`:
|
||||||
- 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
|
- **brain** (`brain-mcp.d-ma.be`) — knowledge query/write. `BRAIN_MCP_TOKEN`.
|
||||||
|
- **gitea** (`git-mcp.d-ma.be`) — issues/PRs/repo, the audit trail. `GITEA_MCP_TOKEN`.
|
||||||
|
|
||||||
These rules apply to every task across every project, regardless of harness.
|
## Workflow
|
||||||
|
|
||||||
1. **No assumptions.** Don't hide confusion — surface it. Surface tradeoffs explicitly.
|
1. **Issue** — work is scoped as a Gitea issue (acceptance criteria + report-back format).
|
||||||
Think before coding; if the problem is unclear, ask or state assumptions before acting.
|
2. **Session** — a Claude Code + hyperguild session does the work in this repo.
|
||||||
2. **Minimum viable code.** Solve with the smallest change that works. Nothing
|
3. **PR** — branch off `main`; open a PR; CI (`task check`) is the gate.
|
||||||
speculative, no "while we're here" cleanups, no premature abstractions. Simplicity first.
|
4. **Report-back** — comment the outcome on the issue (issue comments are the audit surface).
|
||||||
3. **Surgical changes.** Touch only what the task requires. Leave unrelated code,
|
5. **Brain capture** — persist durable, non-obvious learnings to the brain.
|
||||||
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
|
## Conventions
|
||||||
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
|
- Go: standard tooling; `task check` (lint + vet + `go test -race`) before every PR.
|
||||||
PR flow only when a human reviewer outside the project is required. Document
|
- Errors wrapped (`fmt.Errorf("...: %w", err)`); structured `slog`.
|
||||||
the reason in PROJECT.md.
|
- Trunk-based: commit to `main` via PR; one logical change per commit; CI is the quality gate.
|
||||||
|
- Secrets via env (`BRAIN_MCP_TOKEN`, `GITEA_MCP_TOKEN`, `LITELLM_API_KEY`); never in code.
|
||||||
|
|
||||||
## Default stack
|
## Boundaries
|
||||||
|
|
||||||
| Layer | Default | Fallback | Last resort |
|
Runtime scope (network egress allow-list, file scope, approved operations, failure posture) is
|
||||||
|-------|---------|----------|-------------|
|
in `AGENT_BOUNDARIES.md`. Read it before adding tools, endpoints, or write access.
|
||||||
| 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
|
|
||||||
|
|
||||||
## 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://gitea.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 are available in `~/dev/.skills/`. Load on demand via the index.
|
|
||||||
|
|
||||||
See `~/dev/.skills/SKILLS_INDEX.md` for the full list with descriptions and "use when" triggers.
|
|
||||||
|
|
||||||
Key skills:
|
|
||||||
- **TDD**: always write tests first — load `tdd` skill
|
|
||||||
- **Code Review**: load `code-review` skill before any review
|
|
||||||
- **SOLID/Clean Code**: load `solid` or `clean-code` skill for design work
|
|
||||||
- **Problem first**: load `problem-analysis` skill before coding non-trivial features
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# __PROJECT_NAME__
|
|
||||||
|
|
||||||
## Identity
|
|
||||||
|
|
||||||
- **Name**: __PROJECT_NAME__
|
|
||||||
- **Owner**: Mathias
|
|
||||||
- **Client**: personal
|
|
||||||
- **Repo**: gitea.d-ma.be/mathias/__PROJECT_NAME__
|
|
||||||
- **Status**: active
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
|
|
||||||
Go + ADK + LiteLLM. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
|
||||||
|
|
||||||
## Agent
|
|
||||||
|
|
||||||
TODO: describe what this agent does, what tools it has, and what it's responsible for.
|
|
||||||
|
|
||||||
## Observability
|
## Observability
|
||||||
|
|
||||||
Traces → Jaeger via `OTLP_ENDPOINT`. Set `ADK_SERVICE_NAME=__PROJECT_NAME__` per deployment.
|
Traces → Jaeger via `OTLP_ENDPOINT`; `ADK_SERVICE_NAME=__PROJECT_NAME__`. Spans: `invoke_agent`,
|
||||||
Spans emitted: `invoke_agent`, `generate_content`. Tool spans require custom callbacks.
|
`generate_content`.
|
||||||
|
|||||||
+4
-2
@@ -22,7 +22,9 @@ Egress MUST be blocked to:
|
|||||||
- Public package registries from runtime (proxy through build only)
|
- Public package registries from runtime (proxy through build only)
|
||||||
- Customer/client domains not listed in the engagement scope
|
- Customer/client domains not listed in the engagement scope
|
||||||
|
|
||||||
Add new endpoints by editing `agent-policy.yaml` AND this table in the same commit.
|
Add new endpoints by editing this table in the same commit that wires them, and enforce them
|
||||||
|
with whatever egress mechanism the deployment uses (e.g. a k8s NetworkPolicy in the project's
|
||||||
|
own deploy manifests).
|
||||||
|
|
||||||
## File scope
|
## File scope
|
||||||
|
|
||||||
@@ -68,7 +70,7 @@ The agent MUST NOT, without explicit opt-in in code review:
|
|||||||
|
|
||||||
## Review triggers
|
## Review triggers
|
||||||
|
|
||||||
Bump this doc + `agent-policy.yaml` when:
|
Bump this doc (and the deployment's egress enforcement) when:
|
||||||
|
|
||||||
- A new external endpoint is added
|
- A new external endpoint is added
|
||||||
- A new tool with side effects is wired in
|
- A new tool with side effects is wired in
|
||||||
|
|||||||
@@ -5,18 +5,38 @@
|
|||||||
- **Name**: __PROJECT_NAME__
|
- **Name**: __PROJECT_NAME__
|
||||||
- **Owner**: Mathias
|
- **Owner**: Mathias
|
||||||
- **Client**: personal
|
- **Client**: personal
|
||||||
- **Repo**: gitea.d-ma.be/mathias/__PROJECT_NAME__
|
- **Repo**: git.d-ma.be/mathias/__PROJECT_NAME__
|
||||||
- **Status**: active
|
- **Status**: active
|
||||||
|
|
||||||
## Stack
|
## Stack
|
||||||
|
|
||||||
Go + ADK + LiteLLM. See `~/dev/.context/AGENT.md` for cross-project conventions.
|
Go + ADK + LiteLLM. Claude Code tree-walks to `~/dev/CLAUDE.md` for cross-project conventions.
|
||||||
|
|
||||||
## Agent
|
## Agent
|
||||||
|
|
||||||
TODO: describe what this agent does, what tools it has, and what it's responsible for.
|
TODO: describe what this agent does, what tools it has, and what it's responsible for.
|
||||||
|
|
||||||
|
## Harness & workflow
|
||||||
|
|
||||||
|
Single harness: **Claude Code + hyperguild** — session-based (you start a session, it works,
|
||||||
|
it stops; there is no push-triggered dispatch). MCP connections are in `.mcp.json`: **brain**
|
||||||
|
(knowledge query/write) and **gitea** (issues/PRs/repo — the audit trail). Provide
|
||||||
|
`BRAIN_MCP_TOKEN` and `GITEA_MCP_TOKEN` in the environment.
|
||||||
|
|
||||||
|
The loop for a unit of work:
|
||||||
|
|
||||||
|
1. **Issue** — the work is a Gitea issue (scope, acceptance criteria, report-back format).
|
||||||
|
2. **Session** — a Claude Code + hyperguild session does the work in this repo.
|
||||||
|
3. **PR** — branch off `main`, open a PR; CI (`task check`) is the gate.
|
||||||
|
4. **Report-back** — comment the outcome on the issue (issue comments are the audit surface).
|
||||||
|
5. **Brain capture** — if a learning is durable and non-obvious, write it to the brain.
|
||||||
|
|
||||||
## Observability
|
## Observability
|
||||||
|
|
||||||
Traces → Jaeger via `OTLP_ENDPOINT`. Set `ADK_SERVICE_NAME=__PROJECT_NAME__` per deployment.
|
Traces → Jaeger via `OTLP_ENDPOINT`. Set `ADK_SERVICE_NAME=__PROJECT_NAME__` per deployment.
|
||||||
Spans emitted: `invoke_agent`, `generate_content`. Tool spans require custom callbacks.
|
Spans emitted: `invoke_agent`, `generate_content`. Tool spans require custom callbacks.
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
|
||||||
|
Runtime scope (network egress, file scope, approved operations) is in `AGENT_BOUNDARIES.md` —
|
||||||
|
read it before adding tools, endpoints, or write access.
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ go mod tidy
|
|||||||
task run
|
task run
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Harness & workflow
|
||||||
|
|
||||||
|
Single harness: **Claude Code + hyperguild** — session-based (start a session, it works, it
|
||||||
|
stops). No push-triggered dispatch. MCP connections live in `.mcp.json`: **brain** (knowledge)
|
||||||
|
and **gitea** (issues/PRs — the audit trail); provide `BRAIN_MCP_TOKEN` and `GITEA_MCP_TOKEN`.
|
||||||
|
|
||||||
|
Work flows: **issue → hyperguild session → PR (`task check` gate) → report-back comment on the
|
||||||
|
issue → brain capture if the learning is durable**. See `AGENTS.md` / `CLAUDE.md` for the full
|
||||||
|
context, `AGENT_BOUNDARIES.md` for runtime scope.
|
||||||
|
|
||||||
## Observability
|
## Observability
|
||||||
|
|
||||||
Set `OTLP_ENDPOINT=http://jaeger.d-ma.be:4318` to emit traces. Each invocation produces:
|
Set `OTLP_ENDPOINT=http://jaeger.d-ma.be:4318` to emit traces. Each invocation produces:
|
||||||
|
|||||||
@@ -23,14 +23,3 @@ tasks:
|
|||||||
- golangci-lint run ./...
|
- golangci-lint run ./...
|
||||||
- go vet ./...
|
- go vet ./...
|
||||||
- go test ./... -race -count=1
|
- go test ./... -race -count=1
|
||||||
|
|
||||||
context:sync:
|
|
||||||
desc: Regenerate all harness-specific context files
|
|
||||||
cmds:
|
|
||||||
- bash scripts/context-sync.sh
|
|
||||||
context:sync:claude:
|
|
||||||
cmds: [bash scripts/context-sync.sh claude]
|
|
||||||
context:sync:agents:
|
|
||||||
cmds: [bash scripts/context-sync.sh agents]
|
|
||||||
context:sync:cursor:
|
|
||||||
cmds: [bash scripts/context-sync.sh cursor]
|
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
# NetworkPolicy for __PROJECT_NAME__.
|
|
||||||
#
|
|
||||||
# Pairs with AGENT_BOUNDARIES.md. Egress is allow-listed: LiteLLM, brain-mcp,
|
|
||||||
# gitea-mcp, OTLP collector, in-cluster DNS. Everything else is denied.
|
|
||||||
#
|
|
||||||
# Apply in the __PROJECT_NAME__ namespace. Substitute __PROJECT_NAME__ at
|
|
||||||
# render time (envsubst, kustomize replacement, or sed in CI).
|
|
||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: __PROJECT_NAME__-egress
|
|
||||||
namespace: __PROJECT_NAME__
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: __PROJECT_NAME__
|
|
||||||
app.kubernetes.io/component: agent
|
|
||||||
spec:
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: __PROJECT_NAME__
|
|
||||||
policyTypes:
|
|
||||||
- Egress
|
|
||||||
egress:
|
|
||||||
# In-cluster DNS — required for resolving any of the endpoints below.
|
|
||||||
- to:
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: kube-system
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
k8s-app: kube-dns
|
|
||||||
ports:
|
|
||||||
- protocol: UDP
|
|
||||||
port: 53
|
|
||||||
- protocol: TCP
|
|
||||||
port: 53
|
|
||||||
|
|
||||||
# LiteLLM — model inference proxy.
|
|
||||||
- to:
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: litellm
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: litellm
|
|
||||||
ports:
|
|
||||||
- protocol: TCP
|
|
||||||
port: 4000
|
|
||||||
|
|
||||||
# Brain MCP — knowledge base query/write.
|
|
||||||
- to:
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: ingestion
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: brain-mcp
|
|
||||||
ports:
|
|
||||||
- protocol: TCP
|
|
||||||
port: 8080
|
|
||||||
|
|
||||||
# Gitea MCP — repo/issue/PR access.
|
|
||||||
- to:
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: gitea
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: gitea-mcp
|
|
||||||
ports:
|
|
||||||
- protocol: TCP
|
|
||||||
port: 8080
|
|
||||||
|
|
||||||
# OTLP — trace export to Jaeger collector.
|
|
||||||
- to:
|
|
||||||
- namespaceSelector:
|
|
||||||
matchLabels:
|
|
||||||
kubernetes.io/metadata.name: observability
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: jaeger
|
|
||||||
ports:
|
|
||||||
- protocol: TCP
|
|
||||||
port: 4318
|
|
||||||
---
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: NetworkPolicy
|
|
||||||
metadata:
|
|
||||||
name: __PROJECT_NAME__-default-deny
|
|
||||||
namespace: __PROJECT_NAME__
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: __PROJECT_NAME__
|
|
||||||
spec:
|
|
||||||
podSelector:
|
|
||||||
matchLabels:
|
|
||||||
app.kubernetes.io/name: __PROJECT_NAME__
|
|
||||||
policyTypes:
|
|
||||||
- Ingress
|
|
||||||
- Egress
|
|
||||||
# Empty rules = deny-all. The allow-list above is additive on Egress.
|
|
||||||
# Ingress stays denied unless a sibling policy opens specific ports.
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Generates harness-specific context files from .context/PROJECT.md
|
|
||||||
# Project-level script — run from a project directory.
|
|
||||||
#
|
|
||||||
# For Claude Code: generates project-only CLAUDE.md (it inherits root via tree walk)
|
|
||||||
# For everything else: concatenates root AGENT.md + project PROJECT.md
|
|
||||||
#
|
|
||||||
# Usage: ./scripts/context-sync.sh [--force] [adapter...]
|
|
||||||
# Task: task context:sync
|
|
||||||
#
|
|
||||||
# Override root context: ROOT_CONTEXT=~/dev/.context/AGENT.md ./scripts/context-sync.sh
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Parse --force flag and collect adapter names separately
|
|
||||||
FORCE=false
|
|
||||||
ADAPTERS=()
|
|
||||||
for _arg in "$@"; do
|
|
||||||
case "$_arg" in
|
|
||||||
--force) FORCE=true ;;
|
|
||||||
*) ADAPTERS+=("$_arg") ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
PROJECT_FILE=".context/PROJECT.md"
|
|
||||||
|
|
||||||
# Walk up to find root .context/AGENT.md
|
|
||||||
find_root_context() {
|
|
||||||
local dir
|
|
||||||
dir="$(pwd)"
|
|
||||||
while [ "$dir" != "/" ]; do
|
|
||||||
dir="$(dirname "$dir")"
|
|
||||||
if [ -f "$dir/.context/AGENT.md" ]; then
|
|
||||||
echo "$dir/.context/AGENT.md"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
ROOT_CONTEXT="${ROOT_CONTEXT:-$(find_root_context)}"
|
|
||||||
|
|
||||||
if [ ! -f "$PROJECT_FILE" ]; then
|
|
||||||
echo "Error: $PROJECT_FILE not found. Are you in a project root?"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Pre-flight: reject unfilled {{...}} placeholders unless --force
|
|
||||||
if [ "$FORCE" = false ]; then
|
|
||||||
_placeholders=$(grep -n '{{[^}]*}}' "$PROJECT_FILE" 2>/dev/null || true)
|
|
||||||
if [ -n "$_placeholders" ]; then
|
|
||||||
echo "Error: unfilled placeholders in $PROJECT_FILE:" >&2
|
|
||||||
while IFS= read -r _match; do
|
|
||||||
_lineno="${_match%%:*}"
|
|
||||||
_content="${_match#*:}"
|
|
||||||
_token=$(printf '%s' "$_content" | grep -o '{{[^}]*}}' | head -1)
|
|
||||||
echo " $PROJECT_FILE:$_lineno: unfilled placeholder $_token" >&2
|
|
||||||
done <<< "$_placeholders"
|
|
||||||
echo "" >&2
|
|
||||||
echo "Fill these placeholders, then re-run: task context:sync" >&2
|
|
||||||
echo "To bypass validation: bash scripts/context-sync.sh --force" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$ROOT_CONTEXT" ] && [ -f "$ROOT_CONTEXT" ]; then
|
|
||||||
echo " Root context: $ROOT_CONTEXT"
|
|
||||||
else
|
|
||||||
echo " No root AGENT.md found (project context only)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Emit root context + separator
|
|
||||||
root_block() {
|
|
||||||
if [ -n "$ROOT_CONTEXT" ] && [ -f "$ROOT_CONTEXT" ]; then
|
|
||||||
cat "$ROOT_CONTEXT"
|
|
||||||
echo ""
|
|
||||||
echo "---"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Claude Code ──────────────────────────────────────────────
|
|
||||||
# Claude Code walks up the tree — it finds ~/dev/CLAUDE.md automatically.
|
|
||||||
# Project-level CLAUDE.md only needs project-specific context.
|
|
||||||
generate_claude() {
|
|
||||||
cat "$PROJECT_FILE" > CLAUDE.md
|
|
||||||
echo " → CLAUDE.md (project-only; Claude Code inherits root)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── AGENTS.md (Crush, Pi, Antigravity) ──────────────────────
|
|
||||||
# These tools read AGENTS.md from cwd but don't walk up.
|
|
||||||
# Concatenate root + project.
|
|
||||||
generate_agents() {
|
|
||||||
{ root_block; cat "$PROJECT_FILE"; } > AGENTS.md
|
|
||||||
echo " → AGENTS.md (root + project; Crush, Pi, Antigravity)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Cursor ───────────────────────────────────────────────────
|
|
||||||
generate_cursor() {
|
|
||||||
{
|
|
||||||
echo "# Cursor rules — auto-generated"
|
|
||||||
echo "# Do not edit. Run: task context:sync"
|
|
||||||
echo ""
|
|
||||||
root_block
|
|
||||||
cat "$PROJECT_FILE"
|
|
||||||
} > .cursorrules
|
|
||||||
echo " → .cursorrules (root + project)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Aider ────────────────────────────────────────────────────
|
|
||||||
generate_aider() {
|
|
||||||
{ root_block; cat "$PROJECT_FILE"; } > .aider.conventions.md
|
|
||||||
if [ ! -f .aider.conf.yml ]; then
|
|
||||||
cat > .aider.conf.yml << 'YAML'
|
|
||||||
read: .aider.conventions.md
|
|
||||||
auto-commits: false
|
|
||||||
YAML
|
|
||||||
fi
|
|
||||||
echo " → .aider.conventions.md (root + project)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── Generic system prompt (Open WebUI, Mods, etc.) ──────────
|
|
||||||
generate_system_prompt() {
|
|
||||||
{
|
|
||||||
echo "You are a coding assistant working on a specific project."
|
|
||||||
echo "Follow all conventions from both the root agent context and project context."
|
|
||||||
echo ""
|
|
||||||
echo "---"
|
|
||||||
echo ""
|
|
||||||
root_block
|
|
||||||
cat "$PROJECT_FILE"
|
|
||||||
echo ""
|
|
||||||
echo "---"
|
|
||||||
} > .context/system-prompt.txt
|
|
||||||
echo " → .context/system-prompt.txt (root + project)"
|
|
||||||
}
|
|
||||||
|
|
||||||
# ── MCP config ───────────────────────────────────────────────
|
|
||||||
generate_mcp() {
|
|
||||||
# Ensure baseline file exists with project-specific knowledge server
|
|
||||||
if [ ! -f .context/mcp.json ]; then
|
|
||||||
cat > .context/mcp.json << 'JSON'
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"knowledge": {
|
|
||||||
"url": "http://localhost:3100/mcp",
|
|
||||||
"description": "Project knowledge base — vector + graph retrieval"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JSON
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Merge root mcp-servers.json if found alongside root AGENT.md
|
|
||||||
local root_mcp=""
|
|
||||||
if [ -n "$ROOT_CONTEXT" ] && [ -f "$ROOT_CONTEXT" ]; then
|
|
||||||
local candidate
|
|
||||||
candidate="$(dirname "$ROOT_CONTEXT")/mcp-servers.json"
|
|
||||||
[ -f "$candidate" ] && root_mcp="$candidate"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$root_mcp" ]; then
|
|
||||||
echo " → .context/mcp.json (exists, no root mcp-servers.json found)"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Root servers take precedence over project entries on key conflict
|
|
||||||
local root_servers count updated
|
|
||||||
root_servers=$(jq '.servers' "$root_mcp")
|
|
||||||
count=$(printf '%s' "$root_servers" | jq 'keys | length')
|
|
||||||
updated=$(jq --argjson root "$root_servers" \
|
|
||||||
'.mcpServers = (.mcpServers + $root)' \
|
|
||||||
.context/mcp.json)
|
|
||||||
printf '%s\n' "$updated" > .context/mcp.json
|
|
||||||
echo " → .context/mcp.json (merged $count root servers)"
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Syncing project context from $PROJECT_FILE..."
|
|
||||||
|
|
||||||
if [ ${#ADAPTERS[@]} -eq 0 ]; then
|
|
||||||
generate_claude
|
|
||||||
generate_agents
|
|
||||||
generate_cursor
|
|
||||||
generate_aider
|
|
||||||
generate_system_prompt
|
|
||||||
generate_mcp
|
|
||||||
else
|
|
||||||
for adapter in "${ADAPTERS[@]}"; do
|
|
||||||
case "$adapter" in
|
|
||||||
claude) generate_claude ;;
|
|
||||||
agents) generate_agents ;;
|
|
||||||
cursor) generate_cursor ;;
|
|
||||||
aider) generate_aider ;;
|
|
||||||
prompt|system|openwebui|owui|generic) generate_system_prompt ;;
|
|
||||||
mcp) generate_mcp ;;
|
|
||||||
*) echo "Unknown adapter: $adapter" >&2; exit 1 ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Done."
|
|
||||||
Reference in New Issue
Block a user