feat: Railiance package and deploy (HARNESS-WP-0001-T06)

Container image, k8s namespace/deployment/smoke job, host venv install path,
and deterministic agent-harness smoke (sandbox commit+push+hub) for remote
verification without Claude Code on the worker host.
This commit is contained in:
tegwick 2026-07-18 10:48:44 +02:00
parent 4144eba160
commit 67f1791491
15 changed files with 520 additions and 1 deletions

55
deploy/README.md Normal file
View file

@ -0,0 +1,55 @@
# Railiance deployment (HARNESS-WP-0001-T06)
Single shared harness instance on **railiance01**. Secrets stay on the host
(Lanes 23); the container image is the portable runtime package.
## Layout
| Path | Role |
|------|------|
| `Containerfile` | Image: Python CLI + git + openssh; optional vendored llm-connect |
| `deploy/k8s/railiance/` | Namespace, ConfigMap, Deployment, smoke Job |
| `deploy/scripts/railiance-smoke.sh` | Host e2e: clone sandbox → commit → push → hub |
| `agent-harness smoke` | Deterministic smoke (no Claude Code required) |
## Prerequisites (done 2026-07-17)
- Lane 2 deploy key on host + Forgejo write on `coulomb/executor-sandbox`
- Lane 3 AppRole under `~/.local/agent-harness/approle-binky-mail`
- `source ~/.local/agent-harness/env`
- Hub: `http://127.0.0.1:18000` (ops-bridge) or in-cluster `state-hub.state-hub.svc`
## Build & load image (workstation → railiance01)
```bash
# from agent-harness repo root
make image # tags agent-harness:railiance01
make image-export # /tmp/agent-harness-railiance01.tar
scp /tmp/agent-harness-railiance01.tar railiance01:/tmp/
ssh railiance01 sudo k3s ctr images import /tmp/agent-harness-railiance01.tar
```
## Apply k8s
```bash
rsync -a deploy/k8s/railiance/ railiance01:agent-harness/deploy/k8s/railiance/
ssh railiance01 kubectl apply -k agent-harness/deploy/k8s/railiance/
ssh railiance01 kubectl -n agent-harness rollout status deploy/agent-harness
```
## Host smoke (authoritative e2e gate)
Full path uses the host deploy key and hub bridge:
```bash
ssh railiance01 'bash ~/agent-harness/deploy/scripts/railiance-smoke.sh'
```
Expect: local commit + push to `executor-sandbox`, hub event `harness_smoke`,
`.kaizen/metrics/coach/` on the sandbox checkout.
## Personal follow-ups (not T06)
- At **binky cutover only**: attach the same deploy key to `coulomb/binky-control`
- Claude Code on the host (or hosted adapter) for real agentic sessions
- T03 issue-core intake for scheduled task consumption

View file

@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: agent-harness
labels:
app.kubernetes.io/part-of: agent-harness
app.kubernetes.io/name: agent-harness

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: agent-harness-config
namespace: agent-harness
labels:
app.kubernetes.io/name: agent-harness
data:
# In-cluster State Hub (production). Host-level smoke may override to
# http://127.0.0.1:18000 (ops-bridge reverse tunnel to workstation hub).
STATE_HUB_URL: "http://state-hub.state-hub.svc.cluster.local:8000"
BAO_ADDR: "https://bao.coulomb.social"
VAULT_ADDR: "https://bao.coulomb.social"

View file

@ -0,0 +1,52 @@
# Long-lived instance placeholder until T03 task intake polls issue-core.
# Keeps one ready replica with harness CLI + git tools; no LLM session here.
apiVersion: apps/v1
kind: Deployment
metadata:
name: agent-harness
namespace: agent-harness
labels:
app.kubernetes.io/name: agent-harness
app.kubernetes.io/part-of: agent-harness
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: agent-harness
template:
metadata:
labels:
app.kubernetes.io/name: agent-harness
app.kubernetes.io/part-of: agent-harness
spec:
securityContext:
fsGroup: 10001
containers:
- name: agent-harness
image: agent-harness:railiance01
imagePullPolicy: Never
command: ["sleep", "infinity"]
envFrom:
- configMapRef:
name: agent-harness-config
resources:
requests:
cpu: 25m
memory: 64Mi
limits:
cpu: 500m
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}

View file

@ -0,0 +1,47 @@
# One-shot smoke Job. Prefer host-level smoke (deploy/scripts/railiance-smoke.sh)
# when deploy keys live on the host. This Job is for image/k8s path verification
# with --no-push (no deploy key in-cluster yet).
apiVersion: batch/v1
kind: Job
metadata:
name: agent-harness-smoke
namespace: agent-harness
labels:
app.kubernetes.io/name: agent-harness
app.kubernetes.io/component: smoke
spec:
ttlSecondsAfterFinished: 600
backoffLimit: 1
template:
metadata:
labels:
app.kubernetes.io/name: agent-harness
app.kubernetes.io/component: smoke
spec:
restartPolicy: Never
securityContext:
fsGroup: 10001
containers:
- name: smoke
image: agent-harness:railiance01
imagePullPolicy: Never
args:
- "profiles"
envFrom:
- configMapRef:
name: agent-harness-config
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001

View file

@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: agent-harness
resources:
- 00-namespace.yaml
- configmap.yaml
- deployment.yaml
- job-smoke.yaml

View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Host-level Railiance smoke for agent-harness (HARNESS-WP-0001-T06).
# Run on railiance01 after install. Uses deploy key + AppRole env + hub :18000.
set -euo pipefail
ROOT="${AGENT_HARNESS_ROOT:-$HOME/agent-harness}"
# shellcheck disable=SC1090
source "${HOME}/.local/agent-harness/env"
export STATE_HUB_URL="${STATE_HUB_URL:-http://127.0.0.1:18000}"
export PATH="${HOME}/.local/bin:${PATH}"
export PYTHONPATH="${ROOT}:${HOME}/llm-connect${PYTHONPATH:+:$PYTHONPATH}"
cd "$ROOT"
if ! command -v agent-harness >/dev/null 2>&1; then
python3 -m pip install --user -e . -q
fi
echo "STATE_HUB_URL=$STATE_HUB_URL"
curl -sS -m 5 "$STATE_HUB_URL/state/health" || curl -sS -m 5 "${STATE_HUB_URL%/}/" || true
echo
agent-harness smoke \
--work-dir "${HOME}/work/executor-sandbox" \
--remote "ssh://git@forgejo-agent-harness/coulomb/executor-sandbox.git"