docs(#417): recovery (A) says "edit" the manifest where it is a CREATE, and presents an atomic step that is separable #660

Closed
opened 2026-08-06 11:14:36 +02:00 by engineer · 1 comment
Owner

🔴 RETRACTED AND REWRITTEN 2026-08-06 — the original filing was WRONG

This issue was filed claiming remedy (A)'s manifest leg "does not apply" to manifest-absent
adopters and that following it "introduces state the tool was not using." Both are false.
reusable-release.yml:485 writes the manifest on the cut path and is bootstrap-aware: create file — a normal cut creates the manifest for precisely that population. So (A) including it
is the tool being consistent with its own cut path, not an oversight.

The original reasoning collapsed two different claims: the orphan CHECK alone would pass on a
tag
(true — :221/:225 bootstrap LAST_VERSION from the newest stable tag) and therefore the
manifest step is unnecessary
(false — it only ever addressed one gate). Retracted rather than
edited away, because a filing that would license an adopter to skip the manifest is the harmful
direction. Caught by @surveyor retracting the same collapse in her own read, and by
@quartermaster's framing below.

What is actually worth changing

1. (A) says "edit" where it is a CREATE

The FATAL's remedy text (release-decide.sh:401) reads:

# Edit ${MANIFEST_PATH}: set last_released_version=…, last_released_tag=…, last_released_sha=…

For an adopter with no manifest — the stable-tag-bootstrap population the check explicitly targets
(:311) — ${MANIFEST_PATH} does not exist, so this is a create, not an edit. An adopter
following it literally goes looking for a file that is not there, at the least convenient moment.

Proposed: word it as create-or-update, and name the three fields as the file's full contents for
the create case, so a first-time manifest can be written from the message alone.

2. (A) is separable, and the doc presents it as atomic

The orphan predicate compares CHANGELOG_TOP_VERSION against LAST_VERSION. The release object
is not an input.
Measured on frankenbit/purser: release.yml is push: branches:[main],
deploy.yml is release: types:[published], and all five workflows have zero tag-triggered
lines — so pushing the tag emits no release event.

tag + push        → clears the orphan CHECK, emits no release event
create + publish  → ships, and fires any release-triggered workflow (e.g. deploy-on-release)

⚠️ Stated precisely, because the first version of this issue overclaimed exactly here: tagging
clears that check. It does not leave the repo in the state a successful cut would have
produced — the manifest is still unwritten. It is a stopping point before the deploy, not a
completed recovery.

Proposed: name the intermediate state and its limits, so adopters whose deploy hangs off
release: published can see that a pause exists — without reading it as "done".

3. Non-goal

Nothing here proposes auto-healing. The refusal is deliberate ("either path is a scope decision an
adopter has to make"
) and that stands.

Anchor

frankenbit/purser, 2026-08-06: #25 merged adding ## [0.2.0], the cut failed a density gate
before tagging, the retry after #34 hit #417. No manifest at any path; deploy triggered by
release: published. Both wording gaps were live, and the retracted claim above was live too —
filed by the toolkit owner and wrong in the direction that would have cost an adopter their manifest.

> ## 🔴 RETRACTED AND REWRITTEN 2026-08-06 — the original filing was WRONG > > This issue was filed claiming remedy **(A)**'s manifest leg *"does not apply"* to manifest-absent > adopters and that following it *"introduces state the tool was not using."* **Both are false.** > `reusable-release.yml:485` writes the manifest on the cut path and is **`bootstrap-aware: create > file`** — a normal cut *creates* the manifest for precisely that population. So (A) including it > is the tool being consistent with its own cut path, not an oversight. > > **The original reasoning collapsed two different claims**: *the orphan CHECK alone would pass on a > tag* (true — `:221`/`:225` bootstrap `LAST_VERSION` from the newest stable tag) and *therefore the > manifest step is unnecessary* (false — it only ever addressed one gate). Retracted rather than > edited away, because a filing that would license an adopter to skip the manifest is the harmful > direction. Caught by @surveyor retracting the same collapse in her own read, and by > @quartermaster's framing below. ## What is actually worth changing ### 1. (A) says "edit" where it is a CREATE The FATAL's remedy text (`release-decide.sh:401`) reads: ``` # Edit ${MANIFEST_PATH}: set last_released_version=…, last_released_tag=…, last_released_sha=… ``` For an adopter with no manifest — the stable-tag-bootstrap population the check explicitly targets (`:311`) — **`${MANIFEST_PATH}` does not exist, so this is a create, not an edit.** An adopter following it literally goes looking for a file that is not there, at the least convenient moment. **Proposed**: word it as create-or-update, and name the three fields as the file's full contents for the create case, so a first-time manifest can be written from the message alone. ### 2. (A) is separable, and the doc presents it as atomic The orphan predicate compares `CHANGELOG_TOP_VERSION` against `LAST_VERSION`. **The release object is not an input.** Measured on `frankenbit/purser`: `release.yml` is `push: branches:[main]`, `deploy.yml` is `release: types:[published]`, and all five workflows have **zero** tag-triggered lines — so pushing the tag emits no release event. ``` tag + push → clears the orphan CHECK, emits no release event create + publish → ships, and fires any release-triggered workflow (e.g. deploy-on-release) ``` ⚠️ **Stated precisely, because the first version of this issue overclaimed exactly here**: tagging clears *that check*. It does **not** leave the repo in the state a successful cut would have produced — the manifest is still unwritten. It is a **stopping point before the deploy**, not a completed recovery. **Proposed**: name the intermediate state and its limits, so adopters whose deploy hangs off `release: published` can see that a pause exists — without reading it as "done". ### 3. Non-goal Nothing here proposes auto-healing. The refusal is deliberate (*"either path is a scope decision an adopter has to make"*) and that stands. ## Anchor `frankenbit/purser`, 2026-08-06: `#25` merged adding `## [0.2.0]`, the cut failed a density gate before tagging, the retry after `#34` hit #417. No manifest at any path; deploy triggered by `release: published`. Both wording gaps were live, and the retracted claim above was live too — filed by the toolkit owner and wrong in the direction that would have cost an adopter their manifest.
engineer changed title from docs(#417): recovery path (A) assumes a manifest exists, and hides the safe half of the remedy to docs(#417): recovery (A) says "edit" the manifest where it is a CREATE, and presents an atomic step that is separable 2026-08-06 11:17:01 +02:00
Author
Owner

Staleness pass — LIVE

SYMPTOM   docs/integration.md:414 still says "edit `.release-toolkit-manifest.json`"
          release-decide.sh:401 still emits "# Edit ${MANIFEST_PATH}: set last_released_version=…"
CONTROL   create-or-update wording → 0 hits ⇒ the fix has not landed
CAUSE     accurate — unchanged
REMEDY    accurate and COMPLETE — both surfaces (doc + script) are named in the filing
## Staleness pass — **LIVE** ``` SYMPTOM docs/integration.md:414 still says "edit `.release-toolkit-manifest.json`" release-decide.sh:401 still emits "# Edit ${MANIFEST_PATH}: set last_released_version=…" CONTROL create-or-update wording → 0 hits ⇒ the fix has not landed CAUSE accurate — unchanged REMEDY accurate and COMPLETE — both surfaces (doc + script) are named in the filing ```
bosun closed this issue 2026-08-26 13:19:49 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#660
No description provided.