5205 Commits

Author SHA1 Message Date
flux-bot
c19e9d77bf chore(maintenance): automated image update 2026-08-22 01:54:00 +00:00
flux-bot
5826c6054d chore(maintenance): automated image update 2026-08-22 01:49:59 +00:00
flux-bot
69f9ec99f2 chore(maintenance): automated image update 2026-08-22 01:43:57 +00:00
ed98278981 Merge branch 'main' into feature/hermes-domain-rename-agent-worker-v2
Some checks failed
Tests / Declarative: Post Actions failed: 40, skipped: 19, passed: 2743
2026-08-21 23:15:16 +00:00
8ce45159de Merge branch 'main' into hermes/t_65356568-multiuser-capacity-assessment
Some checks failed
Tests / Declarative: Post Actions failed: 41, skipped: 19, passed: 2740
2026-08-21 23:14:33 +00:00
77905ff1db Merge branch 'main' into fix/cli-auto-failover-effort
Some checks failed
Tests / Declarative: Post Actions failed: 40, skipped: 19, passed: 2737
2026-08-21 23:12:12 +00:00
Hermes Agent
820872e117 feat(hermes-voice): route Whisper language to multilingual Piper
Port the original #27 detected-language pipeline onto the verified PR #39 prerequisite while preserving the current-main conversation instrument and host continuity changes.

Keep voice selection server-side with no user selector or client voice field. Reuse 207c16ab only for its stricter exact-code trust boundary, omitting malformed or absent language so Piper defaults to Amy.
2026-08-21 13:58:50 +00:00
Hermes Agent
724656d841 feat(hermes-tts): prepare fixed multilingual voice policy
Supersede draft PR #26 with a merge-safe prerequisite: bake and preload the amy, irina, and claude Piper models, route only validated server-side language to fixed voices, and leave the live voice deployment manifest unchanged.

Remove the pinned WebUI speaker selector and its persisted preference, omit client voice fields from every outbound TTS path, and keep hands-free Voice Mode and the conversation instrument intact. Hostile or legacy voice fields remain ignored by the Piper server.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 13:45:31 +00:00
Hermes Agent
94106bf252 refactor(hermes): rename the owner agent host to worker.bstein.dev
Introduce worker.bstein.dev as the canonical hostname for the owner-only
Hermes coordinator, previously agent.hermes.bstein.dev.

The rename is additive, matching the shape #38 restored for chat and triage.
CoreDNS, both agent Ingresses and the hermes-sites certificate now serve BOTH
names, so merging this cannot take away the endpoint the operator uses to
reach the coordinator. Retiring agent.hermes.bstein.dev is a separate,
separately scheduled change. No redirect middleware is added.

What switches to the new host:
- HERMES_DASHBOARD_PUBLIC_URL and the oauth2-proxy --redirect-url
- the Keycloak agent proxy rootUrl
- operator docs, skills, the ZAP baseline target and the triage monitor default

What stays dual-homed until retirement:
- CoreDNS hosts entry, both agent Ingress rules, certificate SANs
- API_SERVER_CORS_ORIGINS (now a comma-separated pair)
- the Keycloak redirect URIs, web origins and post-logout origins, so a
  rollback only needs the oauth2-proxy --redirect-url reverted and does not
  require re-running the ensure job

The agent client passes its legacy origin through the optional fourth argument
#38 added to ensure_proxy_client, so no second mechanism is introduced. The
immutable ensure Job goes -11 -> -12 because #38 already consumed -11 and that
run has completed; without a further bump this change would never be applied.
Login on the new host fails until the -12 Job completes.

Because the session and CSRF cookies use the __Host- prefix they are bound to
one origin, so a fresh login must start on worker.bstein.dev and existing
sessions do not carry over -- re-login is required after rollout.

#38's public-host continuity test now covers the agent proxy's dual origins
rather than asserting the agent surface was untouched by the rename.

Knowledge catalogs and diagrams regenerated with `make knowledge`.
2026-08-21 10:29:46 +00:00
Hermes Agent
004c41629e chore(knowledge): regenerate stale Atlas catalogs
`make knowledge` output on main no longer matched the manifests it renders
from. The legacy chat/triage hosts restored by #38 were missing from the
committed HTTP catalogs and diagrams, along with Flux kustomizations and
Grafana panels added since the last regeneration.

Pure `make knowledge` run against unmodified main, separated into its own
commit so the hostname rename that follows reviews as a hostname rename and
nothing else. No hand edits.
2026-08-21 10:24:46 +00:00
4d072f32ce Merge branch 'main' into fix/hermes-restore-legacy-chat-triage-hosts-v2 2026-08-21 10:17:25 +00:00
flux-bot
ab33b582c8 chore(bstein-dev-home): automated image update 2026-08-21 10:06:01 +00:00
flux-bot
678698c44b chore(bstein-dev-home): automated image update 2026-08-21 10:04:01 +00:00
Hermes Agent
f4f51323f6 hermes: restore legacy chat/triage hosts alongside the renamed ones
PR #34 renamed the public chat/triage hosts in place rather than adding
the new names, so chat.hermes.bstein.dev and triage.hermes.bstein.dev
were dropped from the certificate SANs, the hermes-sites Ingress rules
and the CoreDNS overrides at once. Both legacy hosts now answer 404 with
Traefik's default self-signed certificate, and the renamed hosts cannot
complete a login because the Keycloak clients still carry the old
redirect URIs, so chat and triage are unreachable on every hostname.

Make the rename additive, which is the rollback path the post-merge
runbook asks for when the OIDC step fails:

- put the legacy names back on hermes-sites-tls and on the Ingress,
  pointing at the same oauth2-proxy backends
- restore both CoreDNS host overrides for in-cluster resolution
- teach ensure_proxy_client to register an optional legacy origin, so
  hermes-chat-proxy and hermes-triage-proxy accept the old and new
  redirect URIs, web origins and post-logout origins at the same time
  while rootUrl stays on the canonical new host
- bump the immutable ensure Job so Flux reruns the script

Serving both names is deliberate: oauth2-proxy cookies are host-bound,
so redirecting the legacy hosts would silently drop live sessions.
Retiring them stays a separate, explicit change.

Supersedes #36, which only bumped the Job and would have left the
legacy hosts dark.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:49:09 +00:00
66a537ddbe Merge branch 'main' into feature/hermes-direct-cli-lane-concurrency-2-replacement 2026-08-21 07:57:35 +00:00
Hermes Agent
4277aa6a02 fix(hermes): allow two direct CLI lane workers 2026-08-21 07:11:55 +00:00
Hermes Agent
79be4d1c71 refactor(hermes): rename chat and triage public hosts 2026-08-21 06:43:19 +00:00
468b21beb7 Merge branch 'main' into feature/hermes-kanban-profile-concurrency-2 2026-08-21 06:11:08 +00:00
Hermes Agent
d579c08cbe fix(hermes): cli-auto capacity failover uses automatic Switchyard reclassification
Capacity/auth/quota failover for cli-auto previously called select_route
with a hardcoded manual lane (cli-{alternate}-{effort}), so the retry
boundary was classified as switchyard-manual instead of going through
Jetson automatic classification, making the routing evidence misleading.

Now the retry calls select_route(context, "cli-auto", exclude_provider=...)
so the boundary stays automatically classified with an explicit
failed-provider exclusion. If the classifier reclassifies to a lower
effort than the original route, the lane re-pins the chosen provider at
the original effort floor so a capacity failure never silently downgrades
a high/xhigh task. Manual lanes (assignee != cli-auto) remain unchanged
and still fail closed without switching providers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-21 05:04:55 +00:00
flux-bot
0c264e873b chore(maintenance): automated image update 2026-08-21 01:50:29 +00:00
flux-bot
79c1809286 chore(maintenance): automated image update 2026-08-21 01:49:29 +00:00
flux-bot
287b61ed3e chore(maintenance): automated image update 2026-08-21 01:46:27 +00:00
flux-bot
12f568e78b chore(maintenance): automated image update 2026-08-21 01:41:26 +00:00
Hermes Agent
dda2d5fb60 fix(hermes): persist per-profile Kanban concurrency 2026-08-21 00:27:38 +00:00
flux-bot
33534e3b52 chore(bstein-dev-home): automated image update 2026-08-20 21:59:54 +00:00
flux-bot
ded90b607a chore(bstein-dev-home): automated image update 2026-08-20 21:57:54 +00:00
Hermes Agent
d22588dddb fix(hermes): poll the session contract the chat tenants actually serve
Returning to chat.hermes.bstein.dev after a Keycloak logout/login showed
"This session is unavailable to this account. Start a new chat." even
though the session was intact and owned by the same subject.

The banner comes from the continuity fallback the router injects into
every chat page. It polled `/api/sessions/<id>` and
`/api/sessions/<id>/messages` — routes that belong to the Hermes agent
dashboard (added by scripts/patch_web_session_activity.py, applied only
in agent-deployment.yaml). The router proxies browser traffic to the
tenant Hermes WebUI instead, whose only session read is
`GET /api/session?session_id=<id>`; the dashboard paths are unrouted
there, so server.py answered its generic 404 for every poll and the
fallback reported a false ownership failure.

The script runs only on a full document load of `/session/<id>`, which is
exactly what the OIDC round-trip produces when oauth2-proxy returns the
browser to `rd=/session/<id>` — hence the "only after relogin" symptom.

Poll the WebUI contract instead, and let its own answers decide what the
banner claims: 409 `session_profile_mismatch` is the single response that
means the session is outside this account's active scope, 404 now means
the conversation is no longer stored, and 401/403 still re-enter OIDC.
The steady-state poll drops to one request and backs off to 3s/15s now
that it reaches a real endpoint on the tenant Raspberry Pi.

`boundSessionSnapshot` follows the same move: it caps the WebUI envelope
`{"session": {..., "messages": [...]}}`, relaying every other session key
verbatim rather than re-serializing a fixed struct that would silently
drop metadata the banner depends on.

Isolation is unchanged and now covered: the router still resolves the
slot from the salted Keycloak subject, overwrites any client-supplied
X-Hermes-Tenant-Identity, and forwards only the two tenant cookies.

Tests: relogin keeps a stable slot and resolves the durable session; a
second subject replaying the owner's session id, WebUI cookie and a
forged tenant header gets 404 from its own backend and never reaches the
owner's; the legacy dashboard paths are pinned as permanent 404s against
a stub of the deployed WebUI dispatch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 18:14:55 +00:00
flux-bot
11bd04cce5 chore(maintenance): automated image update
Some checks failed
Tests / Declarative: Post Actions failed: 35, skipped: 7, passed: 2586
2026-08-20 13:49:00 +00:00
flux-bot
1c731b5baa chore(maintenance): automated image update 2026-08-20 13:48:53 +00:00
flux-bot
16bf178b18 chore(maintenance): automated image update 2026-08-20 13:45:52 +00:00
flux-bot
ce0b81c49f chore(maintenance): automated image update 2026-08-20 13:39:52 +00:00
flux-bot
347183090a chore(bstein-dev-home): automated image update 2026-08-20 09:53:23 +00:00
flux-bot
b036fbba88 chore(bstein-dev-home): automated image update 2026-08-20 09:51:23 +00:00
Hermes Agent
2862594c62 fix(monitoring): measure Atlas availability honestly across telemetry gaps
The 2026-08-18 metrics-storage outage exposed two defects in the
availability pipeline that distorted the figure in opposite directions at
once.

The Overview panel fell back to a live one-hour Traefik ratio whenever the
yearly rollup sample went stale for 48h, and rendered it under the same
"365d" title. When the rollup stopped publishing on 2026-08-18 the panel
quietly swapped a 365-day measurement for a 60-minute one and read 99.74%
instead of the recorded 99.95%. The fallback is removed: a stale rollup now
renders no value, and a new atlas-availability-rollup-stale alert pages at
26h, well before the panel goes blank at 48h.

The yearly ratio also silently excluded the 34-hour telemetry gap, because
missing days contribute zero requests and zero failures. Absent data was
read as "nothing happened" — had Atlas genuinely been down in that window,
the figure would still have said 99.95%. Availability keeps its
measured-days-only definition, which is correct, but coverage is now
published alongside it and shown in a new panel, so a telemetry gap lowers
disclosed coverage instead of vanishing. The title reads "365d window" to
stop implying 365 days of data exist; request-v4 begins 2026-05-01.

The rollup job reported healthy runs across a day and a half of lost
publishes: a read-only VictoriaMetrics accepts an import and discards it.
It now reads each sample back and fails loudly when the write did not
survive.

Not addressed here: availability is still measured from inside the platform
via Traefik counters, so it cannot distinguish "Atlas down" from "telemetry
down", and misses failures that never reach Traefik (DNS, TLS, node dead).
An external synthetic prober is the real fix and needs a hosting decision.
2026-08-20 02:03:43 +00:00
flux-bot
a45a9b67fe chore(maintenance): automated image update
Some checks failed
Tests / Declarative: Post Actions failed: 35, skipped: 7, passed: 2586
2026-08-20 01:51:22 +00:00
flux-bot
58d6da2fac chore(maintenance): automated image update 2026-08-20 01:50:23 +00:00
flux-bot
1a82ab4912 chore(maintenance): automated image update 2026-08-20 01:47:21 +00:00
flux-bot
4d026ff2b4 chore(maintenance): automated image update 2026-08-20 01:42:20 +00:00
2b683d9775 Merge branch 'main' into hermes/fix-grafana-no-data-vm-storage
Some checks failed
Tests / Declarative: Post Actions failed: 35, skipped: 7, passed: 2586
2026-08-20 00:49:40 +00:00
flux-bot
417355b2af chore(bstein-dev-home): automated image update 2026-08-19 22:00:51 +00:00
flux-bot
4470e1e3ae chore(bstein-dev-home): automated image update 2026-08-19 21:57:51 +00:00
flux-bot
00741d6830 chore(maintenance): automated image update
Some checks failed
Tests / Declarative: Post Actions failed: 40, skipped: 7, passed: 2578
2026-08-19 13:48:54 +00:00
flux-bot
33b373fffe chore(maintenance): automated image update 2026-08-19 13:48:48 +00:00
flux-bot
5c23790df9 chore(maintenance): automated image update 2026-08-19 13:45:48 +00:00
flux-bot
297dd27db3 chore(maintenance): automated image update 2026-08-19 13:40:47 +00:00
Hermes Agent
c4eac8ceee fix(monitoring): keep VictoriaMetrics writable 2026-08-19 10:51:44 +00:00
flux-bot
8675cb81d0 chore(bstein-dev-home): automated image update 2026-08-19 10:09:21 +00:00
jenkins
e28b32bd4e hermes: run the reviewed agent image and arm the takeover
Some checks failed
Tests / Declarative: Post Actions failed: 40, skipped: 7, passed: 2578
Pins hermes-agent to sha256:4a385fbd, built by hermes-agent-image #11 from
this exact main revision through the daemonless Kaniko lane. Enables
kanban.auto_supervise and returns chat tenancy to the documented four slots.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 23:55:14 -03:00
flux-bot
493c1a1f4f chore(maintenance): automated image update 2026-08-19 02:03:02 +00:00
flux-bot
776b70e11a chore(maintenance): automated image update 2026-08-19 01:48:59 +00:00