Skip to content

fix(team): restart_policy=never freezes the role instead of churning replacements - #108

Merged
arcaven merged 1 commit into
mainfrom
fix/restart-never-terminal
Aug 5, 2026
Merged

fix(team): restart_policy=never freezes the role instead of churning replacements#108
arcaven merged 1 commit into
mainfrom
fix/restart-never-terminal

Conversation

@arcaven

@arcaven arcaven commented Aug 5, 2026

Copy link
Copy Markdown
Member

A role declared restart_policy = "never" never stayed down: the failed session dropped out of CountsAsAlive with no RoleHealth entry, so the reconciler replaced it every 2s tick, uncapped and with no backoff. Left running, that leaks one live pane per ~8s cycle (238 accumulated tmux windows in one overnight demo environment). Fixing it makes "never" mean what the manifest contract and every operator expecting k8s restartPolicy: Never semantics assume: the role stops.

Contract ruling (operator, 2026-08-05): never = the role goes terminal on first failure. The failed row and its pane stay visible for post-mortem; recovery is delete team + re-apply, identical to MaxRestarts saturation.

Mechanism: both failure paths now freeze the role's BackoffUntil to the existing saturation sentinel, so reconcileRole's backoff gate permanently refuses replacements:

  • health path: applyRestartPolicy's RestartNever branch calls freezeRole after marking the session failed
  • reap path: noteReapedCrash short-circuits for never roles (freeze + mark failed + emit session.failed) instead of routing through ordinary crash backoff, which would have replaced the session after the window

Tests: TestRestartNeverFreezesRole (health path: exactly one failed session survives four repair opportunities; far-future freeze visible in RoleHealthSnapshot) and TestRestartNeverReapFreezesRole (reap path: pane kill + 10min clock advance, still no replacement). Full suite passes; docs/demo.md Act 1c updated to describe terminal behavior instead of presenting the churn as intended.

Also carries two gofumpt drift fixes in internal/otel (formatting only, pre-existing).

Root cause diagnosed in aae-orc-pyre (2026-08-02); dates to PR #21, made visible by PR #83.

Closes #107

…replacements

A never role's failed session dropped out of CountsAsAlive with no
RoleHealth entry, so the reconciler replaced it every tick, uncapped
and with no backoff: one leaked live pane per ~8s cycle. Never now
means the role stops. Both failure paths (health-stale and reaped
pane) freeze the role via the existing saturation sentinel, keeping
the failed row and pane for post-mortem. Recovery is delete team +
re-apply, same as MaxRestarts saturation. Act 1c demo doc updated;
the reap path now also emits session.failed for never roles.

Includes two gofumpt drift fixes in internal/otel (formatting only).

Closes #107
Refs: aae-orc-pyre
@arcaven
arcaven merged commit fd58620 into main Aug 5, 2026
9 checks passed
@arcaven
arcaven deleted the fix/restart-never-terminal branch August 5, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

restart_policy=never role is endlessly replaced by the reconciler: terminal session, non-terminal slot

1 participant