feat(aosguard): CI failure alerting as one sealed verb #1093

Merged
coilysiren merged 1 commit from aos/claude/wt57-aosguard-telegram into main 2026-08-16 06:09:59 +00:00
Owner

Kai's idea, and it is better than every option I put on infrastructure#850.

aosguard ops telegram alert posts a job's failure to the in-cluster
signoz-telegram mapper. It takes no arguments. Every field is read from the
runner's own GITHUB_* environment.

- name: Alert Telegram on main failure
  if: ${{ failure() && github.ref == 'refs/heads/main' }}
  continue-on-error: true
  run: aosguard ops telegram alert

The point is deleting copies

Four implementations of this alert exist across the fleet, each drifting on its
own:

  • agentic-os - the local actions/telegram-alert composite action
  • infrastructure - scripts/actions/alert-telegram.py, the rollout's source
  • deploy - scripts/alert-telegram.py
  • agentic-os-kai - scripts/ci/alert-telegram.py

The program is embedded in the binary and the leaf is sealed, following
forgejo-storage measure. No repository carries an alert program, and a caller
cannot turn a fixed POST into an arbitrary one.

Verified

Against a local capture server, so nothing was sent to Telegram:

$ aosguard ops telegram alert
alert posted: 200

coilyco-bridge/deploy CI failing
workflow: deploy-galaxy-gen
run: https://forgejo.coilysiren.me/coilyco-bridge/deploy/actions/runs/4821
  • ALERT_KIND=CD switches the first line.
  • A trailing argument is refused: "alert is sealed: it forwards its pinned
    command exactly and accepts no trailing arguments".
  • A shell metacharacter is refused by policy before exec.

Availability, including where it does not work

Every workflow setting container: agentic-os:release already has aosguard on
PATH, which is 29 of the fleet's 31 alerting workflows. The other two are
deploy/reconcile.yml and deploy/compose-review-roles.yml, both
runs-on: deploy, which is a deploy:host executor. Host-executor steps run
in the runner pod rather than that image, so they have no aosguard. Those two
either keep a script or the runner pod gains the binary. Not decided here.

Sequencing

This lands the verb only. Consumers cannot call it until it ships in a released
image, so call-site moves and deleting the four implementations are the next
step, not this PR.

Depends on nothing. infrastructure#852 is independent and still worth landing:
it fixes the message format and retires the Telegram secrets on the current
shape, which is what the two host-executor workflows keep using.

Kai's idea, and it is better than every option I put on infrastructure#850. `aosguard ops telegram alert` posts a job's failure to the in-cluster `signoz-telegram` mapper. It takes no arguments. Every field is read from the runner's own `GITHUB_*` environment. ```yaml - name: Alert Telegram on main failure if: ${{ failure() && github.ref == 'refs/heads/main' }} continue-on-error: true run: aosguard ops telegram alert ``` ## The point is deleting copies Four implementations of this alert exist across the fleet, each drifting on its own: * `agentic-os` - the local `actions/telegram-alert` composite action * `infrastructure` - `scripts/actions/alert-telegram.py`, the rollout's source * `deploy` - `scripts/alert-telegram.py` * `agentic-os-kai` - `scripts/ci/alert-telegram.py` The program is embedded in the binary and the leaf is `sealed`, following `forgejo-storage measure`. No repository carries an alert program, and a caller cannot turn a fixed POST into an arbitrary one. ## Verified Against a local capture server, so nothing was sent to Telegram: ``` $ aosguard ops telegram alert alert posted: 200 coilyco-bridge/deploy CI failing workflow: deploy-galaxy-gen run: https://forgejo.coilysiren.me/coilyco-bridge/deploy/actions/runs/4821 ``` * `ALERT_KIND=CD` switches the first line. * A trailing argument is refused: "`alert` is sealed: it forwards its pinned command exactly and accepts no trailing arguments". * A shell metacharacter is refused by policy before exec. ## Availability, including where it does not work Every workflow setting `container: agentic-os:release` already has aosguard on PATH, which is 29 of the fleet's 31 alerting workflows. The other two are `deploy/reconcile.yml` and `deploy/compose-review-roles.yml`, both `runs-on: deploy`, which is a `deploy:host` executor. Host-executor steps run in the runner pod rather than that image, so they have no aosguard. Those two either keep a script or the runner pod gains the binary. Not decided here. ## Sequencing This lands the verb only. Consumers cannot call it until it ships in a released image, so call-site moves and deleting the four implementations are the next step, not this PR. Depends on nothing. `infrastructure#852` is independent and still worth landing: it fixes the message format and retires the Telegram secrets on the current shape, which is what the two host-executor workflows keep using.
feat(aosguard): CI failure alerting as one sealed verb
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 16s
ci / ward-doctor (pull_request) Successful in 13s
ci / gate (pull_request) Successful in 51s
e7a1a1bd89
`aosguard ops telegram alert` posts a job's failure to the in-cluster
signoz-telegram mapper. It takes no arguments: every field is read from the
runner's own GITHUB_* environment.

The point is deleting copies. Four implementations of this alert exist across
the fleet, each drifting on its own:

* agentic-os - the local actions/telegram-alert composite action
* infrastructure - scripts/actions/alert-telegram.py, the rollout's source
* deploy - scripts/alert-telegram.py
* agentic-os-kai - scripts/ci/alert-telegram.py

The program is embedded in the binary and the leaf is sealed, following
`forgejo-storage measure`, so no repository carries an alert program and a
caller cannot turn a fixed POST into an arbitrary one.

Verified against a local capture server:

    $ aosguard ops telegram alert
    alert posted: 200

    coilyco-bridge/deploy CI failing
    workflow: deploy-galaxy-gen
    run: https://forgejo.coilysiren.me/coilyco-bridge/deploy/actions/runs/4821

ALERT_KIND=CD switches the first line. A trailing argument is refused by the
seal, and a shell metacharacter is refused by policy.

Availability: every workflow setting `container: agentic-os:release` already
has aosguard. Jobs on the `deploy:host` executor do not, because host-executor
steps run in the runner pod rather than that image. That is two of the fleet's
31 alerting workflows, both in deploy.

This lands the verb only. Consumers migrate after it ships in a released image,
so call-site moves and deleting the four implementations come next.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
coilysiren deleted branch aos/claude/wt57-aosguard-telegram 2026-08-16 06:09:59 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!1093
No description provided.