205 Commits

Author SHA1 Message Date
Hermes Agent
7a55b259bf hermes: add the fenced three-node distributed execution pool
Three fenced worker Pods claim Hermes Kanban runs through a coordinator that
owns every state transition, with per-ordinal HMAC authority, a mediated
broker-only SCM path, and durable per-ordinal workspaces.

Content is the reviewed head of PR #18 (689bcb6e) with PR 16's and PR 19's
contributions removed: they were merged in only to validate co-existence and are
not prerequisites, so this branch no longer carries them as ancestors. Only PR 14
and PR 15 remain, because the broker boundary and the cli_lane_* decomposition
are load-bearing for two of the fixed P0 boundaries.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 16:31:15 +00:00
Hermes Agent
03b10ff8b1 Merge PR 15 (CLI lane decomposition) on top of PR 14 (Atlas SCM broker)
The distributed worker pool stacks on exactly two open pull requests, in this
order: PR 14 supplies the broker-only SCM boundary the mediators route through
and the hermes-scm-boundary-v2 ConfigMap they mount, and PR 15 supplies the
cli_lane_* decomposition -- including canonical_run_id and the eligibility
predicate on claim_ready -- that the coordinator depends on. Neither can be
dropped without breaking a fixed P0 boundary, so both are carried here as
prerequisites and this branch must not merge before them.

PR 16 (agent image release lane) and PR 19 (full-handoff acceptance harness)
are NOT prerequisites and are deliberately absent, so reviewing this branch no
longer means approving them.

PR 14 and PR 15 conflict with each other in nine paths. Each is resolved to the
resolution already reviewed on this branch at 4d4cf1bd.
2026-08-17 16:29:29 +00:00
jenkins
73fefbb5d9 hermes: gate mixed image lane APIs 2026-08-17 08:16:35 -03:00
jenkins
8c6e3acdac hermes: isolate Atlas SCM write authority 2026-08-17 07:58:44 -03:00
jenkins
2c1d97e551 hermes: match canonical Forgejo PR URL 2026-08-17 07:22:26 -03:00
jenkins
cf3e46c2b6 hermes: harden Forgejo client boundary 2026-08-17 07:22:26 -03:00
jenkins
762784da6b hermes: bound Atlas pull request client 2026-08-17 07:22:26 -03:00
jenkins
1ba9f13959 hermes: bind terminal commit to journal inode 2026-08-17 07:19:10 -03:00
jenkins
8c71d55853 hermes: harden journal quarantine races 2026-08-17 07:15:31 -03:00
jenkins
c20bc263e0 hermes: close terminal replay edge cases 2026-08-17 07:15:31 -03:00
jenkins
64ea6d685c hermes: harden replay and decomposition races 2026-08-17 07:15:31 -03:00
jenkins
f04a524738 hermes: preserve terminal results and prevent duplicate fanout 2026-08-17 07:15:31 -03:00
Hermes Agent
750dfa241f hermes: fail closed on kanban created-event producer drift
The sticky-block gate added in the previous commit classifies a task from
the `created` event payload that upstream `create_task` writes. That
producer is code we do not own, so trusting it silently was the gap: if
upstream renamed the key, dropped it, or stopped deriving it from
`initial_status`, the image would still build and ship a consumer that
mis-classifies every task it reads.

Anchor the producer contract at build time, before the regression suite
runs, with three assert-only preconditions: the `initial_status="blocked"`
park resolves `task_status` to `"blocked"`, every non-park creation
resolves it to something else, and the `created` event carries that same
variable under `"status"`. None of them rewrite the producer.

Textual anchors cannot see dataflow, so add the runtime net the reviewer
asked for. The suite now drives the real API: create + claim an ordinary
task, trip the circuit breaker once at failure_limit=1 so it parks with a
`gave_up` event (leaving its own `created` event as the most recent
create/block/unblock row), then recompute at failure_limit=2 and require
promotion to ready. That case is red under an unconditional-true created
predicate and red under producer drift that labels every created event
blocked, while the explicit block/unblock, dependency-promotion and
circuit-breaker-at-current-limit cases stay green. Non-blocked and
malformed created payloads are pinned as controls, and the gate now
rejects non-dict payloads rather than trusting `.get`.

Also make the live placement correction durable: titan-04 is cordoned
after repeated kernel undervoltage and kubelet failure and titan-19 was
probe/Longhorn unstable under worker load, so both join the hard NotIn
list; titan-05 is healthy but sits at 3592m/3600m requested CPU, so the
main hermes container gives back 50m (350m -> 300m) to schedule there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 22:42:18 +00:00
Hermes Agent
4f8dcfbbf7 hermes: harden worker isolation and blocked-task semantics
Three narrowly scoped Hermes reliability fixes backed by live evidence
from the Cassandra/titan-iac proof run.

Worker concurrency. Three simultaneous direct CLI workers on the 4-core
hermes-agent node drove load to ~45 and made the hermes and oauth2-proxy
containers fail their probes, leaving the pod 8/10 Ready; two workers
stayed at 10/10. Cap HERMES_CLI_LANE_CONCURRENCY at 2 and lower the
cli-lane-runner CPU limit from 3 to 2 so the dashboard and auth sidecars
keep a guaranteed share of the node. Requests are unchanged: the pod
still asks for 745m total, so placement does not move.

Service links. Kubernetes injects a service-link variable pair for every
service in the namespace, and hermes-claude-broker produces
HERMES_CLAUDE_BROKER_PORT=tcp://10.43.31.76:9006 — a value the broker
parses as an int. That contaminated worker and test environments even
though the deployment already addresses every service by DNS name. Set
enableServiceLinks: false on the hermes-agent pod spec.

Blocked-task scheduling. create_task(initial_status="blocked") records a
created event carrying status=blocked but never a blocked event, while
_has_sticky_block() only inspects blocked/unblocked events. recompute_ready()
considers blocked tasks, so an explicitly parked task with no incomplete
parent auto-promoted on the next dispatcher cycle. Teach _has_sticky_block()
to also recognize a created event whose payload status is blocked, which
covers tasks created before this image patch without adding a persisted
field. Dependency-driven promotion and the circuit-breaker failure-limit
guard are untouched; unblock_task() still releases either kind of block.

hermes-kanban-blocked-regression.py runs against the real upstream
kanban_db API during the image build, so the build fails if any of these
semantics regress.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 20:53:22 +00:00
jenkins
0dd6ea0f02 hermes: add durable Telegram topics 2026-08-16 15:59:09 -03:00
jenkins
ba590c2518 hermes: retain native auth failure health 2026-08-16 13:47:19 -03:00
jenkins
e8b4f0c57c hermes: widen local goal judge timeout 2026-08-16 13:29:10 -03:00
jenkins
2a103f9895 hermes: require findings in worker schema 2026-08-16 12:04:27 -03:00
jenkins
1ea8e16286 hermes: separate review findings from blockers 2026-08-16 11:54:26 -03:00
jenkins
42ac76fe67 hermes: carry goal-loop controller evidence 2026-08-16 11:27:24 -03:00
jenkins
1527fd1af0 hermes: enforce goal completion evidence 2026-08-16 11:11:38 -03:00
jenkins
2a94c7c74f hermes: isolate worker database lifetimes 2026-08-16 10:30:58 -03:00
jenkins
e758ee1059 hermes: survive transient Kanban storage faults 2026-08-16 09:33:30 -03:00
jenkins
18eeeabb62 hermes: avoid unavailable worker providers 2026-08-16 09:19:23 -03:00
jenkins
c0eda84fa1 hermes: recover stale Codex worker threads 2026-08-16 08:54:19 -03:00
jenkins
3b003b850d hermes: preserve Vault CLI credentials for workers 2026-08-16 08:39:45 -03:00
jenkins
46f37f32a3 hermes: streamline forge evidence tools 2026-08-16 08:21:33 -03:00
jenkins
c7ac16d206 hermes: harden Atlas forge workflow 2026-08-16 07:59:35 -03:00
jenkins
f35e89777b test: cover Switchyard image enum 2026-08-16 07:31:16 -03:00
jenkins
ece52b1f2e hermes: harden routed vision normalization 2026-08-16 07:24:20 -03:00
jenkins
8f7b57419a hermes: accept routed base64 vision 2026-08-16 07:12:11 -03:00
jenkins
bfd53100d9 hermes: normalize routed vision messages 2026-08-16 07:00:50 -03:00
jenkins
5dd13368c6 hermes: normalize vision requests for Codex 2026-08-16 06:55:49 -03:00
jenkins
cef7241f11 hermes: avoid empty ad hoc task lookups 2026-08-16 06:06:26 -03:00
jenkins
bebd92212e hermes: install pinned Go toolchain 2026-08-16 05:38:01 -03:00
jenkins
56a254d7d1 monitoring(ai): allow Switchyard metric scraping 2026-08-16 05:24:52 -03:00
jenkins
612cefad23 monitoring(ai): add provider quota operations dashboard 2026-08-16 05:13:20 -03:00
jenkins
012e5fc2ba hermes: recover stale kanban status pages 2026-08-16 04:49:02 -03:00
jenkins
4bab6130bc hermes: close parked kanban tasks atomically 2026-08-16 04:31:00 -03:00
jenkins
7d284871e8 hermes: show activity during dashboard bootstrap 2026-08-16 03:33:41 -03:00
jenkins
eace0ed0df hermes: scope stale activity lineage 2026-08-16 02:51:33 -03:00
jenkins
9bc47f9ce3 hermes: keep durable worker activity visible 2026-08-16 01:20:08 -03:00
jenkins
1d2d386aeb hermes: pin ARM64 runtime images 2026-08-15 22:32:08 -03:00
jenkins
e9efec4ddf hermes: keep provider lanes available under load 2026-08-15 22:15:40 -03:00
jenkins
8c73906e6e hermes: preserve exact routes and accept Telegram images 2026-08-15 22:15:40 -03:00
jenkins
89b9f1a4c7 hermes: isolate runtime access and expose activity 2026-08-15 22:15:40 -03:00
jenkins
07b64a0245 hermes: expose Vault SSH config to OpenSSH 2026-08-15 14:45:27 -03:00
jenkins
1ee766bc1e hermes: mount node access through Vault CSI 2026-08-15 14:34:49 -03:00
jenkins
d311df6c9b hermes: preserve node SSH account ownership 2026-08-15 14:27:11 -03:00
jenkins
6fd7b9bbba hermes: close stale API worker sessions 2026-08-15 14:20:12 -03:00