5536 Commits

Author SHA1 Message Date
Hermes Agent
cf7535c502 feat(hermes-tts): multilingual Piper voice policy (en=amy, ru=irina, es=claude)
Supersedes draft PR #24 (hermes/tts-voice-hfc-female): Brad changed the
decision after that task landed, so this starts fresh from origin/main
instead of building on it.

Bakes three checksum-pinned Piper voices (en_US-amy-medium,
ru_RU-irina-medium, es_MX-claude-high) alongside the existing lessac set,
and adds deterministic, allow-listed language routing to
hermes-jetson-tts-server.py: an explicit request "language" field maps
through a fixed dict to one of the three baked voices, with unknown,
missing, or malformed input always falling back to English amy. A
client-supplied "voice" field is never read, so no client input can reach
a filesystem path. All three voices are eagerly preloaded at process
start (measured ~243MB RSS for three vs. ~88MB for one).

The WebUI has no signal for the language of the text it is about to
speak (verified: hermes-webui-atlas-voice.js sends only text and engine),
so no client- or server-side language detection is added; this gap is
documented in NOTES.md and the PR description rather than papered over.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-20 18:53:43 +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
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
9872ee0995 Merge pull request 'fix(monitoring): keep VictoriaMetrics writable so public dashboards render' (#23) from hermes/fix-grafana-no-data-vm-storage into main
Reviewed-on: atlas/titan-iac#23
Reviewed-by: bstein <bstein@noreply.scm.bstein.dev>
2026-08-20 00:50:00 +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
jenkins
87f2c58e32 ci(hermes-agent-image): keep image file modes world-readable
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 22:35:18 -03:00
jenkins
baeb70e8b7 ci(hermes-agent-image): pull the base mirror inside the cluster network
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 20:44:36 -03:00
jenkins
fcbff58951 ci(hermes-agent-image): let release verification read the build evidence
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 20:32:00 -03:00
jenkins
b6ae6225f6 hermes: source handoff forge evidence through the scm broker
The acceptance harness pinned a forge client that has never existed in any
commit or pod (/opt/coordinator/gitea_api.py, digest f0943db4..., GIT/POST
grammar, an askpass helper). Every Gitea-backed check was therefore
unrunnable as merged. Point the harness at the credential-isolated SCM
broker client that actually ships in the agent pod.

- policy: GITEA_CLIENT=/opt/scm/gitea_api.py; trust /opt/scm/ instead of
  the phantom /opt/coordinator/; admit the client's real grammar
  (`read <api-path>`, exactly one path) with the same atlas/titan-iac pin
  and dot-segment rejection; bare HTTP methods are refused in every mode.
  The armed POST/PATCH/DELETE windows remain but are documented as
  deferred: the deployed client cannot execute them.
- exec: pin the client digest to the sha256 of
  services/hermes/scm-common/scripts/gitea_api.py — the exact file the
  hermes-scm-boundary-v2 ConfigMap mounts at /opt/scm/gitea_api.py — so
  the pin is derivable from merged source and equal to the deployed
  client. gitea_api.py gains a narrow /api/v1/user identity read in
  _authorize_read (see below), so the pin is the NEW source hash
  76efd16dedbeb74425b12fbbdbfaa391854771292077e0463bf22706855ae6dc.
  Drop the dangling GIT_ASKPASS (no helper exists; broker git needs
  none) and swap /opt/coordinator for /opt/scm in SAFE_PATH.
- checks: all forge/baseline/lineage probes use (client, "read", path).
  The SELF-vantage identity checks now truthfully assert the *broker's*
  forge identity (the only one the platform can exercise) is not an
  administrator and holds push-scoped, non-administrative repository
  authority; the administrative-route check asserts the broker read
  allowlist's live refusal of branch_protections. The remote-main step
  keeps `origin` (the broker remote exists only in pool workspaces and
  the broker origin is cluster-local); its rationale now tells the
  operator to ensure origin fetchability.
- gitea_api.py/_authorize_read: allow exactly `/api/v1/user` (no query,
  no sibling routes) as operation "identity" so the harness can prove
  the broker identity is not an administrator. The broker imports the
  same module, so one reviewed edit covers both sides of the boundary.
- rules: DENIAL_MARKERS now match the client's real refusal lines
  ("SCM broker request failed with HTTP 400/403" and the no-credential
  rejection) and drop "gitea api returned http 403", which the client
  never emits; a broker 404 is deliberately not denial evidence.
- ephemeral: index/verification reads use the real grammar; manual
  cleanup guidance now says close/delete require operator forge
  credentials (the client exposes no mutation besides create-draft);
  armed mode is documented as deferred until the probes are rebuilt on
  the broker's bounded mutation surface.
- docs: broker vantage/evidence section, operator prerequisites (broker
  healthy, no /vault/secrets/gitea-token anywhere on the harness path,
  current ConfigMap mount, operator-side client + origin fetchability),
  armed-mode deferral.
- tests: read-grammar accepted / GET refused in every mode, /opt/scm
  attestation pin proven equal to the merged source digest, real
  denial-marker matching, /api/v1/user identity route bounds; the
  repository-pin mutant probe speaks the new grammar. Full handoff +
  gitea + broker families pass (952 tests), mutation gate 13/13, per-file
  line+branch coverage >=95%, all touched sources within the 500-line cap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 18:21:38 -03:00
jenkins
e85fc7e633 hermes: deploy friendly automatic model labeling to consumer chat
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 18:21:37 -03:00
jenkins
0b25056d4e hermes: let the scm broker actually reach the forge ingress
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 18:21:27 -03:00
jenkins
835e9a2439 ci(hermes-agent-image): pull the reviewed base through the local mirror
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 17:29:45 -03:00
jenkins
3ee7368003 hermes: deploy decluttered consumer chat router
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:59:44 -03:00
jenkins
12f4fcc35f hermes: ship the new lane modules to the coordinator mounts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:57:10 -03:00
jenkins
79baa7ecb9 hermes: return two chat slots to fit the agent runtime
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:33:24 -03:00
jenkins
0a4ff7f1f6 hermes: read node access keys through CSI symlinks
The Vault CSI secrets-store projects /vault/secrets/node-ssh-public-key
as a symlink chain (file -> ..data/file -> ..<timestamp>/file), which
the O_NOFOLLOW hardened reader refuses with ELOOP, crash-looping the
hermes-node-ssh-access key reconciler on most nodes.

Resolve the projection safely instead of relaxing the reader: realpath
the secret strictly (loops and dangling links become a clean refusal),
refuse any resolution that escapes the read-only mount, then apply the
unchanged O_NOFOLLOW regular-file read to the resolved target. Host
account databases and authorized_keys keep the strict no-symlink read.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:28:25 -03:00
jenkins
a5cafddd45 hermes: accept merged lineage in handoff acceptance
The reviewed PR stack is now merged into main, so an open draft PR #19 is
no longer proof that the reviewed code is what runs. The mandatory
release.exact-lineage-is-running check now requires the merged terminal
state instead: PR #19 closed with merged=true, base main, the existing
feature ref, and the exact reviewed head, plus a new merge-ancestry step
that proves the reviewed head is an ancestor of the pinned origin/main
via git merge-base --is-ancestor. An open PR, a PR closed without
merging, a mismatched head, or a head that is not a proven ancestor of
main still fails closed; an undecidable ancestry probe is NOT_RUN. The
recorded pre-merge base SHA is no longer compared against current main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:28:25 -03:00
jenkins
ea97d37524 hermes: derive execution pool key with a supported template function
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:19:28 -03:00
jenkins
381c3e7283 ci(hermes-agent-image): run release boundary where git exists
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:14:35 -03:00
jenkins
de221a0ae2 hermes: fit agent pod on constrained workers
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 16:05:50 -03:00
jenkins
1c4ed3af93 Merge Hermes stack (PRs #15, routing, #22, #18, #19, #12, #21, in-pod supervisor) — chain tip 9749e650 2026-08-18 15:46:42 -03:00
jenkins
08ad19d451 Merge fix/jenkins-quality-gate-discovery: restore branch discovery on titan-iac-quality-gate 2026-08-18 15:46:32 -03:00
flux-bot
7a158f14e5 chore(maintenance): automated image update 2026-08-18 17:17:33 +00:00
jenkins
2eeb4bb5e6 ci(jenkins): restore branch discovery on titan-iac-quality-gate
The titan-iac-quality-gate multibranch job's git branch source was
defined without a discovery trait, so JCasC created it with empty
traits and it indexed zero branches — no PR ever built, no status
check was ever reported, and auto-merge could never fire. Add
traits { gitBranchDiscovery() } to match every working multibranch
job (e.g. hermes-code-demo-branches).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 13:58:20 -03:00
jenkins
9749e65042 Merge remote-tracking branch 'origin/feature/hermes-chat-smoothness' into feature/hermes-inpod-supervisor 2026-08-18 07:03:41 -03:00
jenkins
c8bb23ccd3 hermes: surface a friendly "Automatic" routing label
The composer routing chip showed bare AUTO/FAST/BALANCED/DEEP/MAXIMUM.
Relabel it to Automatic/Fast/Balanced/Deep/Maximum and align the
auto-route model option labels to Automatic · Fast/Balanced/Deep/Maximum
so they match the panels.js profile-default mapping and read as a
recognizable model name. Manual model names (Claude · Opus, etc.) are
unchanged. Update the image-build guard and its quality test to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 06:55:51 -03:00
jenkins
f83c59a1c9 hermes: declutter chat to a chat-only surface
Extend the chat router HTML-injection bridge so tenants see a clean
chat + conversation-history experience instead of the full agent
cockpit. hideChatAdministration now hides the rail buttons and panels
for logs, insights, memory, skills, workspaces, todos, tasks and
profiles (alongside the existing Kanban), and bridgeCSS hides the same
[data-panel] targets pre-JS to avoid a flash. Also hide the redundant
legacy settings model dropdown (#settingsModel) via bridgeCSS while
keeping the composer routing chip. Chat, history/sessions, new-chat,
composer and the model chip are untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 06:55:43 -03:00
jenkins
d1e8cda5ed hermes: make supervisor terminal emissions idempotent across ticks
Fix reviewer BLOCK: the stateless poll loop re-planned every terminal card each
tick, so SHIP and the two cycle-limit escalations - whose source cards stay in
the done state - re-fired their comment/block on every pass (~2880/day/chain).

- Add a persistent emission Ledger (/opt/data/supervisor/emitted.json): SHIP and
  escalate perform their action only when the (action, target) key is absent,
  then record it, so each fires at most once and survives a pod restart. Spawns
  remain self-limiting via the existing dedup scan.
- Cycle-limit escalations now target the SOURCE review/repair card (not the impl
  root), so the card also leaves the done state and is skipped next tick even if
  block_task round-trips imperfectly.
- Harden the _spawn TypeError fallback: re-run the dedup scan before retrying so
  a post-insert TypeError can never double-insert.
- Add across-ticks idempotency tests (10x supervise_once -> exactly one
  comment/flag/block) plus ledger persistence/corruption and spawn-guard tests.

Both modules stay 100% line+branch, <500 LOC. Stacks on the merge train
(base 5f27e50c).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 06:51:36 -03:00
jenkins
2b2c8bda14 Merge remote-tracking branch 'origin/wt/t_1e95ea6d' into feature/hermes-chat-smoothness 2026-08-18 06:46:48 -03:00
jenkins
a9ee1070be Merge remote-tracking branch 'origin/feature/hermes-full-handoff-acceptance' into wt/t_1e95ea6d
# Conflicts:
#	services/hermes/agent-deployment.yaml
#	testing/tests/test_hermes_auto_router.py
2026-08-18 06:41:13 -03:00
jenkins
6a7009b31c hermes: add in-pod autonomous kanban supervisor
Drive the cross-card implement->review->repair->re-review chain from inside
the pod so unattended runs no longer stall once the first implementation card
completes. Today that chain exists only as an external codex-shepherd session;
this adds a bounded in-pod poll loop that reads board state via
hermes_cli.kanban_db and creates Kanban follow-up cards (subscription lanes
only) with no provider/metered path of its own.

- kanban_supervisor.py (I/O shell) + supervisor_policy.py (pure state machine):
  impl-done+PR -> review; review SHIP -> mark impl ready-for-human (never
  merges/approves/clears WIP); review BLOCK -> bounded repair; repair new
  commit -> re-review. Fail-closed on unparseable/ambiguous state; per-
  (parent, head_commit) dedup safe beside the external shepherd; bounded review
  <->repair cycle count and max concurrent chains.
- Deployed as a hardened non-root sidecar (drop ALL caps, read-only rootfs, no
  runtime-access/credential mount) alongside model-steward; scripts packaged in
  the coordinator configMapGenerator.
- Gated by new kanban.auto_supervise config key (default false, re-read each
  tick like auto_decompose) so it is inert until the external shepherd retires.
- Fix latent goal_max_turns NULL fallback in cli_lane_execution (1 -> documented
  default 20).
- 62 new behavioral tests at 100% line+branch on both modules.

Stacks on the merge train (base 5f27e50c).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-18 06:28:49 -03:00