Skip to content

Phase 2.3 — ActionStatus compensation enums + engine wiring #698

Closed

Description

@intel352

Followup from workflow#640 Phase 2 + Phase 2.5 cascade closeouts. Phase 2 PR #694 (sha b09bced) reserved proto tags 4+5 with comment 'Phase 2.3 compensation (COMPENSATED + COMPENSATION_FAILED)'. Phase 2.5 added tag 6 candidate for SKIPPED. Now actually define these + wire compensation semantics.

Scope (5 sub-items per Phase 2 design)

  1. Define ACTION_STATUS_COMPENSATED (tag 4) + ACTION_STATUS_COMPENSATION_FAILED (tag 5) + ACTION_STATUS_SKIPPED (tag 6) enum values in plugin/external/proto/iac.proto
  2. Wire compensation logic in engine (iac/wfctlhelpers/apply.go) — when wfctl-side hook (OnResourceApplied / OnResourceDeleted) fails AFTER per-action driver succeeded, attempt to compensate
  3. Distinguish dispatch-fail (current ActionStatusError) from post-hook-fail (new ActionStatusCompensated/Failed) per cycle-1+2+3 Copilot findings on PR feat: workflow#640 Phase 2 — v2 hooks-over-gRPC contract (ApplyResult.Actions + ActionStatus + engine populate + decoder) #694 (apply.go:313/316/235/354 conflations — all deferred to Phase 2.3)
  4. Distinguish skipped-due-to-cancel from dispatch-fail per ctx-cancel deferral (apply.go:235 finding)
  5. Per-plugin opt-in via existing IaCProviderFinalizer (Phase 2.5) or new IaCProviderCompensator RPC

Design questions

  • What triggers compensation? wfctl-side hook failure (engine knows). Plugin-side post-driver-success errors (plugin emits via FinalizeApplyResponse?).
  • What does compensation DO? Engine could call plugin's Delete RPC for created resources. Risk: re-entrant delete during apply mid-flight.
  • Per-resource-type opt-in? Some resources are not compensable (e.g., DB writes already happened).
  • Test coverage strategy?

Approach

Full superpowers pipeline (brainstorm → design → plan → implement). Compensation semantics warrant dedicated design (saga-style rollback, per-resource-type opt-in, hook-failure-vs-driver-failure differentiation).

Deferred from Phase 2.5+ Cleanup Bundle (docs/plans/2026-05-17-phase2.5-cleanup-bundle-design.md in workflow repo) because: 'compensation semantics require dedicated design that warrants its own pipeline. Mixing it into a mechanical-cleanup bundle would dilute focus and force compromises.'

References

Activity

  1. intel352 commented on May 17, 2026

    @intel352
    ContributorAuthor

    Shipped via PR #700 (squash sha 7a85593). Workflow v0.56.0 published (18 assets, latest).

    Cascade summary

    • Proto: ACTION_STATUS_COMPENSATED (tag 4) + ACTION_STATUS_COMPENSATION_FAILED (tag 5) + ACTION_STATUS_SKIPPED (tag 6) defined.
    • Engine: replaced mapDispatchErrToStatus with 3 phase-specific helpers; 6 call sites updated.
    • Phase 2 + 2.5 conflations resolved: ctx-cancel/JIT-fail/driver-resolve-fail → SKIPPED (was Error/DeleteFailed); post-hook failures → COMPENSATION_FAILED (was Error/DeleteFailed).
    • COMPENSATED reserved-for-future-emission (no auto-compensation in this phase; plugins can opt to emit if they implement own compensation).

    Out of scope

    • Engine-side auto-compensation (Phase 2.4+ when demonstrated need)
    • Per-plugin emission of COMPENSATED (plugin v_next opt-in)
    • Plugin cascade (workflow only; engine populates server-side)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions