Merge pull request 'Rename the owner agent host to worker.bstein.dev (supersedes #41)' (#42) from feature/hermes-domain-rename-agent-worker-v2 into main

Reviewed-on: atlas/titan-iac#42
Reviewed-by: bstein <bstein@noreply.scm.bstein.dev>
This commit is contained in:
bstein 2026-08-21 23:16:04 +00:00
commit 66c1c11d06
29 changed files with 2023 additions and 121 deletions

View File

@ -49,6 +49,7 @@ data:
192.168.22.9 triage.bstein.dev 192.168.22.9 triage.bstein.dev
192.168.22.9 triage.hermes.bstein.dev 192.168.22.9 triage.hermes.bstein.dev
192.168.22.9 vault.bstein.dev 192.168.22.9 vault.bstein.dev
192.168.22.9 worker.bstein.dev
fallthrough fallthrough
} }
} }

View File

@ -1,8 +1,8 @@
{ {
"counts": { "counts": {
"helmrelease_host_hints": 23, "helmrelease_host_hints": 23,
"http_endpoints": 61, "http_endpoints": 65,
"services": 91, "services": 98,
"workloads": 125 "workloads": 130
} }
} }

View File

@ -106,6 +106,31 @@
"path": "services/hermes-chat", "path": "services/hermes-chat",
"targetNamespace": "hermes-chat" "targetNamespace": "hermes-chat"
}, },
{
"name": "hermes-observer-bindings",
"path": "services/hermes-observer-bindings",
"targetNamespace": null
},
{
"name": "hermes-observer-rbac",
"path": "services/hermes-observer-rbac",
"targetNamespace": null
},
{
"name": "hermes-scm-broker",
"path": "services/hermes-scm-broker",
"targetNamespace": "hermes-scm"
},
{
"name": "hermes-scm-broker-code",
"path": "services/hermes/scm-common",
"targetNamespace": "hermes-scm"
},
{
"name": "hermes-scm-namespace",
"path": "services/hermes-scm-namespace",
"targetNamespace": null
},
{ {
"name": "hermes-triage-demo", "name": "hermes-triage-demo",
"path": "services/hermes-triage-demo", "path": "services/hermes-triage-demo",
@ -251,6 +276,11 @@
"path": "infrastructure/vault-csi", "path": "infrastructure/vault-csi",
"targetNamespace": "kube-system" "targetNamespace": "kube-system"
}, },
{
"name": "vault-hermes-jenkins-token-seed",
"path": "services/vault-hermes-jenkins-token-seed",
"targetNamespace": "vault"
},
{ {
"name": "vault-injector", "name": "vault-injector",
"path": "infrastructure/vault-injector", "path": "infrastructure/vault-injector",
@ -304,7 +334,7 @@
"node-role.kubernetes.io/worker": "true" "node-role.kubernetes.io/worker": "true"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-464" "registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-479"
] ]
}, },
{ {
@ -320,7 +350,7 @@
"node-role.kubernetes.io/worker": "true" "node-role.kubernetes.io/worker": "true"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-464" "registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-479"
] ]
}, },
{ {
@ -902,7 +932,7 @@
"serviceAccountName": "hermes-node-ssh-access", "serviceAccountName": "hermes-node-ssh-access",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"busybox:1.37" "python@sha256:6d43704baacd1bfbe7c295d7f13079d5d8104ed33568873133f8fc69980419df"
] ]
}, },
{ {
@ -915,8 +945,8 @@
"serviceAccountName": "hermes-triage", "serviceAccountName": "hermes-triage",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8", "registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37",
"registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1" "registry.bstein.dev/bstein/hermes-webui@sha256:ac6ba7bfd8a86227f31a9a96ebea41227ccf70391f7dcf34206f4d58e835e50e"
] ]
}, },
{ {
@ -930,7 +960,7 @@
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561", "quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561",
"registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8" "registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
] ]
}, },
{ {
@ -943,7 +973,7 @@
"serviceAccountName": "hermes-chat", "serviceAccountName": "hermes-chat",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/hermes-chat-router@sha256:a4010fdc5b6dce2696e6fec06eb38a3992817faa01ff3472122c870038b22bd2" "registry.bstein.dev/bstein/hermes-chat-router@sha256:6744cb7b87c6050f1b97c0675cd280b8295b3b5826ba1d6d92e37aee6fd0b8c4"
] ]
}, },
{ {
@ -1058,6 +1088,48 @@
"registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca" "registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca"
] ]
}, },
{
"kind": "Deployment",
"namespace": "hermes",
"name": "hermes-execution-mediator-0",
"labels": {
"app": "hermes-execution-mediator",
"pool-ordinal": "0"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{
"kind": "Deployment",
"namespace": "hermes",
"name": "hermes-execution-mediator-1",
"labels": {
"app": "hermes-execution-mediator",
"pool-ordinal": "1"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{
"kind": "Deployment",
"namespace": "hermes",
"name": "hermes-execution-mediator-2",
"labels": {
"app": "hermes-execution-mediator",
"pool-ordinal": "2"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{ {
"kind": "Deployment", "kind": "Deployment",
"namespace": "hermes", "namespace": "hermes",
@ -1177,8 +1249,36 @@
"serviceAccountName": "hermes-chat", "serviceAccountName": "hermes-chat",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8", "registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37",
"registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1" "registry.bstein.dev/bstein/hermes-webui@sha256:c276a9e17c9057237472f39640c9ebac9d4359d9f62a34df52a759eef43167bf"
]
},
{
"kind": "StatefulSet",
"namespace": "hermes",
"name": "hermes-execution-worker",
"labels": {
"app": "hermes-execution-worker",
"app.kubernetes.io/name": "hermes-execution-worker",
"app.kubernetes.io/part-of": "hermes"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{
"kind": "Deployment",
"namespace": "hermes-scm",
"name": "hermes-scm-broker",
"labels": {
"app": "hermes-scm-broker"
},
"serviceAccountName": "hermes-scm-broker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:37ebf720c783ae908a602916ffccf88d43d205a157957f5dc4b487867aee45e7"
] ]
}, },
{ {
@ -1528,7 +1628,7 @@
"kubernetes.io/os": "linux" "kubernetes.io/os": "linux"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-amd64" "registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-amd64"
] ]
}, },
{ {
@ -1544,7 +1644,7 @@
"kubernetes.io/os": "linux" "kubernetes.io/os": "linux"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-arm64" "registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-arm64"
] ]
}, },
{ {
@ -1633,7 +1733,7 @@
"node-role.kubernetes.io/worker": "true" "node-role.kubernetes.io/worker": "true"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/ariadne:0.1.0-454" "registry.bstein.dev/bstein/ariadne:0.1.0-464"
] ]
}, },
{ {
@ -1661,7 +1761,7 @@
"serviceAccountName": "metis", "serviceAccountName": "metis",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/metis:0.1.0-293-arm64" "registry.bstein.dev/bstein/metis:0.1.0-304-arm64"
] ]
}, },
{ {
@ -3179,6 +3279,22 @@
} }
] ]
}, },
{
"namespace": "hermes",
"name": "hermes-cli-lane-metrics",
"type": "ClusterIP",
"selector": {
"app": "hermes-agent"
},
"ports": [
{
"name": "lane-metrics",
"port": 9011,
"targetPort": "lane-metrics",
"protocol": "TCP"
}
]
},
{ {
"namespace": "hermes", "namespace": "hermes",
"name": "hermes-codex-broker", "name": "hermes-codex-broker",
@ -3195,6 +3311,82 @@
} }
] ]
}, },
{
"namespace": "hermes",
"name": "hermes-execution-mediator-0",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-mediator",
"pool-ordinal": "0"
},
"ports": [
{
"name": "mediator",
"port": 9009,
"targetPort": "mediator",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-mediator-1",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-mediator",
"pool-ordinal": "1"
},
"ports": [
{
"name": "mediator",
"port": 9009,
"targetPort": "mediator",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-mediator-2",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-mediator",
"pool-ordinal": "2"
},
"ports": [
{
"name": "mediator",
"port": 9009,
"targetPort": "mediator",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-pool",
"type": "ClusterIP",
"selector": {
"app": "hermes-agent"
},
"ports": [
{
"name": "http",
"port": 9007,
"targetPort": "execution-pool",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-worker",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-worker"
},
"ports": []
},
{ {
"namespace": "hermes", "namespace": "hermes",
"name": "hermes-gpu-handoff", "name": "hermes-gpu-handoff",
@ -3393,6 +3585,22 @@
} }
] ]
}, },
{
"namespace": "hermes-scm",
"name": "hermes-scm-broker",
"type": "ClusterIP",
"selector": {
"app": "hermes-scm-broker"
},
"ports": [
{
"name": "http",
"port": 9081,
"targetPort": "http",
"protocol": "TCP"
}
]
},
{ {
"namespace": "jellyfin", "namespace": "jellyfin",
"name": "jellyfin", "name": "jellyfin",
@ -4423,6 +4631,26 @@
"source": "hermes" "source": "hermes"
} }
}, },
{
"host": "chat.hermes.bstein.dev",
"path": "/",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-chat",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "oauth2-proxy-hermes-chat"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-sites",
"source": "hermes"
}
},
{ {
"host": "ci.bstein.dev", "host": "ci.bstein.dev",
"path": "/", "path": "/",
@ -5183,6 +5411,26 @@
"source": "hermes" "source": "hermes"
} }
}, },
{
"host": "triage.hermes.bstein.dev",
"path": "/",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-triage",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "oauth2-proxy-hermes-triage"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-sites",
"source": "hermes"
}
},
{ {
"host": "vault.bstein.dev", "host": "vault.bstein.dev",
"path": "/", "path": "/",
@ -5302,6 +5550,46 @@
"name": "wolf", "name": "wolf",
"source": "game-stream" "source": "game-stream"
} }
},
{
"host": "worker.bstein.dev",
"path": "/",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-agent",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "hermes-agent"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-agent-dashboard",
"source": "hermes"
}
},
{
"host": "worker.bstein.dev",
"path": "/terminal",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-agent",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "hermes-agent"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-agent-terminal",
"source": "hermes"
}
} }
], ],
"helmrelease_host_hints": { "helmrelease_host_hints": {

View File

@ -65,6 +65,21 @@ sources:
- name: hermes-chat - name: hermes-chat
path: services/hermes-chat path: services/hermes-chat
targetNamespace: hermes-chat targetNamespace: hermes-chat
- name: hermes-observer-bindings
path: services/hermes-observer-bindings
targetNamespace: null
- name: hermes-observer-rbac
path: services/hermes-observer-rbac
targetNamespace: null
- name: hermes-scm-broker
path: services/hermes-scm-broker
targetNamespace: hermes-scm
- name: hermes-scm-broker-code
path: services/hermes/scm-common
targetNamespace: hermes-scm
- name: hermes-scm-namespace
path: services/hermes-scm-namespace
targetNamespace: null
- name: hermes-triage-demo - name: hermes-triage-demo
path: services/hermes-triage-demo path: services/hermes-triage-demo
targetNamespace: null targetNamespace: null
@ -152,6 +167,9 @@ sources:
- name: vault-csi - name: vault-csi
path: infrastructure/vault-csi path: infrastructure/vault-csi
targetNamespace: kube-system targetNamespace: kube-system
- name: vault-hermes-jenkins-token-seed
path: services/vault-hermes-jenkins-token-seed
targetNamespace: vault
- name: vault-injector - name: vault-injector
path: infrastructure/vault-injector path: infrastructure/vault-injector
targetNamespace: vault targetNamespace: vault
@ -187,7 +205,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: 'true' node-role.kubernetes.io/worker: 'true'
images: images:
- registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-464 - registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-479
- kind: Deployment - kind: Deployment
namespace: bstein-dev-home namespace: bstein-dev-home
name: bstein-dev-home-frontend name: bstein-dev-home-frontend
@ -198,7 +216,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: 'true' node-role.kubernetes.io/worker: 'true'
images: images:
- registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-464 - registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-479
- kind: Deployment - kind: Deployment
namespace: bstein-dev-home namespace: bstein-dev-home
name: bstein-dev-home-vault-sync name: bstein-dev-home-vault-sync
@ -604,7 +622,7 @@ workloads:
serviceAccountName: hermes-node-ssh-access serviceAccountName: hermes-node-ssh-access
nodeSelector: {} nodeSelector: {}
images: images:
- busybox:1.37 - python@sha256:6d43704baacd1bfbe7c295d7f13079d5d8104ed33568873133f8fc69980419df
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes name: hermes
@ -613,8 +631,8 @@ workloads:
serviceAccountName: hermes-triage serviceAccountName: hermes-triage
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8 - registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1 - registry.bstein.dev/bstein/hermes-webui@sha256:ac6ba7bfd8a86227f31a9a96ebea41227ccf70391f7dcf34206f4d58e835e50e
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-agent name: hermes-agent
@ -624,7 +642,7 @@ workloads:
nodeSelector: {} nodeSelector: {}
images: images:
- quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561 - quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561
- registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8 - registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-chat-router name: hermes-chat-router
@ -633,7 +651,7 @@ workloads:
serviceAccountName: hermes-chat serviceAccountName: hermes-chat
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-chat-router@sha256:a4010fdc5b6dce2696e6fec06eb38a3992817faa01ff3472122c870038b22bd2 - registry.bstein.dev/bstein/hermes-chat-router@sha256:6744cb7b87c6050f1b97c0675cd280b8295b3b5826ba1d6d92e37aee6fd0b8c4
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-chat-sandbox-0 name: hermes-chat-sandbox-0
@ -714,6 +732,36 @@ workloads:
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca - registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca
- kind: Deployment
namespace: hermes
name: hermes-execution-mediator-0
labels:
app: hermes-execution-mediator
pool-ordinal: '0'
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment
namespace: hermes
name: hermes-execution-mediator-1
labels:
app: hermes-execution-mediator
pool-ordinal: '1'
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment
namespace: hermes
name: hermes-execution-mediator-2
labels:
app: hermes-execution-mediator
pool-ordinal: '2'
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-local-image name: hermes-local-image
@ -797,8 +845,28 @@ workloads:
serviceAccountName: hermes-chat serviceAccountName: hermes-chat
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8 - registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1 - registry.bstein.dev/bstein/hermes-webui@sha256:c276a9e17c9057237472f39640c9ebac9d4359d9f62a34df52a759eef43167bf
- kind: StatefulSet
namespace: hermes
name: hermes-execution-worker
labels:
app: hermes-execution-worker
app.kubernetes.io/name: hermes-execution-worker
app.kubernetes.io/part-of: hermes
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment
namespace: hermes-scm
name: hermes-scm-broker
labels:
app: hermes-scm-broker
serviceAccountName: hermes-scm-broker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:37ebf720c783ae908a602916ffccf88d43d205a157957f5dc4b487867aee45e7
- kind: Deployment - kind: Deployment
namespace: jellyfin namespace: jellyfin
name: jellyfin name: jellyfin
@ -1037,7 +1105,7 @@ workloads:
kubernetes.io/arch: amd64 kubernetes.io/arch: amd64
kubernetes.io/os: linux kubernetes.io/os: linux
images: images:
- registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-amd64 - registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-amd64
- kind: DaemonSet - kind: DaemonSet
namespace: maintenance namespace: maintenance
name: metis-sentinel-arm64 name: metis-sentinel-arm64
@ -1048,7 +1116,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
kubernetes.io/os: linux kubernetes.io/os: linux
images: images:
- registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-arm64 - registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-arm64
- kind: DaemonSet - kind: DaemonSet
namespace: maintenance namespace: maintenance
name: node-image-sweeper name: node-image-sweeper
@ -1108,7 +1176,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: 'true' node-role.kubernetes.io/worker: 'true'
images: images:
- registry.bstein.dev/bstein/ariadne:0.1.0-454 - registry.bstein.dev/bstein/ariadne:0.1.0-464
- kind: Deployment - kind: Deployment
namespace: maintenance namespace: maintenance
name: maintenance-vault-sync name: maintenance-vault-sync
@ -1127,7 +1195,7 @@ workloads:
serviceAccountName: metis serviceAccountName: metis
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/metis:0.1.0-293-arm64 - registry.bstein.dev/bstein/metis:0.1.0-304-arm64
- kind: Deployment - kind: Deployment
namespace: maintenance namespace: maintenance
name: oauth2-proxy-metis name: oauth2-proxy-metis
@ -2120,6 +2188,16 @@ services:
port: 9006 port: 9006
targetPort: claude-broker targetPort: claude-broker
protocol: TCP protocol: TCP
- namespace: hermes
name: hermes-cli-lane-metrics
type: ClusterIP
selector:
app: hermes-agent
ports:
- name: lane-metrics
port: 9011
targetPort: lane-metrics
protocol: TCP
- namespace: hermes - namespace: hermes
name: hermes-codex-broker name: hermes-codex-broker
type: ClusterIP type: ClusterIP
@ -2130,6 +2208,55 @@ services:
port: 9003 port: 9003
targetPort: codex-broker targetPort: codex-broker
protocol: TCP protocol: TCP
- namespace: hermes
name: hermes-execution-mediator-0
type: ClusterIP
selector:
app: hermes-execution-mediator
pool-ordinal: '0'
ports:
- name: mediator
port: 9009
targetPort: mediator
protocol: TCP
- namespace: hermes
name: hermes-execution-mediator-1
type: ClusterIP
selector:
app: hermes-execution-mediator
pool-ordinal: '1'
ports:
- name: mediator
port: 9009
targetPort: mediator
protocol: TCP
- namespace: hermes
name: hermes-execution-mediator-2
type: ClusterIP
selector:
app: hermes-execution-mediator
pool-ordinal: '2'
ports:
- name: mediator
port: 9009
targetPort: mediator
protocol: TCP
- namespace: hermes
name: hermes-execution-pool
type: ClusterIP
selector:
app: hermes-agent
ports:
- name: http
port: 9007
targetPort: execution-pool
protocol: TCP
- namespace: hermes
name: hermes-execution-worker
type: ClusterIP
selector:
app: hermes-execution-worker
ports: []
- namespace: hermes - namespace: hermes
name: hermes-gpu-handoff name: hermes-gpu-handoff
type: ClusterIP type: ClusterIP
@ -2254,6 +2381,16 @@ services:
port: 80 port: 80
targetPort: http targetPort: http
protocol: TCP protocol: TCP
- namespace: hermes-scm
name: hermes-scm-broker
type: ClusterIP
selector:
app: hermes-scm-broker
ports:
- name: http
port: 9081
targetPort: http
protocol: TCP
- namespace: jellyfin - namespace: jellyfin
name: jellyfin name: jellyfin
type: ClusterIP type: ClusterIP
@ -2894,13 +3031,24 @@ http_endpoints:
namespace: hermes namespace: hermes
service: oauth2-proxy-hermes-chat service: oauth2-proxy-hermes-chat
port: http port: http
workloads: workloads: &id004
- kind: Deployment - kind: Deployment
name: oauth2-proxy-hermes-chat name: oauth2-proxy-hermes-chat
via: via:
kind: Ingress kind: Ingress
name: hermes-sites name: hermes-sites
source: hermes source: hermes
- host: chat.hermes.bstein.dev
path: /
backend:
namespace: hermes
service: oauth2-proxy-hermes-chat
port: http
workloads: *id004
via:
kind: Ingress
name: hermes-sites
source: hermes
- host: ci.bstein.dev - host: ci.bstein.dev
path: / path: /
backend: backend:
@ -3005,7 +3153,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: &id005 workloads: &id006
- kind: Deployment - kind: Deployment
name: matrix-guest-register name: matrix-guest-register
via: via:
@ -3018,7 +3166,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: &id004 workloads: &id005
- kind: Deployment - kind: Deployment
name: matrix-authentication-service name: matrix-authentication-service
via: via:
@ -3031,7 +3179,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3042,7 +3190,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3053,7 +3201,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: *id005 workloads: *id006
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3101,7 +3249,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3145,7 +3293,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: *id005 workloads: *id006
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3156,7 +3304,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3167,7 +3315,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3178,7 +3326,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3189,7 +3337,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: *id005 workloads: *id006
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3367,13 +3515,24 @@ http_endpoints:
namespace: hermes namespace: hermes
service: oauth2-proxy-hermes-triage service: oauth2-proxy-hermes-triage
port: http port: http
workloads: workloads: &id007
- kind: Deployment - kind: Deployment
name: oauth2-proxy-hermes-triage name: oauth2-proxy-hermes-triage
via: via:
kind: Ingress kind: Ingress
name: hermes-sites name: hermes-sites
source: hermes source: hermes
- host: triage.hermes.bstein.dev
path: /
backend:
namespace: hermes
service: oauth2-proxy-hermes-triage
port: http
workloads: *id007
via:
kind: Ingress
name: hermes-sites
source: hermes
- host: vault.bstein.dev - host: vault.bstein.dev
path: / path: /
backend: backend:
@ -3406,7 +3565,7 @@ http_endpoints:
namespace: veles namespace: veles
service: veles-backend service: veles-backend
port: 80 port: 80
workloads: &id006 workloads: &id008
- kind: Deployment - kind: Deployment
name: veles-backend name: veles-backend
via: via:
@ -3419,7 +3578,7 @@ http_endpoints:
namespace: veles namespace: veles
service: veles-backend service: veles-backend
port: 80 port: 80
workloads: *id006 workloads: *id008
via: via:
kind: Ingress kind: Ingress
name: veles name: veles
@ -3430,7 +3589,7 @@ http_endpoints:
namespace: veles namespace: veles
service: veles-backend service: veles-backend
port: 80 port: 80
workloads: *id006 workloads: *id008
via: via:
kind: Ingress kind: Ingress
name: veles name: veles
@ -3448,6 +3607,28 @@ http_endpoints:
kind: Ingress kind: Ingress
name: wolf name: wolf
source: game-stream source: game-stream
- host: worker.bstein.dev
path: /
backend:
namespace: hermes
service: oauth2-proxy-hermes-agent
port: http
workloads: *id001
via:
kind: Ingress
name: hermes-agent-dashboard
source: hermes
- host: worker.bstein.dev
path: /terminal
backend:
namespace: hermes
service: oauth2-proxy-hermes-agent
port: http
workloads: *id001
via:
kind: Ingress
name: hermes-agent-terminal
source: hermes
helmrelease_host_hints: helmrelease_host_hints:
cert-manager:cert-manager/cert-manager: cert-manager:cert-manager/cert-manager:
- atlas.bstein.dev - atlas.bstein.dev

View File

@ -1,4 +1,440 @@
[ [
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Weekly Remaining",
"panel_id": 1,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"openai\",limit=\"codex\",window=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Spark Weekly Remaining",
"panel_id": 2,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"openai\",limit=\"gpt-5-3-codex-spark\",window=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 5h Remaining",
"panel_id": 3,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"anthropic\",window=\"five_hour\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 7d Remaining",
"panel_id": 4,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"anthropic\",window=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Quota Collectors Healthy",
"panel_id": 5,
"panel_type": "stat",
"description": "Successful latest quota fetches. Providers are polled independently every five minutes.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(atlas_ai_quota_fetch_success) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Oldest Quota Sample",
"panel_id": 6,
"panel_type": "stat",
"description": "Age of the stalest successful provider quota snapshot.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"max((time() - atlas_ai_quota_last_success_timestamp_seconds) and (atlas_ai_quota_last_success_timestamp_seconds > 0)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Weekly Reset In",
"panel_id": 7,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(clamp_min(atlas_ai_quota_reset_timestamp_seconds{provider=\"openai\",limit=\"codex\",window=\"seven_day\"} - time(), 0) and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 5h Reset In",
"panel_id": 8,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(clamp_min(atlas_ai_quota_reset_timestamp_seconds{provider=\"anthropic\",window=\"five_hour\"} - time(), 0) and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 7d Reset In",
"panel_id": 9,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(clamp_min(atlas_ai_quota_reset_timestamp_seconds{provider=\"anthropic\",window=\"seven_day\"} - time(), 0) and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Tokens (Latest Day)",
"panel_id": 10,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_account_tokens{provider=\"openai\",period=\"latest_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Tokens (7d)",
"panel_id": 11,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_account_tokens{provider=\"openai\",period=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Switchyard Requests",
"panel_id": 12,
"panel_type": "stat",
"description": "Hosted model requests observed by Switchyard in the selected dashboard range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(increase(switchyard_requests_total[$__range])) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Model Selection Rate",
"panel_id": 13,
"panel_type": "timeseries",
"description": "AUTO and fixed-route decisions by selected provider, model family, and reasoning effort.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum by (selected_model) (rate(switchyard_decisions_total[5m]))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Provider Selections (Range)",
"panel_id": 14,
"panel_type": "bargauge",
"description": "Switchyard selections grouped by provider over the selected dashboard range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sort_desc(sum by (provider) (label_replace(increase(switchyard_decisions_total{selected_model=~\"(route|worker)/(codex|claude|local)/.*\"}[$__range]), \"provider\", \"$2\", \"selected_model\", \"^(route|worker)/(codex|claude|local)/.*\")))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Token Throughput",
"panel_id": 15,
"panel_type": "timeseries",
"description": "Prompt, cache, reasoning, and completion token rates reported by hosted Switchyard calls.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(rate(switchyard_prompt_tokens_total[5m]))",
"sum(rate(switchyard_cached_tokens_total[5m]))",
"sum(rate(switchyard_cache_creation_tokens_total[5m]))",
"sum(rate(switchyard_reasoning_tokens_total[5m]))",
"sum(rate(switchyard_completion_tokens_total[5m]))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Model Call p95 Latency",
"panel_id": 16,
"panel_type": "timeseries",
"description": "95th percentile upstream latency for each selected model route.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"histogram_quantile(0.95, sum by (le, model) (rate(switchyard_model_call_latency_ms_bucket[5m])))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Prompt Cache Share",
"panel_id": 17,
"panel_type": "stat",
"description": "Cached tokens as a share of prompt plus cached tokens; higher generally means less repeated provider work.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"100 * sum(rate(switchyard_cached_tokens_total[5m])) / clamp_min(sum(rate(switchyard_prompt_tokens_total[5m])) + sum(rate(switchyard_cached_tokens_total[5m])), 1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Client Success Rate",
"panel_id": 18,
"panel_type": "stat",
"description": "Successful client-facing Switchyard responses in the selected range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"100 * sum(increase(switchyard_client_responses_total{outcome=\"success\"}[$__range])) / clamp_min(sum(increase(switchyard_client_responses_total[$__range])), 1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Classifier Fail-Open (Range)",
"panel_id": 19,
"panel_type": "stat",
"description": "Local classifier failures that safely fell back to the conservative hosted route.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(increase(switchyard_classifier_fail_open_total[$__range])) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Upstream Errors (Range)",
"panel_id": 20,
"panel_type": "stat",
"description": "Hosted model attempts that returned errors in the selected range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(increase(switchyard_errors_total[$__range])) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Local Classifier Calls",
"panel_id": 21,
"panel_type": "timeseries",
"description": "Local Qwen routing-classifier activity, split by successful and failed calls.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum by (outcome) (rate(switchyard_llm_calls_total{selected_model=~\"qwen.*\"}[5m]))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Routing Overhead p95",
"panel_id": 22,
"panel_type": "timeseries",
"description": "95th percentile time Switchyard spends selecting a model before the upstream call.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"histogram_quantile(0.95, sum by (le, algorithm) (rate(switchyard_routing_overhead_ms_bucket[5m])))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Traffic Lanes (Range)",
"panel_id": 23,
"panel_type": "bargauge",
"description": "Request volume split between interactive route traffic and durable worker traffic.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sort_desc(sum by (lane) (label_replace(increase(switchyard_requests_total{model=~\"(route|worker)/.*\"}[$__range]), \"lane\", \"$1\", \"model\", \"^(route|worker)/.*\")))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Hermes Workload CPU (Attribution Proxy)",
"panel_id": 25,
"panel_type": "timeseries",
"description": "Compute use by Hermes pod/container. Switchyard currently exposes model and worker-vs-route attribution, but not tenant-slot token labels; CPU is clearly marked as a proxy rather than token usage.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum by (pod, container) (rate(container_cpu_usage_seconds_total{namespace=\"hermes\",pod=~\"hermes-(agent|chat-tenant|switchyard|model-gate).*\",container!=\"\",image!=\"\"}[5m]))"
]
},
{ {
"dashboard": "Atlas GitOps", "dashboard": "Atlas GitOps",
"panel_title": "Flux Source", "panel_title": "Flux Source",

File diff suppressed because one or more lines are too long

View File

@ -56,6 +56,8 @@ flowchart LR
host_chat_bstein_dev --> svc_hermes_oauth2_proxy_hermes_chat host_chat_bstein_dev --> svc_hermes_oauth2_proxy_hermes_chat
wl_hermes_oauth2_proxy_hermes_chat["hermes/oauth2-proxy-hermes-chat (Deployment)"] wl_hermes_oauth2_proxy_hermes_chat["hermes/oauth2-proxy-hermes-chat (Deployment)"]
svc_hermes_oauth2_proxy_hermes_chat --> wl_hermes_oauth2_proxy_hermes_chat svc_hermes_oauth2_proxy_hermes_chat --> wl_hermes_oauth2_proxy_hermes_chat
host_chat_hermes_bstein_dev["chat.hermes.bstein.dev"]
host_chat_hermes_bstein_dev --> svc_hermes_oauth2_proxy_hermes_chat
host_ci_bstein_dev["ci.bstein.dev"] host_ci_bstein_dev["ci.bstein.dev"]
svc_jenkins_jenkins["jenkins/jenkins (Service)"] svc_jenkins_jenkins["jenkins/jenkins (Service)"]
host_ci_bstein_dev --> svc_jenkins_jenkins host_ci_bstein_dev --> svc_jenkins_jenkins
@ -175,6 +177,8 @@ flowchart LR
host_triage_bstein_dev --> svc_hermes_oauth2_proxy_hermes_triage host_triage_bstein_dev --> svc_hermes_oauth2_proxy_hermes_triage
wl_hermes_oauth2_proxy_hermes_triage["hermes/oauth2-proxy-hermes-triage (Deployment)"] wl_hermes_oauth2_proxy_hermes_triage["hermes/oauth2-proxy-hermes-triage (Deployment)"]
svc_hermes_oauth2_proxy_hermes_triage --> wl_hermes_oauth2_proxy_hermes_triage svc_hermes_oauth2_proxy_hermes_triage --> wl_hermes_oauth2_proxy_hermes_triage
host_triage_hermes_bstein_dev["triage.hermes.bstein.dev"]
host_triage_hermes_bstein_dev --> svc_hermes_oauth2_proxy_hermes_triage
host_vault_bstein_dev["vault.bstein.dev"] host_vault_bstein_dev["vault.bstein.dev"]
svc_vaultwarden_vaultwarden_service["vaultwarden/vaultwarden-service (Service)"] svc_vaultwarden_vaultwarden_service["vaultwarden/vaultwarden-service (Service)"]
host_vault_bstein_dev --> svc_vaultwarden_vaultwarden_service host_vault_bstein_dev --> svc_vaultwarden_vaultwarden_service
@ -194,6 +198,8 @@ flowchart LR
host_wolf_bstein_dev --> svc_game_stream_oauth2_proxy_wolf host_wolf_bstein_dev --> svc_game_stream_oauth2_proxy_wolf
wl_game_stream_oauth2_proxy_wolf["game-stream/oauth2-proxy-wolf (Deployment)"] wl_game_stream_oauth2_proxy_wolf["game-stream/oauth2-proxy-wolf (Deployment)"]
svc_game_stream_oauth2_proxy_wolf --> wl_game_stream_oauth2_proxy_wolf svc_game_stream_oauth2_proxy_wolf --> wl_game_stream_oauth2_proxy_wolf
host_worker_bstein_dev["worker.bstein.dev"]
host_worker_bstein_dev --> svc_hermes_oauth2_proxy_hermes_agent
subgraph bstein_dev_home[bstein-dev-home] subgraph bstein_dev_home[bstein-dev-home]
svc_bstein_dev_home_bstein_dev_home_frontend svc_bstein_dev_home_bstein_dev_home_frontend

View File

@ -99,7 +99,7 @@ in-process call removed a whole pod launch from the critical path.
`hermes-demo-test-<N>` (failed) and `hermes-demo-repair-<N>` (succeeded); `hermes-demo-test-<N>` (failed) and `hermes-demo-repair-<N>` (succeeded);
both TTL-clean after 1 h. both TTL-clean after 1 h.
- Hermes side: the run appears in the dashboard at - Hermes side: the run appears in the dashboard at
`https://agent.hermes.bstein.dev` (session/run history). `https://worker.bstein.dev` (session/run history).
- Escalation path: alert `HermesTriageHumanRequired` in vmalert - Escalation path: alert `HermesTriageHumanRequired` in vmalert
(`vmalert-atlas-availability` deployment, 1 m interval, `for: 2m`) (`vmalert-atlas-availability` deployment, 1 m interval, `for: 2m`)
fires to Alertmanager for any `human_required` incident. Gauges are fires to Alertmanager for any `human_required` incident. Gauges are

View File

@ -40,7 +40,7 @@ JENKINS = os.environ.get("JENKINS_URL", "https://ci.bstein.dev")
GITEA = os.environ.get("GITEA_URL", "https://scm.bstein.dev") GITEA = os.environ.get("GITEA_URL", "https://scm.bstein.dev")
CODE_REPO_OWNER = os.environ.get("CODE_REPO_OWNER", "atlas") CODE_REPO_OWNER = os.environ.get("CODE_REPO_OWNER", "atlas")
GRAFANA = os.environ.get("GRAFANA_URL", "https://metrics.bstein.dev") GRAFANA = os.environ.get("GRAFANA_URL", "https://metrics.bstein.dev")
HERMES_UI = os.environ.get("HERMES_URL", "https://agent.hermes.bstein.dev") HERMES_UI = os.environ.get("HERMES_URL", "https://worker.bstein.dev")
POLL_SECONDS = 6 POLL_SECONDS = 6
# `--filter <text>` restricts the monitor to incidents whose id contains that # `--filter <text>` restricts the monitor to incidents whose id contains that

View File

@ -1,8 +1,8 @@
{ {
"counts": { "counts": {
"helmrelease_host_hints": 23, "helmrelease_host_hints": 23,
"http_endpoints": 61, "http_endpoints": 65,
"services": 91, "services": 98,
"workloads": 125 "workloads": 130
} }
} }

View File

@ -106,6 +106,31 @@
"path": "services/hermes-chat", "path": "services/hermes-chat",
"targetNamespace": "hermes-chat" "targetNamespace": "hermes-chat"
}, },
{
"name": "hermes-observer-bindings",
"path": "services/hermes-observer-bindings",
"targetNamespace": null
},
{
"name": "hermes-observer-rbac",
"path": "services/hermes-observer-rbac",
"targetNamespace": null
},
{
"name": "hermes-scm-broker",
"path": "services/hermes-scm-broker",
"targetNamespace": "hermes-scm"
},
{
"name": "hermes-scm-broker-code",
"path": "services/hermes/scm-common",
"targetNamespace": "hermes-scm"
},
{
"name": "hermes-scm-namespace",
"path": "services/hermes-scm-namespace",
"targetNamespace": null
},
{ {
"name": "hermes-triage-demo", "name": "hermes-triage-demo",
"path": "services/hermes-triage-demo", "path": "services/hermes-triage-demo",
@ -251,6 +276,11 @@
"path": "infrastructure/vault-csi", "path": "infrastructure/vault-csi",
"targetNamespace": "kube-system" "targetNamespace": "kube-system"
}, },
{
"name": "vault-hermes-jenkins-token-seed",
"path": "services/vault-hermes-jenkins-token-seed",
"targetNamespace": "vault"
},
{ {
"name": "vault-injector", "name": "vault-injector",
"path": "infrastructure/vault-injector", "path": "infrastructure/vault-injector",
@ -304,7 +334,7 @@
"node-role.kubernetes.io/worker": "true" "node-role.kubernetes.io/worker": "true"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-464" "registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-479"
] ]
}, },
{ {
@ -320,7 +350,7 @@
"node-role.kubernetes.io/worker": "true" "node-role.kubernetes.io/worker": "true"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-464" "registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-479"
] ]
}, },
{ {
@ -902,7 +932,7 @@
"serviceAccountName": "hermes-node-ssh-access", "serviceAccountName": "hermes-node-ssh-access",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"busybox:1.37" "python@sha256:6d43704baacd1bfbe7c295d7f13079d5d8104ed33568873133f8fc69980419df"
] ]
}, },
{ {
@ -915,8 +945,8 @@
"serviceAccountName": "hermes-triage", "serviceAccountName": "hermes-triage",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8", "registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37",
"registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1" "registry.bstein.dev/bstein/hermes-webui@sha256:ac6ba7bfd8a86227f31a9a96ebea41227ccf70391f7dcf34206f4d58e835e50e"
] ]
}, },
{ {
@ -930,7 +960,7 @@
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561", "quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561",
"registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8" "registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
] ]
}, },
{ {
@ -943,7 +973,7 @@
"serviceAccountName": "hermes-chat", "serviceAccountName": "hermes-chat",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/hermes-chat-router@sha256:a4010fdc5b6dce2696e6fec06eb38a3992817faa01ff3472122c870038b22bd2" "registry.bstein.dev/bstein/hermes-chat-router@sha256:6744cb7b87c6050f1b97c0675cd280b8295b3b5826ba1d6d92e37aee6fd0b8c4"
] ]
}, },
{ {
@ -1058,6 +1088,48 @@
"registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca" "registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca"
] ]
}, },
{
"kind": "Deployment",
"namespace": "hermes",
"name": "hermes-execution-mediator-0",
"labels": {
"app": "hermes-execution-mediator",
"pool-ordinal": "0"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{
"kind": "Deployment",
"namespace": "hermes",
"name": "hermes-execution-mediator-1",
"labels": {
"app": "hermes-execution-mediator",
"pool-ordinal": "1"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{
"kind": "Deployment",
"namespace": "hermes",
"name": "hermes-execution-mediator-2",
"labels": {
"app": "hermes-execution-mediator",
"pool-ordinal": "2"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{ {
"kind": "Deployment", "kind": "Deployment",
"namespace": "hermes", "namespace": "hermes",
@ -1177,8 +1249,36 @@
"serviceAccountName": "hermes-chat", "serviceAccountName": "hermes-chat",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8", "registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37",
"registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1" "registry.bstein.dev/bstein/hermes-webui@sha256:c276a9e17c9057237472f39640c9ebac9d4359d9f62a34df52a759eef43167bf"
]
},
{
"kind": "StatefulSet",
"namespace": "hermes",
"name": "hermes-execution-worker",
"labels": {
"app": "hermes-execution-worker",
"app.kubernetes.io/name": "hermes-execution-worker",
"app.kubernetes.io/part-of": "hermes"
},
"serviceAccountName": "hermes-execution-worker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37"
]
},
{
"kind": "Deployment",
"namespace": "hermes-scm",
"name": "hermes-scm-broker",
"labels": {
"app": "hermes-scm-broker"
},
"serviceAccountName": "hermes-scm-broker",
"nodeSelector": {},
"images": [
"registry.bstein.dev/bstein/hermes-agent@sha256:37ebf720c783ae908a602916ffccf88d43d205a157957f5dc4b487867aee45e7"
] ]
}, },
{ {
@ -1528,7 +1628,7 @@
"kubernetes.io/os": "linux" "kubernetes.io/os": "linux"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-amd64" "registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-amd64"
] ]
}, },
{ {
@ -1544,7 +1644,7 @@
"kubernetes.io/os": "linux" "kubernetes.io/os": "linux"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-arm64" "registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-arm64"
] ]
}, },
{ {
@ -1633,7 +1733,7 @@
"node-role.kubernetes.io/worker": "true" "node-role.kubernetes.io/worker": "true"
}, },
"images": [ "images": [
"registry.bstein.dev/bstein/ariadne:0.1.0-454" "registry.bstein.dev/bstein/ariadne:0.1.0-464"
] ]
}, },
{ {
@ -1661,7 +1761,7 @@
"serviceAccountName": "metis", "serviceAccountName": "metis",
"nodeSelector": {}, "nodeSelector": {},
"images": [ "images": [
"registry.bstein.dev/bstein/metis:0.1.0-293-arm64" "registry.bstein.dev/bstein/metis:0.1.0-304-arm64"
] ]
}, },
{ {
@ -3179,6 +3279,22 @@
} }
] ]
}, },
{
"namespace": "hermes",
"name": "hermes-cli-lane-metrics",
"type": "ClusterIP",
"selector": {
"app": "hermes-agent"
},
"ports": [
{
"name": "lane-metrics",
"port": 9011,
"targetPort": "lane-metrics",
"protocol": "TCP"
}
]
},
{ {
"namespace": "hermes", "namespace": "hermes",
"name": "hermes-codex-broker", "name": "hermes-codex-broker",
@ -3195,6 +3311,82 @@
} }
] ]
}, },
{
"namespace": "hermes",
"name": "hermes-execution-mediator-0",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-mediator",
"pool-ordinal": "0"
},
"ports": [
{
"name": "mediator",
"port": 9009,
"targetPort": "mediator",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-mediator-1",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-mediator",
"pool-ordinal": "1"
},
"ports": [
{
"name": "mediator",
"port": 9009,
"targetPort": "mediator",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-mediator-2",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-mediator",
"pool-ordinal": "2"
},
"ports": [
{
"name": "mediator",
"port": 9009,
"targetPort": "mediator",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-pool",
"type": "ClusterIP",
"selector": {
"app": "hermes-agent"
},
"ports": [
{
"name": "http",
"port": 9007,
"targetPort": "execution-pool",
"protocol": "TCP"
}
]
},
{
"namespace": "hermes",
"name": "hermes-execution-worker",
"type": "ClusterIP",
"selector": {
"app": "hermes-execution-worker"
},
"ports": []
},
{ {
"namespace": "hermes", "namespace": "hermes",
"name": "hermes-gpu-handoff", "name": "hermes-gpu-handoff",
@ -3393,6 +3585,22 @@
} }
] ]
}, },
{
"namespace": "hermes-scm",
"name": "hermes-scm-broker",
"type": "ClusterIP",
"selector": {
"app": "hermes-scm-broker"
},
"ports": [
{
"name": "http",
"port": 9081,
"targetPort": "http",
"protocol": "TCP"
}
]
},
{ {
"namespace": "jellyfin", "namespace": "jellyfin",
"name": "jellyfin", "name": "jellyfin",
@ -4423,6 +4631,26 @@
"source": "hermes" "source": "hermes"
} }
}, },
{
"host": "chat.hermes.bstein.dev",
"path": "/",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-chat",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "oauth2-proxy-hermes-chat"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-sites",
"source": "hermes"
}
},
{ {
"host": "ci.bstein.dev", "host": "ci.bstein.dev",
"path": "/", "path": "/",
@ -5183,6 +5411,26 @@
"source": "hermes" "source": "hermes"
} }
}, },
{
"host": "triage.hermes.bstein.dev",
"path": "/",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-triage",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "oauth2-proxy-hermes-triage"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-sites",
"source": "hermes"
}
},
{ {
"host": "vault.bstein.dev", "host": "vault.bstein.dev",
"path": "/", "path": "/",
@ -5302,6 +5550,46 @@
"name": "wolf", "name": "wolf",
"source": "game-stream" "source": "game-stream"
} }
},
{
"host": "worker.bstein.dev",
"path": "/",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-agent",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "hermes-agent"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-agent-dashboard",
"source": "hermes"
}
},
{
"host": "worker.bstein.dev",
"path": "/terminal",
"backend": {
"namespace": "hermes",
"service": "oauth2-proxy-hermes-agent",
"port": "http",
"workloads": [
{
"kind": "Deployment",
"name": "hermes-agent"
}
]
},
"via": {
"kind": "Ingress",
"name": "hermes-agent-terminal",
"source": "hermes"
}
} }
], ],
"helmrelease_host_hints": { "helmrelease_host_hints": {

View File

@ -65,6 +65,21 @@ sources:
- name: hermes-chat - name: hermes-chat
path: services/hermes-chat path: services/hermes-chat
targetNamespace: hermes-chat targetNamespace: hermes-chat
- name: hermes-observer-bindings
path: services/hermes-observer-bindings
targetNamespace: null
- name: hermes-observer-rbac
path: services/hermes-observer-rbac
targetNamespace: null
- name: hermes-scm-broker
path: services/hermes-scm-broker
targetNamespace: hermes-scm
- name: hermes-scm-broker-code
path: services/hermes/scm-common
targetNamespace: hermes-scm
- name: hermes-scm-namespace
path: services/hermes-scm-namespace
targetNamespace: null
- name: hermes-triage-demo - name: hermes-triage-demo
path: services/hermes-triage-demo path: services/hermes-triage-demo
targetNamespace: null targetNamespace: null
@ -152,6 +167,9 @@ sources:
- name: vault-csi - name: vault-csi
path: infrastructure/vault-csi path: infrastructure/vault-csi
targetNamespace: kube-system targetNamespace: kube-system
- name: vault-hermes-jenkins-token-seed
path: services/vault-hermes-jenkins-token-seed
targetNamespace: vault
- name: vault-injector - name: vault-injector
path: infrastructure/vault-injector path: infrastructure/vault-injector
targetNamespace: vault targetNamespace: vault
@ -187,7 +205,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: 'true' node-role.kubernetes.io/worker: 'true'
images: images:
- registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-464 - registry.bstein.dev/bstein/bstein-dev-home-backend:0.1.1-479
- kind: Deployment - kind: Deployment
namespace: bstein-dev-home namespace: bstein-dev-home
name: bstein-dev-home-frontend name: bstein-dev-home-frontend
@ -198,7 +216,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: 'true' node-role.kubernetes.io/worker: 'true'
images: images:
- registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-464 - registry.bstein.dev/bstein/bstein-dev-home-frontend:0.1.1-479
- kind: Deployment - kind: Deployment
namespace: bstein-dev-home namespace: bstein-dev-home
name: bstein-dev-home-vault-sync name: bstein-dev-home-vault-sync
@ -604,7 +622,7 @@ workloads:
serviceAccountName: hermes-node-ssh-access serviceAccountName: hermes-node-ssh-access
nodeSelector: {} nodeSelector: {}
images: images:
- busybox:1.37 - python@sha256:6d43704baacd1bfbe7c295d7f13079d5d8104ed33568873133f8fc69980419df
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes name: hermes
@ -613,8 +631,8 @@ workloads:
serviceAccountName: hermes-triage serviceAccountName: hermes-triage
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8 - registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1 - registry.bstein.dev/bstein/hermes-webui@sha256:ac6ba7bfd8a86227f31a9a96ebea41227ccf70391f7dcf34206f4d58e835e50e
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-agent name: hermes-agent
@ -624,7 +642,7 @@ workloads:
nodeSelector: {} nodeSelector: {}
images: images:
- quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561 - quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561
- registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8 - registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-chat-router name: hermes-chat-router
@ -633,7 +651,7 @@ workloads:
serviceAccountName: hermes-chat serviceAccountName: hermes-chat
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-chat-router@sha256:a4010fdc5b6dce2696e6fec06eb38a3992817faa01ff3472122c870038b22bd2 - registry.bstein.dev/bstein/hermes-chat-router@sha256:6744cb7b87c6050f1b97c0675cd280b8295b3b5826ba1d6d92e37aee6fd0b8c4
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-chat-sandbox-0 name: hermes-chat-sandbox-0
@ -714,6 +732,36 @@ workloads:
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca - registry.bstein.dev/bstein/hermes-chat-sandbox@sha256:17ee62b8e61c08573a3a8cca903b38ec43800cb44ec29340e1bc095176544bca
- kind: Deployment
namespace: hermes
name: hermes-execution-mediator-0
labels:
app: hermes-execution-mediator
pool-ordinal: '0'
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment
namespace: hermes
name: hermes-execution-mediator-1
labels:
app: hermes-execution-mediator
pool-ordinal: '1'
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment
namespace: hermes
name: hermes-execution-mediator-2
labels:
app: hermes-execution-mediator
pool-ordinal: '2'
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment - kind: Deployment
namespace: hermes namespace: hermes
name: hermes-local-image name: hermes-local-image
@ -797,8 +845,28 @@ workloads:
serviceAccountName: hermes-chat serviceAccountName: hermes-chat
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/hermes-agent@sha256:cce1f65dc7d30fdce4b1748cc7d3434b9761ae9946a8c8be6049204c503d60a8 - registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- registry.bstein.dev/bstein/hermes-webui@sha256:9c2fe8341c7b650e08d10acead3151b19e2af737863268bafb39b3d9517575b1 - registry.bstein.dev/bstein/hermes-webui@sha256:c276a9e17c9057237472f39640c9ebac9d4359d9f62a34df52a759eef43167bf
- kind: StatefulSet
namespace: hermes
name: hermes-execution-worker
labels:
app: hermes-execution-worker
app.kubernetes.io/name: hermes-execution-worker
app.kubernetes.io/part-of: hermes
serviceAccountName: hermes-execution-worker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:4a385fbd04ae1e3e8ca0237db98a318606a2a03786ef467757b8da5eee4e4b37
- kind: Deployment
namespace: hermes-scm
name: hermes-scm-broker
labels:
app: hermes-scm-broker
serviceAccountName: hermes-scm-broker
nodeSelector: {}
images:
- registry.bstein.dev/bstein/hermes-agent@sha256:37ebf720c783ae908a602916ffccf88d43d205a157957f5dc4b487867aee45e7
- kind: Deployment - kind: Deployment
namespace: jellyfin namespace: jellyfin
name: jellyfin name: jellyfin
@ -1037,7 +1105,7 @@ workloads:
kubernetes.io/arch: amd64 kubernetes.io/arch: amd64
kubernetes.io/os: linux kubernetes.io/os: linux
images: images:
- registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-amd64 - registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-amd64
- kind: DaemonSet - kind: DaemonSet
namespace: maintenance namespace: maintenance
name: metis-sentinel-arm64 name: metis-sentinel-arm64
@ -1048,7 +1116,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
kubernetes.io/os: linux kubernetes.io/os: linux
images: images:
- registry.bstein.dev/bstein/metis-sentinel:0.1.0-293-arm64 - registry.bstein.dev/bstein/metis-sentinel:0.1.0-304-arm64
- kind: DaemonSet - kind: DaemonSet
namespace: maintenance namespace: maintenance
name: node-image-sweeper name: node-image-sweeper
@ -1108,7 +1176,7 @@ workloads:
kubernetes.io/arch: arm64 kubernetes.io/arch: arm64
node-role.kubernetes.io/worker: 'true' node-role.kubernetes.io/worker: 'true'
images: images:
- registry.bstein.dev/bstein/ariadne:0.1.0-454 - registry.bstein.dev/bstein/ariadne:0.1.0-464
- kind: Deployment - kind: Deployment
namespace: maintenance namespace: maintenance
name: maintenance-vault-sync name: maintenance-vault-sync
@ -1127,7 +1195,7 @@ workloads:
serviceAccountName: metis serviceAccountName: metis
nodeSelector: {} nodeSelector: {}
images: images:
- registry.bstein.dev/bstein/metis:0.1.0-293-arm64 - registry.bstein.dev/bstein/metis:0.1.0-304-arm64
- kind: Deployment - kind: Deployment
namespace: maintenance namespace: maintenance
name: oauth2-proxy-metis name: oauth2-proxy-metis
@ -2120,6 +2188,16 @@ services:
port: 9006 port: 9006
targetPort: claude-broker targetPort: claude-broker
protocol: TCP protocol: TCP
- namespace: hermes
name: hermes-cli-lane-metrics
type: ClusterIP
selector:
app: hermes-agent
ports:
- name: lane-metrics
port: 9011
targetPort: lane-metrics
protocol: TCP
- namespace: hermes - namespace: hermes
name: hermes-codex-broker name: hermes-codex-broker
type: ClusterIP type: ClusterIP
@ -2130,6 +2208,55 @@ services:
port: 9003 port: 9003
targetPort: codex-broker targetPort: codex-broker
protocol: TCP protocol: TCP
- namespace: hermes
name: hermes-execution-mediator-0
type: ClusterIP
selector:
app: hermes-execution-mediator
pool-ordinal: '0'
ports:
- name: mediator
port: 9009
targetPort: mediator
protocol: TCP
- namespace: hermes
name: hermes-execution-mediator-1
type: ClusterIP
selector:
app: hermes-execution-mediator
pool-ordinal: '1'
ports:
- name: mediator
port: 9009
targetPort: mediator
protocol: TCP
- namespace: hermes
name: hermes-execution-mediator-2
type: ClusterIP
selector:
app: hermes-execution-mediator
pool-ordinal: '2'
ports:
- name: mediator
port: 9009
targetPort: mediator
protocol: TCP
- namespace: hermes
name: hermes-execution-pool
type: ClusterIP
selector:
app: hermes-agent
ports:
- name: http
port: 9007
targetPort: execution-pool
protocol: TCP
- namespace: hermes
name: hermes-execution-worker
type: ClusterIP
selector:
app: hermes-execution-worker
ports: []
- namespace: hermes - namespace: hermes
name: hermes-gpu-handoff name: hermes-gpu-handoff
type: ClusterIP type: ClusterIP
@ -2254,6 +2381,16 @@ services:
port: 80 port: 80
targetPort: http targetPort: http
protocol: TCP protocol: TCP
- namespace: hermes-scm
name: hermes-scm-broker
type: ClusterIP
selector:
app: hermes-scm-broker
ports:
- name: http
port: 9081
targetPort: http
protocol: TCP
- namespace: jellyfin - namespace: jellyfin
name: jellyfin name: jellyfin
type: ClusterIP type: ClusterIP
@ -2894,13 +3031,24 @@ http_endpoints:
namespace: hermes namespace: hermes
service: oauth2-proxy-hermes-chat service: oauth2-proxy-hermes-chat
port: http port: http
workloads: workloads: &id004
- kind: Deployment - kind: Deployment
name: oauth2-proxy-hermes-chat name: oauth2-proxy-hermes-chat
via: via:
kind: Ingress kind: Ingress
name: hermes-sites name: hermes-sites
source: hermes source: hermes
- host: chat.hermes.bstein.dev
path: /
backend:
namespace: hermes
service: oauth2-proxy-hermes-chat
port: http
workloads: *id004
via:
kind: Ingress
name: hermes-sites
source: hermes
- host: ci.bstein.dev - host: ci.bstein.dev
path: / path: /
backend: backend:
@ -3005,7 +3153,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: &id005 workloads: &id006
- kind: Deployment - kind: Deployment
name: matrix-guest-register name: matrix-guest-register
via: via:
@ -3018,7 +3166,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: &id004 workloads: &id005
- kind: Deployment - kind: Deployment
name: matrix-authentication-service name: matrix-authentication-service
via: via:
@ -3031,7 +3179,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3042,7 +3190,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3053,7 +3201,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: *id005 workloads: *id006
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3101,7 +3249,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3145,7 +3293,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: *id005 workloads: *id006
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3156,7 +3304,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3167,7 +3315,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3178,7 +3326,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-authentication-service service: matrix-authentication-service
port: 8080 port: 8080
workloads: *id004 workloads: *id005
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3189,7 +3337,7 @@ http_endpoints:
namespace: comms namespace: comms
service: matrix-guest-register service: matrix-guest-register
port: 8080 port: 8080
workloads: *id005 workloads: *id006
via: via:
kind: Ingress kind: Ingress
name: matrix-routing name: matrix-routing
@ -3367,13 +3515,24 @@ http_endpoints:
namespace: hermes namespace: hermes
service: oauth2-proxy-hermes-triage service: oauth2-proxy-hermes-triage
port: http port: http
workloads: workloads: &id007
- kind: Deployment - kind: Deployment
name: oauth2-proxy-hermes-triage name: oauth2-proxy-hermes-triage
via: via:
kind: Ingress kind: Ingress
name: hermes-sites name: hermes-sites
source: hermes source: hermes
- host: triage.hermes.bstein.dev
path: /
backend:
namespace: hermes
service: oauth2-proxy-hermes-triage
port: http
workloads: *id007
via:
kind: Ingress
name: hermes-sites
source: hermes
- host: vault.bstein.dev - host: vault.bstein.dev
path: / path: /
backend: backend:
@ -3406,7 +3565,7 @@ http_endpoints:
namespace: veles namespace: veles
service: veles-backend service: veles-backend
port: 80 port: 80
workloads: &id006 workloads: &id008
- kind: Deployment - kind: Deployment
name: veles-backend name: veles-backend
via: via:
@ -3419,7 +3578,7 @@ http_endpoints:
namespace: veles namespace: veles
service: veles-backend service: veles-backend
port: 80 port: 80
workloads: *id006 workloads: *id008
via: via:
kind: Ingress kind: Ingress
name: veles name: veles
@ -3430,7 +3589,7 @@ http_endpoints:
namespace: veles namespace: veles
service: veles-backend service: veles-backend
port: 80 port: 80
workloads: *id006 workloads: *id008
via: via:
kind: Ingress kind: Ingress
name: veles name: veles
@ -3448,6 +3607,28 @@ http_endpoints:
kind: Ingress kind: Ingress
name: wolf name: wolf
source: game-stream source: game-stream
- host: worker.bstein.dev
path: /
backend:
namespace: hermes
service: oauth2-proxy-hermes-agent
port: http
workloads: *id001
via:
kind: Ingress
name: hermes-agent-dashboard
source: hermes
- host: worker.bstein.dev
path: /terminal
backend:
namespace: hermes
service: oauth2-proxy-hermes-agent
port: http
workloads: *id001
via:
kind: Ingress
name: hermes-agent-terminal
source: hermes
helmrelease_host_hints: helmrelease_host_hints:
cert-manager:cert-manager/cert-manager: cert-manager:cert-manager/cert-manager:
- atlas.bstein.dev - atlas.bstein.dev

View File

@ -1,4 +1,440 @@
[ [
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Weekly Remaining",
"panel_id": 1,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"openai\",limit=\"codex\",window=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Spark Weekly Remaining",
"panel_id": 2,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"openai\",limit=\"gpt-5-3-codex-spark\",window=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 5h Remaining",
"panel_id": 3,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"anthropic\",window=\"five_hour\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 7d Remaining",
"panel_id": 4,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_quota_remaining_percent{provider=\"anthropic\",window=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Quota Collectors Healthy",
"panel_id": 5,
"panel_type": "stat",
"description": "Successful latest quota fetches. Providers are polled independently every five minutes.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(atlas_ai_quota_fetch_success) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Oldest Quota Sample",
"panel_id": 6,
"panel_type": "stat",
"description": "Age of the stalest successful provider quota snapshot.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"max((time() - atlas_ai_quota_last_success_timestamp_seconds) and (atlas_ai_quota_last_success_timestamp_seconds > 0)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Weekly Reset In",
"panel_id": 7,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(clamp_min(atlas_ai_quota_reset_timestamp_seconds{provider=\"openai\",limit=\"codex\",window=\"seven_day\"} - time(), 0) and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 5h Reset In",
"panel_id": 8,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(clamp_min(atlas_ai_quota_reset_timestamp_seconds{provider=\"anthropic\",window=\"five_hour\"} - time(), 0) and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Claude 7d Reset In",
"panel_id": 9,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(clamp_min(atlas_ai_quota_reset_timestamp_seconds{provider=\"anthropic\",window=\"seven_day\"} - time(), 0) and on(provider) (atlas_ai_quota_fetch_success{provider=\"anthropic\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Tokens (Latest Day)",
"panel_id": 10,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_account_tokens{provider=\"openai\",period=\"latest_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Codex Tokens (7d)",
"panel_id": 11,
"panel_type": "stat",
"description": "Live first-party CLI account telemetry. Unavailable means the provider did not return a fresh structured value.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"(atlas_ai_account_tokens{provider=\"openai\",period=\"seven_day\"} and on(provider) (atlas_ai_quota_fetch_success{provider=\"openai\"} == 1)) or on() vector(-1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Switchyard Requests",
"panel_id": 12,
"panel_type": "stat",
"description": "Hosted model requests observed by Switchyard in the selected dashboard range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(increase(switchyard_requests_total[$__range])) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Model Selection Rate",
"panel_id": 13,
"panel_type": "timeseries",
"description": "AUTO and fixed-route decisions by selected provider, model family, and reasoning effort.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum by (selected_model) (rate(switchyard_decisions_total[5m]))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Provider Selections (Range)",
"panel_id": 14,
"panel_type": "bargauge",
"description": "Switchyard selections grouped by provider over the selected dashboard range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sort_desc(sum by (provider) (label_replace(increase(switchyard_decisions_total{selected_model=~\"(route|worker)/(codex|claude|local)/.*\"}[$__range]), \"provider\", \"$2\", \"selected_model\", \"^(route|worker)/(codex|claude|local)/.*\")))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Token Throughput",
"panel_id": 15,
"panel_type": "timeseries",
"description": "Prompt, cache, reasoning, and completion token rates reported by hosted Switchyard calls.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(rate(switchyard_prompt_tokens_total[5m]))",
"sum(rate(switchyard_cached_tokens_total[5m]))",
"sum(rate(switchyard_cache_creation_tokens_total[5m]))",
"sum(rate(switchyard_reasoning_tokens_total[5m]))",
"sum(rate(switchyard_completion_tokens_total[5m]))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Model Call p95 Latency",
"panel_id": 16,
"panel_type": "timeseries",
"description": "95th percentile upstream latency for each selected model route.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"histogram_quantile(0.95, sum by (le, model) (rate(switchyard_model_call_latency_ms_bucket[5m])))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Prompt Cache Share",
"panel_id": 17,
"panel_type": "stat",
"description": "Cached tokens as a share of prompt plus cached tokens; higher generally means less repeated provider work.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"100 * sum(rate(switchyard_cached_tokens_total[5m])) / clamp_min(sum(rate(switchyard_prompt_tokens_total[5m])) + sum(rate(switchyard_cached_tokens_total[5m])), 1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Client Success Rate",
"panel_id": 18,
"panel_type": "stat",
"description": "Successful client-facing Switchyard responses in the selected range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"100 * sum(increase(switchyard_client_responses_total{outcome=\"success\"}[$__range])) / clamp_min(sum(increase(switchyard_client_responses_total[$__range])), 1)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Classifier Fail-Open (Range)",
"panel_id": 19,
"panel_type": "stat",
"description": "Local classifier failures that safely fell back to the conservative hosted route.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(increase(switchyard_classifier_fail_open_total[$__range])) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Upstream Errors (Range)",
"panel_id": 20,
"panel_type": "stat",
"description": "Hosted model attempts that returned errors in the selected range.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum(increase(switchyard_errors_total[$__range])) or on() vector(0)"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Local Classifier Calls",
"panel_id": 21,
"panel_type": "timeseries",
"description": "Local Qwen routing-classifier activity, split by successful and failed calls.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum by (outcome) (rate(switchyard_llm_calls_total{selected_model=~\"qwen.*\"}[5m]))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Routing Overhead p95",
"panel_id": 22,
"panel_type": "timeseries",
"description": "95th percentile time Switchyard spends selecting a model before the upstream call.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"histogram_quantile(0.95, sum by (le, algorithm) (rate(switchyard_routing_overhead_ms_bucket[5m])))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Traffic Lanes (Range)",
"panel_id": 23,
"panel_type": "bargauge",
"description": "Request volume split between interactive route traffic and durable worker traffic.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sort_desc(sum by (lane) (label_replace(increase(switchyard_requests_total{model=~\"(route|worker)/.*\"}[$__range]), \"lane\", \"$1\", \"model\", \"^(route|worker)/.*\")))"
]
},
{
"dashboard": "Atlas AI Operations",
"panel_title": "Hermes Workload CPU (Attribution Proxy)",
"panel_id": 25,
"panel_type": "timeseries",
"description": "Compute use by Hermes pod/container. Switchyard currently exposes model and worker-vs-route attribution, but not tenant-slot token labels; CPU is clearly marked as a proxy rather than token usage.",
"tags": [
"atlas",
"ai",
"hermes",
"switchyard"
],
"datasource_uid": "atlas-vm",
"datasource_type": "prometheus",
"exprs": [
"sum by (pod, container) (rate(container_cpu_usage_seconds_total{namespace=\"hermes\",pod=~\"hermes-(agent|chat-tenant|switchyard|model-gate).*\",container!=\"\",image!=\"\"}[5m]))"
]
},
{ {
"dashboard": "Atlas GitOps", "dashboard": "Atlas GitOps",
"panel_title": "Flux Source", "panel_title": "Flux Source",

File diff suppressed because one or more lines are too long

View File

@ -56,6 +56,8 @@ flowchart LR
host_chat_bstein_dev --> svc_hermes_oauth2_proxy_hermes_chat host_chat_bstein_dev --> svc_hermes_oauth2_proxy_hermes_chat
wl_hermes_oauth2_proxy_hermes_chat["hermes/oauth2-proxy-hermes-chat (Deployment)"] wl_hermes_oauth2_proxy_hermes_chat["hermes/oauth2-proxy-hermes-chat (Deployment)"]
svc_hermes_oauth2_proxy_hermes_chat --> wl_hermes_oauth2_proxy_hermes_chat svc_hermes_oauth2_proxy_hermes_chat --> wl_hermes_oauth2_proxy_hermes_chat
host_chat_hermes_bstein_dev["chat.hermes.bstein.dev"]
host_chat_hermes_bstein_dev --> svc_hermes_oauth2_proxy_hermes_chat
host_ci_bstein_dev["ci.bstein.dev"] host_ci_bstein_dev["ci.bstein.dev"]
svc_jenkins_jenkins["jenkins/jenkins (Service)"] svc_jenkins_jenkins["jenkins/jenkins (Service)"]
host_ci_bstein_dev --> svc_jenkins_jenkins host_ci_bstein_dev --> svc_jenkins_jenkins
@ -175,6 +177,8 @@ flowchart LR
host_triage_bstein_dev --> svc_hermes_oauth2_proxy_hermes_triage host_triage_bstein_dev --> svc_hermes_oauth2_proxy_hermes_triage
wl_hermes_oauth2_proxy_hermes_triage["hermes/oauth2-proxy-hermes-triage (Deployment)"] wl_hermes_oauth2_proxy_hermes_triage["hermes/oauth2-proxy-hermes-triage (Deployment)"]
svc_hermes_oauth2_proxy_hermes_triage --> wl_hermes_oauth2_proxy_hermes_triage svc_hermes_oauth2_proxy_hermes_triage --> wl_hermes_oauth2_proxy_hermes_triage
host_triage_hermes_bstein_dev["triage.hermes.bstein.dev"]
host_triage_hermes_bstein_dev --> svc_hermes_oauth2_proxy_hermes_triage
host_vault_bstein_dev["vault.bstein.dev"] host_vault_bstein_dev["vault.bstein.dev"]
svc_vaultwarden_vaultwarden_service["vaultwarden/vaultwarden-service (Service)"] svc_vaultwarden_vaultwarden_service["vaultwarden/vaultwarden-service (Service)"]
host_vault_bstein_dev --> svc_vaultwarden_vaultwarden_service host_vault_bstein_dev --> svc_vaultwarden_vaultwarden_service
@ -194,6 +198,8 @@ flowchart LR
host_wolf_bstein_dev --> svc_game_stream_oauth2_proxy_wolf host_wolf_bstein_dev --> svc_game_stream_oauth2_proxy_wolf
wl_game_stream_oauth2_proxy_wolf["game-stream/oauth2-proxy-wolf (Deployment)"] wl_game_stream_oauth2_proxy_wolf["game-stream/oauth2-proxy-wolf (Deployment)"]
svc_game_stream_oauth2_proxy_wolf --> wl_game_stream_oauth2_proxy_wolf svc_game_stream_oauth2_proxy_wolf --> wl_game_stream_oauth2_proxy_wolf
host_worker_bstein_dev["worker.bstein.dev"]
host_worker_bstein_dev --> svc_hermes_oauth2_proxy_hermes_agent
subgraph bstein_dev_home[bstein-dev-home] subgraph bstein_dev_home[bstein-dev-home]
svc_bstein_dev_home_bstein_dev_home_frontend svc_bstein_dev_home_bstein_dev_home_frontend

View File

@ -99,7 +99,7 @@ in-process call removed a whole pod launch from the critical path.
`hermes-demo-test-<N>` (failed) and `hermes-demo-repair-<N>` (succeeded); `hermes-demo-test-<N>` (failed) and `hermes-demo-repair-<N>` (succeeded);
both TTL-clean after 1 h. both TTL-clean after 1 h.
- Hermes side: the run appears in the dashboard at - Hermes side: the run appears in the dashboard at
`https://agent.hermes.bstein.dev` (session/run history). `https://worker.bstein.dev` (session/run history).
- Escalation path: alert `HermesTriageHumanRequired` in vmalert - Escalation path: alert `HermesTriageHumanRequired` in vmalert
(`vmalert-atlas-availability` deployment, 1 m interval, `for: 2m`) (`vmalert-atlas-availability` deployment, 1 m interval, `for: 2m`)
fires to Alertmanager for any `human_required` incident. Gauges are fires to Alertmanager for any `human_required` incident. Gauges are

View File

@ -5,7 +5,7 @@ This is the mental model and demonstration script for the operator instance at
consumer instance at `chat.bstein.dev` is intentionally separate and is not the consumer instance at `chat.bstein.dev` is intentionally separate and is not the
place to perform infrastructure triage. place to perform infrastructure triage.
`agent.hermes.bstein.dev` is the owner-only engineering control plane. Its root `worker.bstein.dev` is the owner-only engineering control plane. Its root
serves the stock Hermes dashboard, including embedded chat/TUI and the native serves the stock Hermes dashboard, including embedded chat/TUI and the native
sessions, files, models, logs, Kanban, skills, plugins, MCP, profiles, and sessions, files, models, logs, Kanban, skills, plugins, MCP, profiles, and
configuration surfaces. `/terminal/` remains the raw full-screen TUI. The configuration surfaces. `/terminal/` remains the raw full-screen TUI. The
@ -177,7 +177,7 @@ off. The final TypeScript build, Python compile, and source assertions remain
mandatory, so an omitted or drifted replay fails before any image can pass mandatory, so an omitted or drifted replay fails before any image can pass
release verification. release verification.
From agent.hermes, trigger that one fixed job with: From worker.bstein.dev, trigger that one fixed job with:
```sh ```sh
jenkins_image_build_trigger.py '<reviewed full main commit>' jenkins_image_build_trigger.py '<reviewed full main commit>'

View File

@ -17,3 +17,6 @@ spec:
# the rename in #34 must not break links or sessions already in flight. # the rename in #34 must not break links or sessions already in flight.
- chat.hermes.bstein.dev - chat.hermes.bstein.dev
- triage.hermes.bstein.dev - triage.hermes.bstein.dev
# worker.bstein.dev is the canonical owner-agent host; the legacy
# agent.hermes.bstein.dev SAN above stays until it is retired on purpose.
- worker.bstein.dev

View File

@ -142,7 +142,7 @@ data:
- "*git clean -f*" - "*git clean -f*"
dashboard: dashboard:
public_url: https://agent.hermes.bstein.dev public_url: https://worker.bstein.dev
display: display:
compact: true compact: true
@ -174,7 +174,7 @@ data:
backup_keep: 5 backup_keep: 5
non_interactive_local_changes: stash non_interactive_local_changes: stash
SOUL.md: | SOUL.md: |
You are Brad's private Hermes coordinator at agent.hermes.bstein.dev. Turn You are Brad's private Hermes coordinator at worker.bstein.dev. Turn
objectives into organized, reviewable delivery without making Brad manage objectives into organized, reviewable delivery without making Brad manage
model names, terminals, or provider capacity. model names, terminals, or provider capacity.
@ -408,7 +408,7 @@ data:
START-HERE.md: | START-HERE.md: |
# Agent Hermes # Agent Hermes
The authenticated root of agent.hermes.bstein.dev opens Hermes' stock The authenticated root of worker.bstein.dev opens Hermes' stock
dashboard with embedded chat/TUI, sessions, files, models, logs, Kanban, dashboard with embedded chat/TUI, sessions, files, models, logs, Kanban,
skills, plugins, MCP, profiles, and configuration. `/terminal/` opens the skills, plugins, MCP, profiles, and configuration. `/terminal/` opens the
raw full-screen Hermes TUI. Give Hermes raw full-screen Hermes TUI. Give Hermes

View File

@ -624,14 +624,15 @@ spec:
- {name: HERMES_DASHBOARD_HOST, value: 127.0.0.1} - {name: HERMES_DASHBOARD_HOST, value: 127.0.0.1}
- {name: HERMES_DASHBOARD_PORT, value: "9119"} - {name: HERMES_DASHBOARD_PORT, value: "9119"}
- {name: HERMES_DASHBOARD_FILES_ROOT, value: /opt/data/workspace} - {name: HERMES_DASHBOARD_FILES_ROOT, value: /opt/data/workspace}
- {name: HERMES_DASHBOARD_PUBLIC_URL, value: https://agent.hermes.bstein.dev} - {name: HERMES_DASHBOARD_PUBLIC_URL, value: https://worker.bstein.dev}
- {name: HERMES_TUI_AGENT_INIT_TIMEOUT_S, value: "180"} - {name: HERMES_TUI_AGENT_INIT_TIMEOUT_S, value: "180"}
- {name: HERMES_STREAM_STALE_TIMEOUT, value: "600"} - {name: HERMES_STREAM_STALE_TIMEOUT, value: "600"}
- {name: HERMES_API_CALL_STALE_TIMEOUT, value: "600"} - {name: HERMES_API_CALL_STALE_TIMEOUT, value: "600"}
- {name: API_SERVER_ENABLED, value: "true"} - {name: API_SERVER_ENABLED, value: "true"}
- {name: API_SERVER_HOST, value: 0.0.0.0} - {name: API_SERVER_HOST, value: 0.0.0.0}
- {name: API_SERVER_PORT, value: "8642"} - {name: API_SERVER_PORT, value: "8642"}
- {name: API_SERVER_CORS_ORIGINS, value: https://agent.hermes.bstein.dev} # Comma-separated; the legacy origin stays until agent.hermes.bstein.dev is retired.
- {name: API_SERVER_CORS_ORIGINS, value: "https://worker.bstein.dev,https://agent.hermes.bstein.dev"}
- {name: HERMES_MEDIA_DELIVERY_STRICT, value: "1"} - {name: HERMES_MEDIA_DELIVERY_STRICT, value: "1"}
- {name: HERMES_MEDIA_ALLOW_DIRS, value: /opt/data/workspace} - {name: HERMES_MEDIA_ALLOW_DIRS, value: /opt/data/workspace}
- {name: HERMES_AUTO_ROUTER_PROFILE, value: agent} - {name: HERMES_AUTO_ROUTER_PROFILE, value: agent}
@ -694,7 +695,11 @@ spec:
args: args:
- --provider=oidc - --provider=oidc
- --config=/vault/secrets/oidc-config - --config=/vault/secrets/oidc-config
- --redirect-url=https://agent.hermes.bstein.dev/oauth2/callback # Single canonical callback. The __Host- cookie prefix below binds both the
# session and the CSRF cookie to one host, so a fresh login must start on
# worker.bstein.dev; agent.hermes.bstein.dev keeps serving already
# authenticated sessions until it is retired separately.
- --redirect-url=https://worker.bstein.dev/oauth2/callback
- --oidc-issuer-url=https://sso.bstein.dev/realms/atlas - --oidc-issuer-url=https://sso.bstein.dev/realms/atlas
- --user-id-claim=sub - --user-id-claim=sub
- --oidc-groups-claim=groups - --oidc-groups-claim=groups

View File

@ -6,8 +6,10 @@ metadata:
namespace: hermes namespace: hermes
spec: spec:
redirectRegex: redirectRegex:
regex: ^https://agent\.hermes\.bstein\.dev/terminal$ # Host-preserving so the trailing-slash fixup works on both the canonical
replacement: https://agent.hermes.bstein.dev/terminal/ # worker.bstein.dev and the legacy agent.hermes.bstein.dev host.
regex: ^https://(worker\.bstein\.dev|agent\.hermes\.bstein\.dev)/terminal$
replacement: https://${1}/terminal/
permanent: false permanent: false
--- ---
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1
@ -33,9 +35,21 @@ spec:
ingressClassName: traefik ingressClassName: traefik
tls: tls:
- hosts: - hosts:
- worker.bstein.dev
- agent.hermes.bstein.dev - agent.hermes.bstein.dev
secretName: hermes-sites-tls secretName: hermes-sites-tls
rules: rules:
- host: worker.bstein.dev
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: oauth2-proxy-hermes-agent
port:
name: http
# Legacy host, served unchanged until it is retired in a separate change.
- host: agent.hermes.bstein.dev - host: agent.hermes.bstein.dev
http: http:
paths: paths:
@ -60,9 +74,21 @@ spec:
ingressClassName: traefik ingressClassName: traefik
tls: tls:
- hosts: - hosts:
- worker.bstein.dev
- agent.hermes.bstein.dev - agent.hermes.bstein.dev
secretName: hermes-sites-tls secretName: hermes-sites-tls
rules: rules:
- host: worker.bstein.dev
http:
paths:
- path: /terminal
pathType: Prefix
backend:
service:
name: oauth2-proxy-hermes-agent
port:
name: http
# Legacy host, served unchanged until it is retired in a separate change.
- host: agent.hermes.bstein.dev - host: agent.hermes.bstein.dev
http: http:
paths: paths:
@ -90,6 +116,7 @@ spec:
- agent.hermes.bstein.dev - agent.hermes.bstein.dev
- chat.bstein.dev - chat.bstein.dev
- triage.bstein.dev - triage.bstein.dev
- worker.bstein.dev
- chat.hermes.bstein.dev - chat.hermes.bstein.dev
- triage.hermes.bstein.dev - triage.hermes.bstein.dev
secretName: hermes-sites-tls secretName: hermes-sites-tls

View File

@ -113,7 +113,7 @@ data:
This is the dedicated triage appliance at triage.bstein.dev. Keep This is the dedicated triage appliance at triage.bstein.dev. Keep
automated Ariadne intake and testing conversations here. Project delivery automated Ariadne intake and testing conversations here. Project delivery
and coding orchestration belong to agent.hermes.bstein.dev; general user and coding orchestration belong to worker.bstein.dev; general user
chat belongs to chat.bstein.dev. chat belongs to chat.bstein.dev.
Start in AUTO routing with a careful, intelligence-biased posture. Every Start in AUTO routing with a careful, intelligence-biased posture. Every

View File

@ -8,7 +8,7 @@ asserting health, placement, ownership, or current model availability.
| Surface | Purpose | Identity boundary | State and permissions | | Surface | Purpose | Identity boundary | State and permissions |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `triage.bstein.dev` | Brad's automated testing triage | Keycloak plus an outer oauth2-proxy exact-email allow-list for `brad@bstein.dev` | `hermes` namespace, its own PVC and service account; read-only cluster triage plus approved internal evidence endpoints | | `triage.bstein.dev` | Brad's automated testing triage | Keycloak plus an outer oauth2-proxy exact-email allow-list for `brad@bstein.dev` | `hermes` namespace, its own PVC and service account; read-only cluster triage plus approved internal evidence endpoints |
| `agent.hermes.bstein.dev` | Brad's project coordinator | Keycloak plus an outer oauth2-proxy exact-email allow-list for `brad@bstein.dev` | `hermes` namespace and separate PVC; native Hermes delegates bounded work while Herdr preserves real Codex and Claude Code CLI sessions when needed | | `worker.bstein.dev` | Brad's project coordinator | Keycloak plus an outer oauth2-proxy exact-email allow-list for `brad@bstein.dev` | `hermes` namespace and separate PVC; native Hermes delegates bounded work while Herdr preserves real Codex and Claude Code CLI sessions when needed |
| `chat.bstein.dev` | Private consumer chat and research through Hermes WebUI or a linked Telegram DM | Keycloak login plus one-time Telegram account link | One Hermes process and PVC per assigned Keycloak subject; no Kubernetes RBAC, terminal, or private-service access | | `chat.bstein.dev` | Private consumer chat and research through Hermes WebUI or a linked Telegram DM | Keycloak login plus one-time Telegram account link | One Hermes process and PVC per assigned Keycloak subject; no Kubernetes RBAC, terminal, or private-service access |
The instances do not share conversation state, credentials, profiles, skills The instances do not share conversation state, credentials, profiles, skills

View File

@ -3,7 +3,7 @@
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
metadata: metadata:
name: hermes-access-oidc-client-ensure-11 name: hermes-access-oidc-client-ensure-12
namespace: sso namespace: sso
spec: spec:
backoffLimit: 3 backoffLimit: 3

View File

@ -343,7 +343,8 @@ ensure_telegram_config() {
ensure_hermes_owner ensure_hermes_owner
ensure_proxy_client "hermes-chat-proxy" "https://chat.bstein.dev" "hermes/chat-oidc" \ ensure_proxy_client "hermes-chat-proxy" "https://chat.bstein.dev" "hermes/chat-oidc" \
"https://chat.hermes.bstein.dev" "https://chat.hermes.bstein.dev"
ensure_proxy_client "hermes-agent-proxy" "https://agent.hermes.bstein.dev" "hermes/agent-oidc" ensure_proxy_client "hermes-agent-proxy" "https://worker.bstein.dev" "hermes/agent-oidc" \
"https://agent.hermes.bstein.dev"
ensure_proxy_client "hermes-triage-proxy" "https://triage.bstein.dev" "hermes/triage-oidc" \ ensure_proxy_client "hermes-triage-proxy" "https://triage.bstein.dev" "hermes/triage-oidc" \
"https://triage.hermes.bstein.dev" "https://triage.hermes.bstein.dev"
ensure_service_account_client "hermes-automation" "hermes/developer-keycloak" ensure_service_account_client "hermes-automation" "hermes/developer-keycloak"

View File

@ -26,7 +26,7 @@ data:
https://budget.bstein.dev https://budget.bstein.dev
https://money.bstein.dev https://money.bstein.dev
https://health.bstein.dev https://health.bstein.dev
https://agent.hermes.bstein.dev https://worker.bstein.dev
https://chat.bstein.dev https://chat.bstein.dev
https://triage.bstein.dev https://triage.bstein.dev
https://cassandra.bstein.dev https://cassandra.bstein.dev

View File

@ -63,7 +63,7 @@ def test_owner_agent_installs_the_pinned_operator_toolchain():
assert 'chmod 0644 "${profile_file}"' in init_command assert 'chmod 0644 "${profile_file}"' in init_command
def test_owner_agent_uses_only_the_canonical_hostname(): def test_owner_agent_uses_the_canonical_hostname():
paths = [ paths = [
HERMES / "agent-configmap.yaml", HERMES / "agent-configmap.yaml",
HERMES / "agent-deployment.yaml", HERMES / "agent-deployment.yaml",
@ -73,7 +73,40 @@ def test_owner_agent_uses_only_the_canonical_hostname():
for path in paths: for path in paths:
content = path.read_text() content = path.read_text()
assert "agent.bstein.dev" not in content assert "agent.bstein.dev" not in content
assert "agent.hermes.bstein.dev" in content assert "worker.bstein.dev" in content
def test_legacy_owner_host_stays_served_until_it_is_retired_separately():
"""The rename must not cut off the host the operator reaches Hermes on.
``agent.hermes.bstein.dev`` keeps resolving, routing and validating TLS
until it is retired in its own change, so rolling the rename back never
needs more than reverting the oauth2-proxy callback.
"""
legacy = "agent.hermes.bstein.dev"
canonical = "worker.bstein.dev"
coredns = (
Path(__file__).parents[2] / "infrastructure/core/coredns-custom.yaml"
).read_text()
assert f"192.168.22.9 {legacy}" in coredns
assert f"192.168.22.9 {canonical}" in coredns
certificate = yaml.safe_load((HERMES / "agent-certificate.yaml").read_text())
assert {legacy, canonical} <= set(certificate["spec"]["dnsNames"])
ingresses = [
doc
for doc in yaml.safe_load_all((HERMES / "agent-ingress.yaml").read_text())
if doc
and doc.get("kind") == "Ingress"
and doc["metadata"]["name"].startswith("hermes-agent-")
]
assert len(ingresses) == 2
for ingress in ingresses:
assert {legacy, canonical} <= {rule["host"] for rule in ingress["spec"]["rules"]}
for tls in ingress["spec"]["tls"]:
assert {legacy, canonical} <= set(tls["hosts"])
def test_agent_reconnect_retains_complete_history_and_long_tool_budget(): def test_agent_reconnect_retains_complete_history_and_long_tool_budget():

View File

@ -122,7 +122,7 @@ def test_owner_agent_installs_the_pinned_operator_toolchain():
assert 'chmod 0644 "${profile_file}"' in init_command assert 'chmod 0644 "${profile_file}"' in init_command
def test_owner_agent_uses_only_the_canonical_hostname(): def test_owner_agent_uses_the_canonical_hostname():
paths = [ paths = [
HERMES / "agent-configmap.yaml", HERMES / "agent-configmap.yaml",
HERMES / "agent-deployment.yaml", HERMES / "agent-deployment.yaml",
@ -132,7 +132,7 @@ def test_owner_agent_uses_only_the_canonical_hostname():
for path in paths: for path in paths:
content = path.read_text() content = path.read_text()
assert "agent.bstein.dev" not in content assert "agent.bstein.dev" not in content
assert "agent.hermes.bstein.dev" in content assert "worker.bstein.dev" in content
def test_agent_reconnect_retains_complete_history_and_long_tool_budget(): def test_agent_reconnect_retains_complete_history_and_long_tool_budget():

View File

@ -35,8 +35,10 @@ PUBLIC_HOSTS = {
"triage.hermes.bstein.dev": "oauth2-proxy-hermes-triage", "triage.hermes.bstein.dev": "oauth2-proxy-hermes-triage",
} }
# The agent surface was deliberately untouched by the rename. # The agent surface is mid-rename too: worker.bstein.dev is canonical and the
# legacy name stays served until a deliberate retirement change removes it.
AGENT_HOST = "agent.hermes.bstein.dev" AGENT_HOST = "agent.hermes.bstein.dev"
AGENT_CANONICAL_HOST = "worker.bstein.dev"
def _docs(path: Path) -> list[dict]: def _docs(path: Path) -> list[dict]:
@ -107,21 +109,29 @@ def test_host_is_registered_with_keycloak(host: str, ensure_script: str):
assert f"https://{host}" in ensure_script assert f"https://{host}" in ensure_script
def test_agent_surface_was_not_touched_by_the_rename( @pytest.mark.parametrize("host", [AGENT_HOST, AGENT_CANONICAL_HOST])
certificate: dict, coredns_hosts: set[str], ensure_script: str def test_agent_surface_serves_both_hosts_during_its_rename(
host: str, certificate: dict, coredns_hosts: set[str], ensure_script: str
): ):
assert AGENT_HOST in certificate["spec"]["dnsNames"] """Retiring the legacy owner host is a separate, deliberate change.
assert AGENT_HOST in coredns_hosts
assert f"https://{AGENT_HOST}" in ensure_script The agent hosts are served by hermes-agent-dashboard/-terminal rather than
hermes-sites, so their Ingress rules are asserted in
``test_hermes_agent_runtime_patches.py`` instead of the table above.
"""
assert host in certificate["spec"]["dnsNames"]
assert host in coredns_hosts
assert f"https://{host}" in ensure_script
def test_ensure_script_registers_legacy_and_renamed_origins_together( def test_ensure_script_registers_legacy_and_renamed_origins_together(
ensure_script: str, ensure_script: str,
): ):
"""The renamed proxies must carry both origins; the agent proxy only one.""" """Every renamed proxy must accept its old and new origin at the same time."""
for client, canonical, legacy in ( for client, canonical, legacy in (
("hermes-chat-proxy", "chat.bstein.dev", "chat.hermes.bstein.dev"), ("hermes-chat-proxy", "chat.bstein.dev", "chat.hermes.bstein.dev"),
("hermes-triage-proxy", "triage.bstein.dev", "triage.hermes.bstein.dev"), ("hermes-triage-proxy", "triage.bstein.dev", "triage.hermes.bstein.dev"),
("hermes-agent-proxy", "worker.bstein.dev", "agent.hermes.bstein.dev"),
): ):
call = re.search( call = re.search(
rf'ensure_proxy_client "{client}".*?(?=\nensure_)', rf'ensure_proxy_client "{client}".*?(?=\nensure_)',