42 Commits

Author SHA1 Message Date
flux-bot
befc4b8557 chore(maintenance): automated image update 2026-08-10 01:50:01 +00:00
flux-bot
b860a95b01 chore(maintenance): automated image update 2026-08-10 01:42:58 +00:00
flux-bot
e069e95444 chore(maintenance): automated image update 2026-08-09 13:33:03 +00:00
flux-bot
2d42f153c8 chore(maintenance): automated image update 2026-08-09 13:29:00 +00:00
flux-bot
a48704b77f chore(maintenance): automated image update 2026-08-09 01:32:25 +00:00
flux-bot
b2363a50d8 chore(maintenance): automated image update 2026-08-09 01:28:23 +00:00
jenkins
bb73efb285 feat(hermes): split chat agent and triage surfaces 2026-08-08 17:59:57 -03:00
flux-bot
e2f4302861 chore(maintenance): automated image update 2026-08-08 13:36:58 +00:00
flux-bot
ad211e2fa3 chore(maintenance): automated image update 2026-08-08 13:33:57 +00:00
flux-bot
1919326513 chore(maintenance): automated image update 2026-08-07 13:41:09 +00:00
flux-bot
59173a3abf chore(maintenance): automated image update 2026-08-07 13:37:05 +00:00
jenkins
0855e38c0f feat(ariadne): turn on suggested fixes for unpatchable findings
Most of the SonarQube backlog is refactors too diffuse for an anchored patch,
so without this the majority of what static analysis knows never reaches a
maintainer. Deduped on the rule like the pull requests, so one root cause
yields one issue.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 05:00:25 -03:00
jenkins
10a629d5a7 feat(ariadne): sweep seven projects, and stop advertising the wrong model
The sweep covered four projects because only four had a write allowlist.
ananke (Go, cmd/ and internal/), pegasus (Go backend, TS frontend) and
atlasbot (Python) all have SonarQube projects and mapped repositories; they
were excluded only for want of prefixes and suffixes, which are now set from
each repository's actual layout.

The per-sweep ceiling rises to seven, one per project. With rule-level dedupe
a project stops producing proposals once every rule it has is already under
review, so this is a ceiling rather than a rate - the backlog cannot become a
queue nobody drains.

The Hermes deployment annotation still advertised gpt-5.6-terra as primary.
The config has had claude-opus-5 as default and primary for some time, so the
annotation was telling operators the wrong thing about which model made a
decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 04:45:15 -03:00
jenkins
8c47328b23 feat(ariadne): sweep four services, and link proposals to the finding
Only one pull request appeared because the sweep was scoped to one project at
one proposal per hour - a throttle I set deliberately while nothing had ever
run, not a limit of the mechanism. It has now run, so it widens to every
project whose job also has a write allowlist: ariadne, metis, soteria and
bstein-dev-home. The rest are left out because without allowed prefixes
nothing is patchable, and a sweep would spend a SonarQube call to discover it
has nowhere to write.

Still one proposal per project per hour. The backlog is 139 findings on
Ariadne alone; the constraint that matters is how many pull requests a person
will actually read, not how many the mechanism could open.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 00:06:33 -03:00
jenkins
1bfb29388a feat(ariadne): link pull requests to the Hermes run that wrote them
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 23:17:06 -03:00
jenkins
00af41891c fix(ariadne): read the SonarQube token from a path Ariadne can already reach
The sweep's token was injected from kv/data/atlas/quality/sonarqube-oidc,
which the maintenance role cannot read. I granted that path on the live policy
and verified the read, but the grant was reverted by whatever manages Vault
policy, and the next rollout wedged: vault-agent-init retries a 403 forever, so
the pod never initializes and the Deployment cannot roll. The old replica kept
serving, which is the only reason this was not an outage.

A template block that depends on a grant outside this repository is the actual
defect. The token now lives beside Ariadne's other credentials in
kv/data/atlas/maintenance/ariadne-db - a path its role has always been able to
read - so no policy change is needed and nothing outside this repo can revoke
it. Existing keys at that path were merged, not replaced.

Guarded with an if, so a deployment whose secret predates the key renders an
empty value and starts normally instead of blocking on a missing field. The
sweep then reports an empty token and skips, which is the right failure: no
sweep is much better than no Ariadne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 22:42:23 -03:00
flux-bot
918898276a chore(maintenance): automated image update 2026-08-07 01:37:12 +00:00
flux-bot
b82d5d0206 chore(maintenance): automated image update 2026-08-07 01:33:03 +00:00
jenkins
d5440a9dd4 feat(ariadne): enable the SonarQube sweep, scoped to one project
Static analysis findings never fail a build, so nothing has ever pulled them
into triage. There are 139 open on Ariadne alone, each already naming its
file, line and rule - better-located evidence than the console text the
code-repair flow usually mines.

Scoped deliberately narrow to start: one project, one proposal per hourly
sweep, and only findings SonarQube itself estimates at 20 minutes or less.
Effort is the filter rather than severity because it is the closest proxy for
the single anchored change the patch validator can actually check. The
64-open-proposal ceiling still applies on top, so the queue cannot grow while
nobody is draining it.

Hotspots are not in the type list and cannot be: SonarQube models them as
needing human review, this instance's quality gate fails on exactly that
condition, and an automation that resolved them would be marking them reviewed
without review.

The token comes from Vault. Ariadne's maintenance role was granted read on
kv/data/atlas/quality/sonarqube-oidc, which it did not previously have.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 22:13:03 -03:00
jenkins
8140e0bf75 feat(ariadne): allowlist clear_stuck_agent_pods
A build whose agent never started is a distinct failure from one that lost a
connection mid-run, and a plain retry queues behind the same stuck pods. The
remediation clears pods that have already succeeded or failed - Ariadne's
existing scheduled cleanup - and only then rebuilds.

Mapping jenkins_agent_provisioning_failure to it keeps the one-classification-
one-action rule: a diagnosis asking for this action under any other
classification is still refused before anything runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 21:16:21 -03:00
jenkins
2fceb9caa5 feat(ariadne): allowlist reclaim_workspace_storage
Maps workspace_storage_exhausted to the reclaim action, so a build that failed
on a full workspace volume is remediated rather than escalated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 20:55:52 -03:00
jenkins
0af41aa995 feat(ariadne): declare the fix categories, and show them beside the actions
The three categories now appear in the deployment next to the action
allowlist, and the monitor prints both at the policy gate so the difference is
visible during a demo rather than asserted: two ids Ariadne may execute on its
own authority, three categories it may only ask Hermes to propose a patch for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 20:46:55 -03:00
jenkins
c05a5e4abb feat(ariadne): widen code and issue coverage, cap open proposals at 64
ananke, pegasus and atlasbot were triaged but mapped to no repository, so
their failures could produce neither an issue nor a pull request. All three
exist on main and are non-empty. data-prepper is deliberately absent: it has
no repository under bstein.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 13:10:20 -03:00
jenkins
5311b0bef2 feat(ariadne): map bstein-dev-home to its own log namespace
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 12:33:19 -03:00
flux-bot
7e11b99b34 chore(maintenance): automated image update 2026-08-06 13:46:29 +00:00
flux-bot
7b7e46e884 chore(maintenance): automated image update 2026-08-06 13:39:24 +00:00
jenkins
aab389499c fix(ariadne): let the pod finish booting before liveness judges it
The earlier probe fix addressed slow /health responses under load, but the
restarts continued with a different signature: connection refused rather than
timeout, meaning the app was not listening yet. Ariadne runs migrations and
builds its cron schedule before binding, which can outlast what liveness
allows from initialDelaySeconds, so the kubelet kept restarting a pod that
was merely still starting.

Add a startupProbe granting up to five minutes to come up, after which
liveness takes over unchanged. This is the case startupProbe exists for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 06:16:09 -03:00
jenkins
699d1a5689 fix(ariadne): stop the kubelet killing a healthy triage pod
The liveness probe used the default timeoutSeconds of 1. The auto-triage tick
runs every minute and spends most of it waiting on Jenkins, OpenSearch, Gitea
and Hermes, so against a 500m CPU limit /health occasionally answers in over a
second. Three of those and the container is killed, dropping triage ticks for
the length of a restart. Observed 11 times in 139 minutes, with the pod
sitting 1/2 Ready and restarting repeatedly.

Give both probes a 5s timeout and let liveness tolerate five failures, so a
busy tick is no longer mistaken for a hung process.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 05:20:35 -03:00
flux-bot
426b6db1e7 chore(maintenance): automated image update 2026-08-06 04:47:42 +00:00
flux-bot
a08815fb3f chore(maintenance): automated image update 2026-08-06 03:09:11 +00:00
flux-bot
4ff140ac45 chore(maintenance): automated image update 2026-08-06 03:02:09 +00:00
jenkins
97dfb1a844 feat(ariadne): allowlist the transient-infra retry action
The classification->action registry already mapped transient_infra_failure to
retry_transient_infra, but the action allowlist held only repair_demo_fixture,
so that route always died at the action_not_allowlisted gate. Add the action
and state the registry explicitly rather than relying on the code default.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:17:32 -03:00
jenkins
664e436575 feat(hermes-triage): real-repo patch proposals + Alertmanager email escalation
- Ariadne: per-repo code config for metis, lesavka, soteria,
  bstein-dev-home and ariadne, each with its own base branch, source path
  prefixes and file suffixes so a proposal can only touch that repo's
  source tree
- Alertmanager: the only receiver was an empty "default", so every alert
  fired into a void. HermesTriageHumanRequired now routes to an email
  receiver via Mailu's in-cluster local-domain relay, with resolved
  notices; scoped to service=hermes-triage so nothing else mails yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 21:30:34 -03:00
jenkins
46bd4daf88 docs(hermes-triage): delivery record + enable Gitea issue filing config
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 21:01:50 -03:00
jenkins
639b43673e feat(hermes-triage): enable real-service triage across homegrown Jenkins jobs
Adds ariadne, lesavka, soteria, metis, ananke, pegasus, atlasbot,
bstein-dev-home and data-prepper to the autotriage allowlist. These get
detection, evidence, Hermes diagnosis and human-required escalation only:
no allowlisted repair action applies to them, so nothing is mutated.

Verified on lesavka #582 with the new console failure-region evidence:
classification coverage_quality_gate_failure, confidence 0.93, first
failed gate coverage (previously undetermined).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 20:31:44 -03:00
jenkins
71e6357887 feat(hermes-code): demo repo Jenkins job + Ariadne code-path configuration
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 19:19:05 -03:00
jenkins
161834904f revert(hermes-triage): restore action allowlist after alert rehearsal
Rehearsal confirmed: emptied allowlist -> incident 14 human_required
(action_not_allowlisted) -> HermesTriageHumanRequired FIRING in vmalert and
active in Alertmanager.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 19:03:28 -03:00
jenkins
d23ee3f448 test(hermes-triage): temporarily empty action allowlist for alert-lifecycle rehearsal
Reverted immediately after the rehearsal confirms HermesTriageHumanRequired
fires and self-clears.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 18:51:58 -03:00
jenkins
2b8829b056 feat(hermes-triage): enable autoremediation for the demo loop
Observe-mode rehearsal passed: incident hermes-triage-demo/9 diagnosed
correctly (0.99 confidence, known_demo_fixture_failure) and stopped only
at this kill switch. Scope stays: allowlisted job, one allowlisted
action, one action per incident, isolated namespace.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 17:56:46 -03:00
jenkins
f4e2da317c feat(hermes-triage): human-required alert rule + Ariadne autotriage config
- vmalert: hermes-triage.yaml alert group (HermesTriageHumanRequired on
  ariadne_hermes_triage_incident{status="human_required"}, 1m interval),
  wire Alertmanager notifier into vmalert-atlas-availability
- Ariadne deployment: hermes autotriage env (observe mode: autotriage on,
  autoremediation OFF), 1m schedule, allowlist hermes-triage-demo only,
  HERMES_API_KEY from optional hermes-api-server-key Secret
2026-08-05 16:51:48 -03:00
jenkins
c4b4e8a404 Merge origin/main into layout migration
Reconciles the services layout migration with ~991 upstream commits:
- Remote content wins for cassandra/cassandra-auth, monitoring dashboards,
  vmalert availability rules, veles, vault auth script, dashboard render
  script and tests (request-v4 availability definition)
- Layout paths win for structure: keycloak/bstein-dev-home job dirs use
  bootstrap-jobs/validation-jobs; cassandra realm jobs live in
  cassandra-auth (removed keycloak duplicates)
- Union: applications CR list gains hermes-chat and cassandra
  image-automation
- Fixed post-migration paths in dashboard test module loader and
  hermes-access job header

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 16:26:36 -03:00
jenkins
8f45f47e60 refactor: restructure services layout, retire oceanus, add aether scaffolding
- Move flat service manifests into structured subdirs (apps/, bootstrap-jobs/,
  repair-jobs/, migration-jobs/, validation-jobs/, node-ops/, networking/)
- Retire oneoffs/ directories across services
- Remove oceanus cluster and its host roles; add aether cluster + terraform scaffolding
- Reorganize scripts/ into ops/, render/, sync/, manual-tests/
- Add Makefile with render/validate/test/flux targets and repo-structure tests
- Update flux-system application CRs to the new paths
- Add hermes-automated-triage-24h-plan knowledge doc (+ comms mirror)
- Refresh knowledge catalogs, dashboards, vmalert rules, quality contract

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 16:21:36 -03:00