A Git ref event and a Deploy delivery are separate idempotency boundaries. Ordinary ref-event processing may create repository Action runs and fan the result out to matching Deploy projects. Maintenance repairs only a missing Deploy delivery; it never manufactures another ref event and never starts new repository Actions.
The durable delivery identity is:
delivery:deploy:repo:<repository-id>:project:<project-id>:config:<generation>:sha:<40-char-sha>Maintenance copies the Action run IDs already attached to the latest matching
ref event into author_config_json.required_workflow_run_ids. A successful
required Action therefore remains successful and is not replayed. The release
gate continues to fail closed if any required run did not succeed.
Automatic reconciliation only fills a missing release. Any release for the same repository, project, configuration generation, and SHA—including a failed or cancelled release—blocks creation of a fresh repair release. This prevents a maintenance pass from rerunning repository commands after they may have started. Repeated maintenance calls recover the same queued claim or become a no-op.
For the target repository/project/configuration/SHA tuple, acceptance requires
exactly one deploy_release_runs build and no queued or in-progress Site-kind
runner run without a deploy_release_runs owner. A green build alone is
insufficient; the ownership condition must also pass.
Forge does not currently expose a post-command automatic retry. A future API-owned retry must require all of the following in one request:
The API must verify those values against the failed immutable release before it creates a new release. Adding that mutation remains a separately approved change; reconciliation must not infer permission from a failed build.
The API gives each generalized build workflow a release-specific identity. If
the dispatcher stops after allocating the workflow but before linking
deploy_release_runs, recovery finds that exact workflow, completes any missing
job/step/link rows idempotently, and dispatches it only while its persisted
workflow status is still queued. An in_progress or completed workflow is
linked back to the release but never replayed by API maintenance.