feat(runtime): add typed execution outcomes and safe retry lifecycle - #13
Merged
Merged
Conversation
Classify cancellation only from runner context, cap tight retry loops, keep provider text runtime-owned, and reject duplicate action IDs.
Keep nil-error typed outcomes authoritative across cancellation races and allow only runtime-owned provider code identifiers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ProviderResultdata from runner-owned normalizedActionResultidentity, status, route, and attemptsOutcome mapping
succeededandalready_satisfied->doneretryable_failure->failedwhen exhausted or halted for retry-afterpermanent_failure,rate_limited, andauthentication_required->failedstopped->stoppedcancelled->cancelledAlready-satisfied remains distinct in runtime results and events. Retryability is derived only from
retryable_failure; ambiguous and invalid results fail closed as permanent failures.Runtime lifecycle
MaxAttemptsPerActionEvents and audit
Action and lifecycle events retain execution mode and executor ID with outcome, attempt, derived retryability, optional retry-after milliseconds, optional safe provider code, and typed halt reason. Empty optional fields are omitted. Messages, targets, raw errors, raw responses, credentials, authorization data, and private content are not written to execution audit fields.
Standalone retry edits return
PlanActionEdit; they are not represented as provider execution events.Simulation and TUI
succeeded,done, attempt 1, andNo-op apply completed.Compatibility
Tests
Deterministic scripted executors cover first-attempt success, already satisfied, retry-success, retry exhaustion, permanent failure, rate limits, authentication loss, retry-after halt, stop, cancellation, invalid outcomes, unsafe metadata, and unexpected executor errors. Regression tests cover route identity, audit safety, simulations, plan JSON isolation, event names, policy continuation, and concise TUI output.
Deferred
Validation
gofmtverificationgo test -count=1 ./...go vet ./...go build ./cmd/vanishscripts/check-safety.shgit diff --check origin/main...HEADFinal review fixes
Runner-context cancellation
Runner.Runcontext is donecontext.Canceledandcontext.DeadlineExceedederrors fail safely as permanent failuresHard retry ceiling
Runtime-owned provider messages
Unique cleanup action IDs
CleanupPlan.Validaterejects duplicate action IDs with a clear indexed errorValidation rerun: changed-file
gofmt,go test -count=1 ./...,go vet ./...,go build ./cmd/vanish,scripts/check-safety.sh, andgit diff --check origin/main...HEADall pass.Final runtime corrections
Definitive results survive cancellation races
succeededandalready_satisfiedactions staydone; only untouched remaining actions becomecancelledProvider code persistence is closed
ProviderCodeis now a runtime-owned typed identifier with an explicit allowlisttemporary_failureremains available as a known diagnostic categoryAuthentication guidance is concise
authentication_requiredrenders one reconnect instruction instead of duplicate Message and Next step rowsValidation rerun: changed-file
gofmt,go test -count=1 ./...,go vet ./...,go build ./cmd/vanish,scripts/check-safety.sh, andgit diff --check origin/main...HEADall pass.