36 Commits

Author SHA1 Message Date
jenkins
8a71084585 build(hermes-agent): source base image + test deps from in-cluster mirrors
The hermes-agent-image pipeline failed intermittently on external network:
Kaniko's docker.io fallback for the base image is IPv6-broken from build
pods, and the "Validate reviewed release source" stage pip-installed pytest
from files.pythonhosted.org (DNS failures). Neither should touch the public
internet.

Base image: repoint the Dockerfile FROM from docker.io to the in-cluster
Harbor "mirror" project, keeping the exact content-addressed index digest
(9c841866...) and both arch leaves. A Flux-managed one-shot Job
(services/harbor/hermes-agent-base-mirror-job.yaml, suspend: true like the
cassandra bootstrap job) runs `skopeo copy --all` from docker.io into Harbor
using the same Vault-injected admin credential as the existing Harbor
immutability jobs; a tiny fail-closed helper ensures the public target
project first. Digest pinning and multi-arch are preserved; Kaniko pulls it
over the internal insecure registry with no docker.io fallback.

Test deps: install pytest/PyYAML fully offline (`pip --no-index
--find-links`) from a reviewed in-repo wheelhouse
(ci/vendor/hermes-agent-test-wheels) matching the arm64 python:3.12 build
container, so the validate stage never resolves a public index.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvMSXH8VH2tMWXanb8SJdf
2026-08-25 13:53:22 -03:00
jenkins
ff2c003b4b build(hermes-agent): multi-arch image via two native kaniko legs
Repoint the hermes-agent base FROM at the upstream multi-arch OCI INDEX
digest (tag v2026.7.7.2, revision 9de9c25f) whose arm64 leaf is byte-for-byte
the previously pinned single-arch base, so the arm64 build is unchanged while
the same reviewed version now also resolves an amd64 leaf. Kaniko selects the
matching leaf per build platform.

Rework the release pipeline to build both arches natively and promote a
multi-arch image without switching off kaniko or weakening any existing
security assertion:

- Keep the arm64 kaniko leg on the unchanged rpi5 coordinating pod; it now
  pushes an arch-suffixed candidate tag (...-build-<N>-arm64).
- Add a second native amd64 kaniko leg on a titan-24-pinned, tolerating,
  resource-capped pod (ceiling strictly below the arm64 leg) that
  independently re-verifies the reviewed revision and stashes its leaf
  evidence (...-build-<N>-amd64).
- Add ci/scripts/hermes_multiarch_combine.py: a pure-python, fail-closed
  combiner that re-reads each per-arch leaf from the registry, proves its
  digest AND its config architecture, assembles a Docker manifest LIST
  (already inside the promote allow-list), refuses to overwrite an existing
  final tag, publishes the arch-less ...-build-<N> tag, and re-verifies the
  registry resolved the exact index referencing exactly the two leaves. It
  emits the index digest in the SAME digest-file/image-file format the
  single-arch step produced, so render/verify-evidence/hermes_oci_promote.py
  promote the INDEX with no change to those scripts.

Tests: add test_hermes_multiarch_combine.py (full hash/verification chain);
strengthen the image-builder suites for the two-arch topology (both kaniko
legs carry the reviewed heredoc-compat build-arg; amd64 leg pinned+capped+
boundary-checked; combine stage wiring; expanded evidence archive) without
weakening the arm64-leg assertions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvMSXH8VH2tMWXanb8SJdf
2026-08-25 11:05:29 -03:00
Hermes Agent
79be4d1c71 refactor(hermes): rename chat and triage public hosts 2026-08-21 06:43:19 +00:00
jenkins
a3077224e0 Merge origin/main (#14 + #16) into PR #15 decomposition reliability
Reconcile two independent test/gate reorganizations:
- Gate/semgrep/mailu: keep main's #16 dual-metric implementation.
- quality_contract.json: union #16 image-builder + #14 scm/node + #15 cli_lane.
- agent-deployment.yaml: keep #14 gitea removal + #16 image-build-token + #15 probe.
- Test splits: main's chat/coordinator/agent organization is authoritative;
  drop #15's redundant competing splits and #14's stale cli-lane duplicates;
  keep #15's cli-lane decomposition suite and port the execution-safety test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 00:42:53 -03:00
jenkins
e8c26ecf85 hermes: add daemonless agent image release lane 2026-08-17 08:25:52 -03:00
jenkins
73fefbb5d9 hermes: gate mixed image lane APIs 2026-08-17 08:16:35 -03:00
jenkins
1ba9f13959 hermes: bind terminal commit to journal inode 2026-08-17 07:19:10 -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
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
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
8c73906e6e hermes: preserve exact routes and accept Telegram images 2026-08-15 22:15:40 -03:00
jenkins
d27a9649cf hermes: secure node access and expose live workers 2026-08-15 13:58:42 -03:00
jenkins
9fa7612cd4 hermes: restore terminal rendering and worker lineage 2026-08-13 02:49:41 -03:00
jenkins
65b0e7f0c5 hermes: distinguish Claude subscription auth 2026-08-13 00:12:02 -03:00
jenkins
422f001a93 hermes: make Switchyard the routing authority 2026-08-11 20:22:26 -03:00
jenkins
9f21f66fcb hermes: route turns by service priority 2026-08-11 16:22:19 -03:00
jenkins
00e67b1482 hermes(agent): preflight protected socket auth 2026-08-11 04:05:46 -03:00
jenkins
c411018853 hermes(agent): recover stale dashboard sockets 2026-08-11 03:50:13 -03:00
jenkins
47ee53fd48 hermes: recover expired dashboard sessions 2026-08-11 02:23:15 -03:00
jenkins
f48ac926ec hermes(agent): retry dashboard ticket acquisition 2026-08-10 23:57:32 -03:00
jenkins
6169b2c802 hermes(agent): reconnect stock dashboard feeds 2026-08-10 23:44:56 -03:00
jenkins
f2a3616476 hermes: grant owner agent union access 2026-08-10 17:05:14 -03:00
jenkins
dee4ee8ab8 fix(hermes): put stock TUI in foreground 2026-08-10 05:45:36 -03:00
jenkins
aa8f97e3f0 fix(hermes): route delegated work independently 2026-08-10 05:16:30 -03:00
jenkins
c0b5af8621 fix(hermes): route every agent loop through Jetson 2026-08-10 04:31:41 -03:00
jenkins
379d2ea52e fix(hermes): run coding workers unattended 2026-08-10 02:15:34 -03:00
jenkins
9bdcddad7c feat(hermes): add Jetson-assisted auto routing 2026-08-09 02:42:30 -03:00
jenkins
432466156b fix(hermes): discover chat extraction backend 2026-08-08 23:59:05 -03:00
jenkins
639ac031a8 feat(hermes): strengthen isolated chat reasoning 2026-08-08 23:25:16 -03:00
jenkins
b315e02821 fix(hermes): report consumer access denial 2026-08-02 17:00:40 -03:00
jenkins
723a789ddf fix(hermes): isolate consumer sessions 2026-08-02 16:46:21 -03:00
jenkins
5c55735c89 fix(hermes): prevent stale dashboard sockets 2026-08-02 15:53:30 -03:00