Skip to content

Name a Recovery a Dispatch Can Actually Perform in D4.5 - #1213

Merged
ptr727 merged 2 commits into
developfrom
fix/d45-recovery-bound
Sep 2, 2026
Merged

Name a Recovery a Dispatch Can Actually Perform in D4.5#1213
ptr727 merged 2 commits into
developfrom
fix/d45-recovery-bound

Conversation

@ptr727

@ptr727 ptr727 commented Sep 2, 2026

Copy link
Copy Markdown
Owner

One reviewer finding from #1203, the develop -> main promotion PR, fixed at its source in both places it appears. A promotion PR's head is develop, so it could not be pushed there directly.

What the finding was

D4.5 named a recovery the publisher forbids. It said a failed package push is recovered "by re-dispatching the same commit", and workflow_dispatch accepts a branch or tag ref rather than a commit SHA. publish-release.yml triggers on workflow_dispatch alone, its assert-dispatch-ref job rejects any ref_name that is not main or develop, and the publish job passes ref: ${{ github.sha }}, the dispatch-time tip.

A maintainer with a failed NuGet push follows that sentence, runs gh workflow run publish-release.yml --ref <failed-sha>, gets HTTP 422 No ref found, falls back to the release tag, and is rejected again by the ref gate.

Why both copies moved

CodeRabbit asked for the bound in all four D4.5 copies. A first pass at this fixed the three condensed ones and left WORKFLOW.md, on the reading that it already stated the limit in its next sentence. It does, and it still opened with the same unperformable phrasing, so a reader routed to the authority for exact wording landed on the less accurate of the two texts.

WORKFLOW.md now says a re-dispatch "while the branch tip is still the commit whose push failed", which is also the accurate half, since the build succeeded and only the push failed, and adds that the dispatch names the branch rather than the commit.

The condensed catalog carries the limit and the harm together, that a re-dispatch after the tip has moved publishes a further version and leaves the first release without its package, with the git-height cause that makes it deterministic rather than merely risky. version.json declares no pathFilters, so any commit advances height.

Provenance

Both come from the promotion this fixes. #1198 added the failed-push paragraph to WORKFLOW.md with its caveat and added the condensed restatement without it, so the authority and the catalog disagreed from the moment they landed.

Review

Whole-unit passes over the two changed units settled the wording, and the process is worth recording because the sentence took several attempts. Each earlier revision was rejected for a distinct, real defect:

  • an operation the publisher forbids (the original)
  • a relative clause attached to cleanup rather than to the re-dispatch
  • a split correlative, where rather than by cleanup read as attaching to repairs
  • an antecedent-less demonstrative, after removing the phrasing that had introduced the referent
  • a garden path, where a later one read off the branch tip
  • the harm stated with its cause dropped

The shipped wording is a reviewer-supplied split that carries none of them.

Deliberately not here

The same passes found pre-existing defects in both units, each filed rather than swept in:

Verification

Every gate OPERATIONS.md "Local Verification" names, run at the head commit: build_dist.py --check, canonical_review.py check and report --check, repo_gate.py, prose_lint.py, spec/validate.py, and markdownlint-cli2 on both changed Markdown files. All green.

Two changed carried units, each covered by a recorded whole-unit pass, and the diff receipt recorded against the shipping content. Both ledger entries name a commit that resolves on the remote.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Clarified that a failed package push may leave the release and tag published without a package.
    • Documented that re-dispatching the same commit repairs the original release when the branch tip is unchanged.
    • Clarified that re-dispatching after the branch tip moves publishes a newer version, leaving the original release incomplete.
  • Chores

    • Updated supporting documentation metadata and review records.

CodeRabbit found on #1203 that D4.5 names a recovery the publisher forbids.
It said a failed package push is recovered "by re-dispatching the same
commit", and workflow_dispatch accepts a branch or tag ref rather than a
commit SHA. publish-release.yml triggers on workflow_dispatch alone, its
assert-dispatch-ref job rejects any ref_name that is not main or develop, and
the publish job passes ref: github.sha, the dispatch-time tip. A maintainer
following that sentence runs gh workflow run --ref <sha>, gets HTTP 422, and
finds the release tag rejected too.

The finding asked for the bound in all four D4.5 copies. WORKFLOW.md stated
it in its next sentence and still opened with the same unperformable phrasing,
so both surfaces move here rather than only the condensed one.

WORKFLOW.md now says a re-dispatch "while the branch tip is still the commit
whose push failed", which is also the accurate half, since the build
succeeded and only the push failed, and adds that the dispatch names the
branch rather than the commit. The condensed catalog carries the limit and
the harm together, that a re-dispatch after the tip has moved publishes a
further version and leaves the first release without its package, with the
git-height cause that makes it deterministic rather than merely risky.
version.json declares no pathFilters, so any commit advances height.

Both come from this promotion. #1198 added the failed-push paragraph to
WORKFLOW.md with its caveat and added the condensed restatement without it,
so the authority and the catalog disagreed from the moment they landed.

Whole-unit passes over the two changed units settled the wording, rejecting
an earlier revision at each of an operation the publisher forbids, a relative
clause attached to cleanup rather than to the re-dispatch, a split
correlative, an antecedent-less demonstrative, and a garden path off the
branch tip. The pre-existing defects those passes found in the same units are
filed as #1200 and #1212.
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Clarify D4.5 Package Push Recovery Constraints

📝 Documentation 🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Clarifies package pushes can only be retried while the dispatch branch tip remains unchanged.
• Explains moved tips produce newer NBGV versions and leave original releases incomplete.
• Synchronizes D4.5 guidance across canonical documentation and generated skill copies.
Diagram

graph TD
  A["Package push fails"] --> B["Dispatch branch"] --> C{"Tip unchanged?"}
  C -- "Yes" --> D["Refresh release"] --> E["Retry package push"]
  C -- "No" --> F["Publish newer version"] --> G["Original stays incomplete"]
Loading
High-Level Assessment

Correcting the contract documentation and all synchronized copies is the appropriate approach. Extending the publisher with an explicit commit-recovery input was considered, but that would materially change the workflow’s branch gate and publishing security model rather than fix the inaccurate operational guidance.

Files changed (6) +13 / -13

Other (6) +13 / -13
d-guarantees.mdBound condensed D4.5 recovery to an unchanged branch tip +1/-1

Bound condensed D4.5 recovery to an unchanged branch tip

• Replaces the unsupported same-commit dispatch instruction with the actual branch-based recovery constraint. It also documents how NBGV git height causes a moved tip to publish a newer version while leaving the original release incomplete.

.agents/skills/workflow-ci-contract/references/d-guarantees.md

.source-digestRefresh the fleet skill source digest +1/-1

Refresh the fleet skill source digest

• Updates the generated source digest to reflect the synchronized workflow contract content.

.claude-plugin/fleet-skills/.source-digest

d-guarantees.mdSynchronize corrected D4.5 guidance into the fleet skill +1/-1

Synchronize corrected D4.5 guidance into the fleet skill

• Mirrors the corrected package-push recovery constraint and moved-tip consequences in the generated Claude fleet skill copy.

.claude-plugin/fleet-skills/skills/workflow-ci-contract/references/d-guarantees.md

d-guarantees.mdSynchronize corrected D4.5 guidance into the GitHub skill +1/-1

Synchronize corrected D4.5 guidance into the GitHub skill

• Mirrors the corrected package-push recovery constraint and NBGV versioning behavior in the GitHub skill copy.

.github/skills/workflow-ci-contract/references/d-guarantees.md

WORKFLOW.mdDescribe an executable branch-based package recovery +1/-1

Describe an executable branch-based package recovery

• Clarifies that recovery dispatches the branch while its tip still matches the failed push’s commit, rather than dispatching a commit SHA. Retains the warning that a moved tip builds a newer version and cannot repair the original release.

WORKFLOW.md

canonical-review.jsonRefresh canonical review evidence for revised D4.5 units +8/-8

Refresh canonical review evidence for revised D4.5 units

• Updates digests, finding counts, hub commits, and timestamps for the reviewed workflow contract and condensed D4 guarantee units.

reports/canonical-review.json

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: e632c53f-4efc-444c-bd92-760730948d7e

📥 Commits

Reviewing files that changed from the base of the PR and between 7ab81fe and 5b9f307.

📒 Files selected for processing (2)
  • WORKFLOW.md
  • reports/canonical-review.json

Included review availability: Your plan provides up to 8 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The change clarifies D4.5 package-push recovery. An unchanged branch tip repairs the existing release. A moved tip creates a newer version. Related workflow references, source metadata, and canonical review records are updated.

Changes

Release and publish contract

Layer / File(s) Summary
Recovery contract and review metadata
.agents/skills/workflow-ci-contract/references/d-guarantees.md, .claude-plugin/fleet-skills/skills/workflow-ci-contract/references/d-guarantees.md, .github/skills/workflow-ci-contract/references/d-guarantees.md, WORKFLOW.md, reports/canonical-review.json, .claude-plugin/fleet-skills/.source-digest
D4.5 states that re-dispatch repairs a failed package push only when the branch tip is unchanged. A moved tip publishes a newer version and leaves the original release without its package. Related review records and the source digest are refreshed.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Merge Risk: ⚪ Minimal · up to 5b9f3

The PR corrects recovery guidance so failed package pushes are re-dispatched from the unchanged branch tip rather than an unsupported commit reference. No actionable merge-blocking risk remains; it is merge-ready after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: defining a recovery that a dispatch can perform for D4.5. It is specific, concise, and related to the documentation updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/d45-recovery-bound

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The updated D4.5 recovery sentence in WORKFLOW.md can still be misread as “dispatch a commit SHA,” so the actionable branch-ref requirement should be stated more explicitly to fully resolve the original finding.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates the D4.5 documentation contract so the “failed package push” recovery describes a workflow_dispatch rerun that a maintainer can actually perform, and propagates the corrected wording across the carried guarantee catalogs and canonical-review ledger.

Changes:

  • Refines WORKFLOW.md D4.5 recovery wording to bound re-dispatch recovery to when the branch tip still points at the failed-push commit.
  • Updates the D4.5 condensed restatement in the workflow CI contract’s d-guarantees.md across source and generated distributions.
  • Refreshes reports/canonical-review.json digests/findings metadata for the touched units, plus the fleet-skills source digest.
File summaries
File Description
WORKFLOW.md Adjusts D4.5 prose to describe a dispatch recovery that depends on the branch tip not advancing.
.agents/skills/workflow-ci-contract/references/d-guarantees.md Updates the condensed D4.5 guarantee summary to match the corrected recovery bound.
.github/skills/workflow-ci-contract/references/d-guarantees.md Regenerates the distributed copy of the condensed D4.5 guarantee.
.claude-plugin/fleet-skills/skills/workflow-ci-contract/references/d-guarantees.md Regenerates the plugin-distributed copy of the condensed D4.5 guarantee.
.claude-plugin/fleet-skills/.source-digest Updates the fleet-skills source digest after regeneration.
reports/canonical-review.json Updates canonical-review digests/stamps/findings counts for the modified units.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread WORKFLOW.md Outdated
Copilot found on #1213 that the recovery wording still foregrounds "commit"
and relegates the actionable constraint, that a dispatch must name a branch
ref rather than a commit SHA, to a trailing clause, where it can reintroduce
the operator mistake the change exists to prevent.

The finding is right and two local passes had already flagged the same
placement as a non-blocking style note. Classifying it that way twice was the
error. The constraint is what stops an operator forming the plan at all, so
its position is a correctness property of the item rather than a matter of
flow.

The passage now runs constraint first, consequence after: a dispatch names a
branch, main or develop per D2.3, and never a commit, so what it builds is
that branch's tip at dispatch time, and a re-dispatch therefore repairs the
failed version only while the tip is still the commit whose push failed.

Copilot's suggested wording used a semicolon, which the fleet's prose rules
forbid, so the content is taken and the punctuation is not.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The updated D4.5 language is consistent with the actual dispatch/ref gate behavior and the change is correctly propagated to all carried/distributed copies and review metadata.

Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@ptr727
ptr727 merged commit 16daf0d into develop Sep 2, 2026
9 checks passed
@ptr727
ptr727 deleted the fix/d45-recovery-bound branch September 2, 2026 21:21
ptr727 added a commit that referenced this pull request Sep 2, 2026
…orkflows Falsify (#1203)

Closes #1152.
Closes #1174.
Closes #1175.
Closes #1176.
Closes #1177.
Closes #1178.

Promotes two commits. The first settles seven `WORKFLOW.md` section 4
contract claims that the workflow files and stubs they govern
contradict. The second fixes what this promotion's own review round then
found.

## What is settled

**A caller cannot address a callee's job.** D1.2 named
`validate-task.yml`'s internal job, and a `workflow_call` callee's jobs
resolve nowhere in a caller, so the name an aggregator `needs:` is
always the caller's own `validate` stub job. The task detects the tree
rather than the language, so a non-.NET repo calls the same one instead
of replacing it.

**The aggregator's dependency list was wrong in two directions.** D1.2
claimed `smoke-build` needs the validation job, an edge no shipped stub
carries, and section 6 repeated it twice. D1.5 required a `needs:` on
the `changes` job unconditionally, which a no-build repo does not have,
so its aggregator would fail to load. D1.5 also never stated `if:
always()`, without which the aggregator inherits `success()` and is
skipped the moment a dependency fails, which GitHub reads as a satisfied
required check.

**The paths filter was described as a negation.** Verified against
picomatch: a lone `!.github/workflows/**` matches every other path, so a
docs-only pull request marks the target and smoke-builds, the opposite
of scenario S2. The stub now carries an inclusion list naming the
target's own paths, satisfying S2 and S3 together.

**The no-asset list named the wrong third shape.** D4.3 disagreed with
the release task's own header, which named "NuGet symbols-only" while
`nuget-build-default` uploads a package-carrying asset. The third shape
is source-only.

**A rejected token exchange can leave a release for a version the
registry never received.** D4.5 promised nothing partial ships and
covered only a failed build. Moving the package push into the publishing
repository's own job put it after `github-release`. The item names that
case and bounds its recovery, since a re-dispatch after the branch tip
has moved builds the new tip, NBGV deriving the version from git height.

**A cleanup step skipped exactly the failure it was written for.** D5.2
described a delete that runs unconditionally while both publish stubs
carried the step with no `if:`, so it inherited `success()`. Both now
carry `if: ${{ !cancelled() && steps.download.outcome == 'success' }}`
with an `id:` on the download.

**Adopting the release chain needs the registry policy repointed.** A
repository that worked around the earlier `HTTP 401` by pointing its
nuget.org policy at `build-release-task.yml` now mismatches from the
other direction, and the adopter-owes list omitted it.

## What this promotion's own review then fixed

#1198 changed section 4's preamble and left three other surfaces stating
the framing it replaced. #1209 settles them, and deliberately asserts no
framing in their place, since D9's items and D6.2 state properties of
committed source rather than any output a run produces:

- `WORKFLOW.md`'s file preamble now routes to section 4's preamble
rather than restating it.
- The `workflow-ci-contract` skill's `description:` names the guarantees
and stops.
- Its pointer sentence names what each reference condenses, which also
supplies an antecedent it lacked, and stops describing
`references/test-methodology.md` as the audit procedure when that file
calls itself an index into `WORKFLOW.md` 5A.

#1209 also adds `global.json` to both paths-filter lists in
`docs/reusable-workflows.md`. D1.6 requires that file of any repository
whose test project is MTP-based, and an adopter copying the example
verbatim skipped the smoke build on a change to it.

#1213 then settles a defect #1198 introduced on both of its D4.5
surfaces at once. The item named a recovery the publisher forbids,
"re-dispatching the same commit", where `workflow_dispatch` accepts a
branch or tag ref rather than a commit SHA, `assert-dispatch-ref` gates
the ref to `main` or `develop`, and the publish job passes `ref: ${{
github.sha }}`. A maintainer following it ran `gh workflow run --ref
<sha>`, got `HTTP 422`, and found the release tag rejected too.
`WORKFLOW.md` now leads with the constraint rather than trailing it,
since a constraint an operator meets after forming the plan does not
stop the plan, and the condensed catalog carries the bound and the harm
together with the git-height cause that makes it deterministic.

## Review

Eight whole-unit rounds on #1198 across thirteen carried canonical
units. Two review rounds on #1203 raising eight findings, and two on
#1209.

Of the eight raised here, three were fixed by #1209, one deferred behind
a filed issue, and four declined with evidence in their threads: the
`WORKFLOW.md`-duplicates-`GOVERNANCE.md` finding against the "Canonical
scope" blockquote that declares the overlap and its precedence rule, the
comment-length finding against the rule's own "several sentences is
several lines" clause and twenty-plus shipped workflows carrying the
shape, the failed-push-recovery finding against #1177's specified shape
and the cost D5.2 and D4.5 now state, and the S9 artifact finding
against D5.2's two artifact families with their two different gates.

## Deliberately not in this promotion

Whole-unit passes found pre-existing defects in every unit they read,
and the second review round on this PR raised seven more that are
pre-existing on `main` rather than introduced here. Each is filed rather
than swept in.

- #1199 through #1202, from #1198's own round. #1199 is the live one,
where `validate-task.yml` runs `pytest --cov-report=xml` with no
`--cov`, so it collects nothing and writes no `coverage.xml` while the
upload step stays green. CodeRabbit raised it independently here.
- #1204, S9's narrowing leaves D4.4's dispatch-refresh leg covered by no
scenario in exactly the repositories where a repeated dispatch is the
ordinary way to re-cut a release.
- #1205, #1206, #1207, #1208 and #1212, claims in `WORKFLOW.md`'s
preamble, the skill description, its Core Behavioral Spine, and the
condensed D4 catalog that the documents themselves falsify.
- #1210, canonical-review entries whose `hubCommit` resolves nowhere on
the remote.
- #1211, the documented pull request aggregator accepts a `skipped`
validator where this repository's own workflow requires `success`, so
the canonical stub is weaker than the reference implementation it
documents.
- #1214, D4.5 and D5.2 together imply a failed push is unrecoverable
once the branch tip moves, and neither considers **Re-run all jobs**,
which replays at the run's original `github.sha`. Settling it needs a
real publish against a real registry, which is the maintainer's to run.

Two findings from the second round were declined with evidence rather
than filed: the `enable_<target>` forwarding finding, which is false for
the single-target example the document shows and whose multi-target
pattern is documented in four places, and the S7 cleanup finding, which
section 5's own N/A rule and the per-type walkthroughs already resolve.

Sixteen carried canonical units moved across the two commits, so this
re-vendors fleet-wide and the audit drift wave that follows is the
mechanism working.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Workflow Improvements**
- Manual release dispatches now refresh existing releases instead of
skipping them.
  - Scheduled and push reruns avoid unnecessary republishing.
- Validation, dependency handling, release gating, and partial-failure
behavior are more consistent.
- Artifact cleanup now occurs only when artifacts are no longer needed.

- **Documentation**
- Clarified release assets, trusted publishing requirements, workflow
paths, and rerun behavior.
- Expanded guidance for NuGet, PyPI, Docker, and source-only release
scenarios.
  - Improved workflow governance and review guidance.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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.

2 participants