Skip to content

feat: add Phase 3 durable effect execution - #326

Closed
eshulman2 wants to merge 14 commits into
phase2/event-interpretationfrom
phase3/durable-effects
Closed

feat: add Phase 3 durable effect execution#326
eshulman2 wants to merge 14 commits into
phase2/event-interpretationfrom
phase3/durable-effects

Conversation

@eshulman2

Copy link
Copy Markdown
Collaborator

Summary

  • add Redis and in-memory effect journals with atomic idempotent submission
  • lease due effects and recover abandoned executions after lease expiry
  • record structured success, precondition, retryable and terminal results
  • execute provider operations through a narrow registry with bounded exponential retry
  • index effect history by workflow run for inspection
  • add an idempotent Jira comment executor with provider-side recovery evidence
  • migrate resume acknowledgement comments from inline Jira calls to durable effects
  • run the effect sweeper alongside the queue worker

Stack

Correctness properties

  • intent is persisted before provider execution
  • duplicate submissions share one idempotency key and execute once
  • retries execute the effect without rerunning its originating station
  • expired execution leases are recoverable
  • terminal records cannot be replayed from a stale due-set entry
  • Jira comments are recovered by embedded effect identity after a crash between provider success and result persistence

Verification

  • uv run ruff check src/
  • uv run mypy src/forge/effects
  • uv run pytest tests/unit/ -q --strict-markers — 2,412 passed
  • uv run pytest tests/contracts tests/flows -q --strict-markers — 319 passed

@eshulman2
eshulman2 force-pushed the phase3/durable-effects branch from 9ca4ae5 to 6ca8089 Compare August 31, 2026 09:26
@eshulman2
eshulman2 marked this pull request as ready for review August 31, 2026 11:49

@eshulman2 eshulman2 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration testing found a durable-effect idempotency regression with Jira repository labels.

Reproduction:

  1. Start a Feature workflow with repo:forge-sdlc/forge inferred during PRD generation.
  2. Forge successfully adds that label.
  3. Manually remove the repository label while the workflow is paused.
  4. Revise/approve the PRD so spec generation runs.

generate_spec calls ensure_repo_labels() and correctly infers forge-sdlc/forge, but Jira never receives the second label update. The durable effect created by JiraClient._write() has the same identity as the earlier successful add-label effect (run, definition revision, operation, target, payload, and caller origin), so the journal reuses the completed result and suppresses execution. This prevents the executor from re-reading Jira and restoring external drift.

Observed on AISOS-2482. Expected behavior: convergent/idempotent label operations should re-check current provider state and restore a missing required label when invoked again. Please revise the effect identity/replay semantics so repeated reconciliation calls can execute after external drift, and add a regression test covering label removal between PRD and spec generation.

@eshulman2

Copy link
Copy Markdown
Collaborator Author

Superseded by the Forge 2.0 squash merged in #339.

@eshulman2 eshulman2 closed this Sep 6, 2026
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.

1 participant