Reconcile uncertain tag pushes

This commit is contained in:
2026-10-05 18:53:44 +00:00
parent 3757d40ac4
commit 7481dd0fd2
7 changed files with 388 additions and 22 deletions

View File

@@ -43,7 +43,8 @@ tag object ID. Publication states distinguish an unattempted push, a tag that
was created locally but not pushed, a successful push, a guard conflict, and an
unresolved push error.
When a push reports an error, the local annotated tag is retained and the
result is `unknown` until a later implementation adds authoritative
reconciliation. Do not treat that state as success or proof that the remote
lacks the tag.
When a push reports an error, ReleaseKit makes one bounded query for the
authoritative tag. An exact tag object match confirms success. An absent tag is
reported as `not_published`, a different object as `conflict`, and an unreadable
query as `unknown`. The local annotated tag is retained in every case; an
`unknown` result is neither success nor proof that the remote lacks the tag.

View File

@@ -614,11 +614,12 @@ validates once between exact remote guards, creates an unsigned annotated tag,
rechecks local and remote state, and pushes only the captured tag object. Bare
remote tests verify the note bytes, peeled commit, tag object, unchanged branch
and unrelated refs, disabled follow-tags and mirror expansion, validation count,
remote conflicts, and retained local tags with `unknown` status after push error.
remote conflicts, and retained local tags after push error; Stage 8 adds outcome
classification through remote reconciliation.
## Stage 8: Resolve rejected and ambiguous publication
Status: Pending. Depends on Stage 7.
Status: Complete. Depends on Stage 7.
1. Add the one-query reconciliation path and public error/result classification.
Preserve the original push cause when resolution does not confirm success.
@@ -635,6 +636,17 @@ missing, conflicting, and unavailable remote tags have distinct outcomes. Failed
pushes issue one reconciliation query, successful pushes issue none, and no
recovery force-update or automatic tag deletion occurs.
Evidence: failed tag pushes receive one bounded exact-tag query. Matching object
identity returns published; absence returns not_published with the original push
error; a different object returns conflict; query failure returns unknown while
preserving the push cause. Tests cover rejection by a bare remote's receive
hook, an installed conflicting tag, unavailable reconciliation, and a lost
acknowledgment after the bare remote accepted the tag while the caller context
was canceled. Query counts confirm one recovery read after errors and none after
a successful push.
Tests also verify that a remote branch change during validation and a changed
local tag before push prevent publication.
## Stage 9: Expose publication and document ReleaseKit bootstrap
Status: Pending. Depends on Stage 8.