fix(managed): restart resubmitted terminal targets #109

Merged
Lochnair merged 1 commits from fix/managed-terminal-reconcile into main 2026-08-15 15:56:45 +00:00
Lochnair commented 2026-08-15 15:51:04 +00:00 (Migrated from github.com)

Summary

  • a desired target whose current generation is Terminal no longer satisfies an identical update_targets desired-set submission;
  • resubmitting that target explicitly creates a fresh generation;
  • non-Terminal identical targets remain idempotent;
  • no automatic retry behavior is introduced.

Bug

An organic opening failure left the target as desired=true and Terminal. An identical update_targets submission was then acknowledged as a no-op, causing permanent non-progress under ExplicitStop.

Desired-state semantics

An identical non-Terminal generation is converged. A Terminal generation is not converged.

The caller still triggers retry by submitting a new desired-set transaction.

Generation

The retired Terminal TargetInstance keeps its original generation and recorded outcome. The replacement receives a fresh generation from the existing global allocator and begins Pending.

Outcome preservation

The old generation's already-recorded failure outcome is preserved. Reconciliation removes that Terminal runtime without emitting or recording a synthetic second Replaced outcome.

Limits / transaction

Synchronous Terminal retirement means max_live_target_generations=1 can replace one failed target without transiently requiring capacity for two generations. Validation, generation allocation, command sequencing, and prospective live-limit checks remain fallible-before-apply.

Scope

No automatic retry, backoff, poll_target refactor, client adapter change, server change, CLI change, or public API shape change.

Tests

  • organic opening failure plus identical resubmission;
  • fresh Pending generation and acknowledgement/status snapshot;
  • no duplicate old-generation outcome or TargetFinished event;
  • live identical target remains a no-op;
  • max-live=1 permits Terminal replacement;
  • changed-auth and changed-address replacements remain generation replacements.

Verification

  • cargo test -p irtt-client --all-features --locked managed
  • cargo fmt --all -- --check
  • cargo check --workspace --all-targets --all-features --locked
  • cargo test --workspace --all-targets --all-features --locked
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --locked
  • cargo check -p irtt-cli --no-default-features --features client --all-targets --locked
  • cargo check -p irtt-cli --no-default-features --features tui --all-targets --locked
  • cargo check -p irtt-cli --no-default-features --features server --all-targets --locked
  • git diff --check
## Summary - a desired target whose current generation is Terminal no longer satisfies an identical update_targets desired-set submission; - resubmitting that target explicitly creates a fresh generation; - non-Terminal identical targets remain idempotent; - no automatic retry behavior is introduced. ## Bug An organic opening failure left the target as desired=true and Terminal. An identical update_targets submission was then acknowledged as a no-op, causing permanent non-progress under ExplicitStop. ## Desired-state semantics An identical non-Terminal generation is converged. A Terminal generation is not converged. The caller still triggers retry by submitting a new desired-set transaction. ## Generation The retired Terminal TargetInstance keeps its original generation and recorded outcome. The replacement receives a fresh generation from the existing global allocator and begins Pending. ## Outcome preservation The old generation's already-recorded failure outcome is preserved. Reconciliation removes that Terminal runtime without emitting or recording a synthetic second Replaced outcome. ## Limits / transaction Synchronous Terminal retirement means max_live_target_generations=1 can replace one failed target without transiently requiring capacity for two generations. Validation, generation allocation, command sequencing, and prospective live-limit checks remain fallible-before-apply. ## Scope No automatic retry, backoff, poll_target refactor, client adapter change, server change, CLI change, or public API shape change. ## Tests - organic opening failure plus identical resubmission; - fresh Pending generation and acknowledgement/status snapshot; - no duplicate old-generation outcome or TargetFinished event; - live identical target remains a no-op; - max-live=1 permits Terminal replacement; - changed-auth and changed-address replacements remain generation replacements. ## Verification - cargo test -p irtt-client --all-features --locked managed - cargo fmt --all -- --check - cargo check --workspace --all-targets --all-features --locked - cargo test --workspace --all-targets --all-features --locked - cargo clippy --workspace --all-targets --all-features --locked -- -D warnings - RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --locked - cargo check -p irtt-cli --no-default-features --features client --all-targets --locked - cargo check -p irtt-cli --no-default-features --features tui --all-targets --locked - cargo check -p irtt-cli --no-default-features --features server --all-targets --locked - git diff --check
Sign in to join this conversation.