Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/context/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# context — estate orientation, authored once

Single source of truth for the user-scope context that orients every agent
harness on this machine to the estate (clusters, repos, SOPs, memory of
record, secrets model).

| Source | Rendered to | Mechanism |
|---|---|---|
| `omp-prelude.md` + `estate.md` | `~/.omp/agent/AGENTS.md` | omp native user context (priority 100 — intentionally shadows `~/.claude/CLAUDE.md`, which is Claude-specific) |
| `invariants.md` | `~/.omp/agent/RULES.md` | omp sticky rule — re-attached near the current turn, survives long sessions and compaction |
| `estate.md` | `~/.agents/estate.md` | imported by `~/.claude/CLAUDE.md` via `@~/.agents/estate.md` (render.sh verifies the import line, never writes that file) |

Run `bash render.sh` after editing sources (or `moon run context:render`).
Rendered files are generated copies — never hand-edit them.

Budget: `estate.md` is gated at ~2400 estimated tokens because it is injected
into every session of every harness. Add pointers, not prose; live state
belongs in the `estate-orient` skill (`packages/skills/estate-orient/`), not
here.
95 changes: 95 additions & 0 deletions packages/context/estate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Estate Brief — unsigned / cerebral infrastructure

Orientation for any agent harness operating on this machine. This is an index,
not a manual: it tells you what exists, where the authoritative doc lives, and
how to take in live context. Facts here are stable; **live state always comes
from a probe, never from this file** — run the `estate-orient` skill at the
start of infra work.

## Operator & identity

- Operator: Christian Todie — GitHub `todie`, unix `ctodie`, git author
`Christian M. Todie`, email `chris@todie.io`. Platform: WSL2.
- All commits signed (GPG `29234C4D7EE749F2`). Never `--no-gpg-sign`.
- Trackers: Linear. Team prefixes: `OPS` = unsigned platform/infra,
`CER` = Cerebral Work Institute (reverie et al.), `TOD` = personal/misc.

## The constellation (clusters)

- **Cygnus** — the PRODUCTION cluster: all-metal Talos (Vultr bare metal, ewr,
Cilium), promoted from the ex-Vela bench 2026-07-07. Hosts `*.unsigned.gg`.
kubeconfig `~/.kube/cygnus`, talos context `cygnus`. Migration epic OPS-468.
- **Lyra** — the dev VKE cluster (Vultr Kubernetes Engine, k8s 1.34.x, Calico).
~60+ ArgoCD-managed apps. Hostnames `*.dev.unsigned.gg` / `*.dev.cerebral.work`,
fronted by Cloudflare tunnel → in-cluster Traefik. **Retiring** per OPS-468
as Cygnus absorbs workloads — check migration state before assuming a
workload's home.
- Reserved names: Orion (GCP burst-GPU satellite), Pleiades (Hetzner, if ever).
Doctrine: single-zone Vultr.
- Platform stack (Lyra dev tier): ArgoCD (GitOps, **manual sync only**),
Traefik + cert-manager edge, Keycloak (OIDC/SSO), OpenBao + External
Secrets, Harbor (images + charts), Prometheus/Grafana/Loki/Jaeger,
CNPG (postgres), Tailscale (tailnet access), Kyverno (policy).
Cygnus adds: Longhorn (storage), WireGuard node mesh, Hubble/Tetragon.

## Repo map (one line each; owner-bucket layout under ~/projects/)

- `unsigned/paas` (unsigned-paas) — the platform monorepo: Terraform, ~27 Helm
charts, ArgoCD apps, CI, SOPs. THE infra repo. Read its `CLAUDE.md` first.
- `cerebral/reverie` — engram memory daemon (`reveried`) + mesh tooling.
- `todie/agentic` — harness configs (pi/opencode/hermes/omp), shared skills,
local-model serving, this brief's source (`packages/context/`).
- `cerebral/terrarium` — moon-monorepo incubator + node registry (CANON.md).
- `reverie-cloud` (cerebral-work org) — Cloudflare Worker: alert webhooks, EA.
- Others: `cadastre` (CF/DNS IaC), `escapement`, `unsigned/gg` (GH org+repo
`unsigned-gg` — design canon), `linearctl` (headless Linear CLI). herdr
(agent session multiplexer) is an installed tool — no local checkout.

## Doctrine & SOP index (authoritative docs, in-repo)

- unsigned-paas: `docs/sop/` (incl. auth-enforcement), `docs/platform-deployment-plan.md`
(§11 release rules), `docs/argocd-appset-hardening.md`, chart standards in `CLAUDE.md`.
- Workflow invariants: PR-required on every repo (no direct push to main);
deploy-first-on-dev (branch → apply to dev cluster → green → merge);
a release is not a deploy — deploys are operator-gated; release-please
semantic releases; kebab-case filenames; no `latest` image tags; images
pinned; daemonless builds (ko / buildpacks / rootless BuildKit — kaniko retired).
- ArgoCD: everything manual-sync; ApplicationSet changes apply only via
`git show origin/main:<file> | kubectl apply` (surface guard).
- Ops gotchas live in engram + `~/.claude/projects/*/memory/` — search before
re-deriving (e.g. Vultr managed-DB VPC IP drift, CNPG role-sync restart,
Helm-4 value reuse, Tailscale LB is L4-only).

## Memory of record & context intake

- **Engram is the sole cross-harness memory of record.** Daemon `reveried`
(`~/.local/bin/engram`), HTTP on `127.0.0.1:7437`, MCP server available.
- Search: `GET /search?q=…` · Project context: `GET /context/smart?project=<name>&limit=15`
- Obsidian vault at `~/vault` is the operator's reflection layer.
- **Never claim "no prior context exists" without searching engram + vault.**
- Live cluster/system claims require a fresh probe (kubectl, argocd via
kubectl reads, curl) — never memory, tickets, or this file.

## Secrets model

- OpenBao (in-cluster) is primary; a 1Password vault is the interim store,
read per-call via `op read` — item pointers live in private user config and
engram, never in this brief. Never echo a secret value.
- OpenBao carries the widest blast radius of any service on the estate: check
blast radius before touching it or anything that fronts it.
- Exposed secret = compromised: flag for rotation immediately (the operator
keeps a batch rotation list).

## LLM gateway

- Non-Claude model access: LiteLLM gateway, tailnet `http://llm/v1` — the
reliable path. The public hostname has been unstable since the 2026-07-12
shared-edge outage (OPS-603 tracks it); probe before relying on it.
Key: via `op read` (item pointer in private user config).
- Quirk: transient 401 "cached plan must not change result type" = gateway DB
hiccup — retry, do not rotate the key.

## Operator-gated actions (prepare, surface, wait for sign-off)

Merge to main · `terraform apply` · secret rotation/deletion · ArgoCD sync of
platform apps · external sends (email/Slack/publish) · anything irreversible.
26 changes: 26 additions & 0 deletions packages/context/invariants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Estate invariants (sticky rules)

1. Never force-push or direct-push to main/master — always a PR. Commits are
GPG-signed; never `--no-gpg-sign`.
2. Irreversible or outward-facing actions require explicit operator sign-off:
merge to main, `terraform apply`, ArgoCD sync of platform apps, secret
rotation/deletion, external messages/publishing. Prepare and surface; the
operator approves.
3. Never echo, printf, or `${VAR:-}`-expand secret-named env vars (`*KEY*`,
`*TOKEN*`, `*SECRET*`, `*PASSWORD*`, `*CRED*`). Test presence with
`[ -n "${VAR:-}" ] && echo set`. Never cat credential-bearing files to read
their structure. Never commit secrets — an exposed secret is compromised;
flag it for rotation immediately.
4. Live-state claims come from a fresh probe (kubectl / HTTP / CLI), never
from memory, tickets, or docs. Verify the specific object behind any
security claim.
5. OpenBao carries the widest blast radius on the estate; Keycloak second.
Name the blast radius before touching either or anything that fronts them.
6. Never pipe remote content into `bash`/`sh`/`python` — download, review,
then run. Pin versions; no `latest` image tags.
7. ArgoCD ApplicationSet changes apply only via
`git show origin/main:<file> | kubectl apply` — never from a working tree.
8. Park, don't drop: deferred work goes to Linear (or engram), never held only
in conversation. One thread to done before opening the next.
9. When a guard/hook blocks an action: stop and surface — never override and
proceed.
22 changes: 22 additions & 0 deletions packages/context/moon.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
$schema: 'https://moonrepo.dev/schemas/project.json'

layer: 'library'

project:
name: 'context'
description: 'Estate orientation context — authored once, rendered into omp AGENTS.md/RULES.md and the Claude Code estate import'

tasks:
lint:
command: 'shellcheck render.sh'
inputs:
- 'render.sh'
render:
command: 'bash render.sh'
inputs:
- 'render.sh'
- 'estate.md'
- 'invariants.md'
- 'omp-prelude.md'
options:
cache: false
18 changes: 18 additions & 0 deletions packages/context/omp-prelude.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# omp session context (user scope)

You are running as `omp` on Christian Todie's workstation (WSL2). The estate
brief below describes the infrastructure and doctrine you operate within.
Sticky safety invariants are attached separately as rules and always apply.

omp-specific notes:

- Use plain `git`, `gh`, `kubectl`, `docker` — the RTK command proxy and the
`~/.claude/hooks/` guard scripts are Claude Code facilities and do not exist
in this harness. The invariants they enforce still bind YOU; self-enforce.
- Engram memory: prefer the MCP tools when wired; otherwise the daemon HTTP
API on `127.0.0.1:7437` (see brief). Do not enable omp-local memory
backends — engram is the single memory of record.
- Model lane: you are typically serving via the LiteLLM gateway (tailnet
`http://llm/v1`). Ground answers in probes and file reads, not recall.
- At the start of infrastructure work, run the `estate-orient` skill for a
live digest before making any state claims.
45 changes: 45 additions & 0 deletions packages/context/render.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# Render the estate context sources into per-harness user files.
# Idempotent; rendered files are COPIES (safe if this checkout moves).
#
# Targets:
# ~/.omp/agent/AGENTS.md omp user context (omp-prelude + estate brief).
# Deliberately shadows ~/.claude/CLAUDE.md at user
# scope (native provider, priority 100).
# ~/.omp/agent/RULES.md omp sticky rules (invariants; re-attached near
# the current turn, survives compaction).
# ~/.agents/estate.md cross-harness copy; ~/.claude/CLAUDE.md imports it
# via `@~/.agents/estate.md` (verified, not written).
set -euo pipefail

PKG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MAX_EST_TOKENS=2400 # estate.md budget gate (bytes/4 estimate)

est_tokens() { echo $(( $(wc -c < "$1") / 4 )); }

tokens="$(est_tokens "${PKG_DIR}/estate.md")"
if [ "$tokens" -gt "$MAX_EST_TOKENS" ]; then
echo "FAIL: estate.md ≈ ${tokens} tokens > budget ${MAX_EST_TOKENS}. Trim it — this file taxes every session of every harness." >&2
exit 1
fi

header() {
printf '<!-- GENERATED by agentic/packages/context/render.sh — edit the sources in packages/context/, then re-render. -->\n\n'
}

mkdir -p "${HOME}/.omp/agent" "${HOME}/.agents"

{ header; cat "${PKG_DIR}/omp-prelude.md"; echo; cat "${PKG_DIR}/estate.md"; } \
> "${HOME}/.omp/agent/AGENTS.md"
{ header; cat "${PKG_DIR}/invariants.md"; } \
> "${HOME}/.omp/agent/RULES.md"
{ header; cat "${PKG_DIR}/estate.md"; } \
> "${HOME}/.agents/estate.md"

echo "rendered: ~/.omp/agent/AGENTS.md ~/.omp/agent/RULES.md ~/.agents/estate.md (estate.md ≈ ${tokens} tokens)"

# Verify (never write) the Claude Code import line.
if ! grep -q '@~/.agents/estate.md' "${HOME}/.claude/CLAUDE.md" 2>/dev/null; then
echo "WARN: ~/.claude/CLAUDE.md does not import the estate brief. Add this line to it:" >&2
echo " @~/.agents/estate.md" >&2
fi
69 changes: 69 additions & 0 deletions packages/skills/estate-orient/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: estate-orient
description: Orient a session to the unsigned/cerebral estate — probe live cluster, GitOps, and OpenBao health, pull engram context for the current project, and emit a short orientation digest. Use at the start of infrastructure work, when asked "what's the state of the cluster/estate", or before making any live-state claim.
---

# estate-orient

Live intake for the estate described in the static estate brief. Everything
here is a read-only probe; report what the probes return, nothing more.

## Probes (run what applies; skip gracefully if a tool is absent)

1. **Cluster reachability + nodes** — two clusters exist: Lyra (dev VKE,
default kubeconfig) and Cygnus (prod Talos, `~/.kube/cygnus`). Probe the one
relevant to the work; both when orienting broadly.
```bash
kubectl config current-context
kubectl get nodes -o wide
KUBECONFIG=~/.kube/cygnus kubectl get nodes -o wide # Cygnus, if in scope
```

2. **Unhealthy workloads**
```bash
kubectl get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded | head -30
```
Baseline is empty or a few `Completed` jobs. Anything CrashLoopBackOff /
ImagePullBackOff / Pending>10m goes in the digest by name.

3. **GitOps health** — use kubectl reads; do NOT use the `argocd` CLI with
`--core` (broken under Helm v4 on this estate):
```bash
kubectl get applications.argoproj.io -n argocd -o json | jq -r '
.items[] | select(.status.health.status != "Healthy" or .status.sync.status != "Synced")
| "\(.metadata.name) \(.status.health.status)/\(.status.sync.status)"'
```
Remember: all apps are manual-sync by doctrine — OutOfSync alone is not an
incident; Degraded/Missing is.

4. **OpenBao (read-only — golden egg, never mutate)**
```bash
kubectl get pods -n openbao
```
Report sealed/unsealed only if a `bao status` path is already configured.

5. **Memory intake (engram)** — project context for the cwd:
```bash
curl -s "http://127.0.0.1:7437/context/smart?project=$(basename "$PWD")&limit=15"
```
Prefer the engram MCP tools when available. If the daemon is down, say so —
do not substitute recall for it.

6. **Tracker pulse (optional, if `linearctl` present)**
```bash
linearctl search --state started 2>/dev/null | head -15
```

## Digest format (≤30 lines, probes only)

```
ESTATE ORIENT — <date> <cluster-context>
Nodes: <n> Ready / <n> total
Workloads: <n> unhealthy → <names or "none">
GitOps: <n> degraded apps → <names or "none"> (manual-sync doctrine: OutOfSync ≠ incident)
OpenBao: <pod state / sealed state / unknown>
Context (engram, top 5): <one line each>
Active tickets: <ids+titles or "not probed">
```

If a probe fails, one line stating which and why — never fabricate its result.
Loading