Skip to content

chore: write the release version literals from one command - #47

Merged
hkwuks merged 1 commit into
mainfrom
chore/release-overhead
Sep 22, 2026
Merged

hkwuks merged 1 commit into
mainfrom
chore/release-overhead

Conversation

@hkwuks

@hkwuks hkwuks commented Sep 22, 2026

Copy link
Copy Markdown
Owner

Summary

Cut the mechanical overhead out of a release: write the eight version literals a release has to move from one command, state the ordering rule that keeps the release notes inside the tagged commit, and fail CI on the two release records that could go stale unnoticed.

The literals are one approved version string transcribed into six files — the four host manifests and the two plugin list samples in each README. Seven of the eight are mechanical, and hand-editing them is where a release drifts. The eighth is the CHANGELOG.md section, which stays with the author.

Changes

hooks/release-version <x.y.z> [root] (new) — writes every mechanical literal in a single call: four manifests, and both README samples in both READMEs. It checks before it writes, so a refusal leaves all six files byte-identical, and each staged rewrite is read back with the same reader release-check uses before anything is moved. The Codex and CodeBuddy cachebuster dates come from the run's own date.

It refuses until the CHANGELOG.md section exists. That is deliberate: it is what binds the prose to the same commit as the literals. It never tags, pushes, publishes, or records an approval — RELEASE.md's manual, approved tag step is untouched.

hooks/release-check — two checks that were measured missing:

Gap Measured before
Each README was read with … | head -1, so only the first of its two literals was compared setting README.md:261 to 1.0.7 printed STATUS: pass
Nothing looked at the range between the tagged commit and the pin commit an unrelated file in that range shipped under the pin

Every sample line is now compared, each named by position when it is not the first, and the output lists each literal so a second sample disagreeing with the first is visible rather than averaged away. The pin-window rule allows only the two marketplace catalogs, and exempts TaskFlowDocs/ because task documents are not distributed with the release.

RELEASE.md — states why the CHANGELOG.md section is written before the tag (the tag is what the marketplace sha pins, so the commit it names must carry the notes itself), names the new command in the scope list, and records the pin-window rule in the validation checklist.

hooks/README.md — the hook tree gains release-version.

TaskFlow traceability

  • Task: TaskFlowDocs/achieved/2026-09-21-release-overhead/ (archived in this PR)
  • Todo item: TF-20260919-c41f8a
  • Scope: hooks/release-version, hooks/release-check, hooks/smoke-test, RELEASE.md, hooks/README.md, and the task documents
  • Base branch: main
  • Target repository: hkwuks/TaskFlow (origin)

Verification

  • bash hooks/smoke-test — ALL SMOKE PASSED
  • git diff --check — clean
  • Relevant Skill/plugin validation — bash -n clean on all three changed hooks; the new hook and both changed checks are covered by the smoke suite; no skill or manifest file is touched, so no Skill validation is applicable
  • Results recorded in the TaskFlow Plan — TaskFlowDocs/achieved/2026-09-21-release-overhead/plan.md, ## Verification / Review

Beyond the suite: bash hooks/release-check . reports STATUS: pass on the unmodified repository and lists all nine literal lines; bash hooks/release-version was refused in four ways (no CHANGELOG section, malformed version, no increase, already at target) with the tree verified byte-identical afterwards.

Five mutations, one per new check, each caught by the suite:

Mutation Suite result
readme_versions restricted to the first match, as the old code did FAIL stale second README sample accepted
the pin-window rule's guard forced false FAIL a stray file in the pin window was accepted
"exactly one version key" relaxed to "at least one" FAIL a manifest with two version keys was rewritten
the CHANGELOG-section precondition removed FAIL release-version ran without a CHANGELOG section
the already-at-target refusal removed FAIL a file already at the target version was overwritten silently

Two claims from the Todo entry that measurement did not support

Recorded in the PRD's ## Background / Confirmed Facts and the Plan's ## Change Log, because both changed what was built:

  1. "The release notes live in the commit after the tag." The tagged commits for v1.0.7 (c3c536d) and v1.0.8 (620c6a7) both already carry their CHANGELOG.md sections. The git tag -a annotation is a second copy on the tag object, not a replacement for the first. So there was no procedure change to make — what was missing was RELEASE.md stating the ordering, which is now R4.
  2. "Six fixed literals in seven files." The mechanical literals are eight in six files: four manifests, plus two samples in each of the two READMEs. CHANGELOG.md is the seventh file and stays prose, which the item had right.

Review boundaries

  • No secrets or opaque remote payloads included
  • No unrelated task or user files changed — no version literal in the repository was modified by this PR; the new command was exercised only against fixtures
  • Remote/base assumptions are stated — pushed to origin (hkwuks/TaskFlow), targeting main
  • Known limitations and follow-ups are documented below

Known limitations

  • The pin-window rule ends at the commit that last wrote a marketplace catalog, not at HEAD. Work landing on main after the release is not part of the release, so comparing against HEAD would report every commit since as a stray. A release that writes the catalogs in more than one commit is still covered — the range spans all of them.
  • release-version transcribes and never decides. It refuses a version that is not greater than the current one, so a deliberate re-release of the same number is not expressible; that has not occurred and would need a decision about what it means for the tag.
  • The README.zh-CN.md fixture is a copy of the English one in the smoke suite, so a sample line that exists only in the Chinese README would not be caught by the assertions — the check itself reads both files, so this is a fixture limitation, not a check limitation.

A release moves one approved version string through eight literals in six
files. Seven of the eight are transcription — the four host manifests and the
two `plugin list` samples in each README — and hand-editing them is the step
that drifts. `hooks/release-version X.Y.Z` writes them in one call and checks
before it writes, so a refusal leaves every file byte-identical.

It refuses until the `CHANGELOG.md` section exists. That is the ordering rule
`RELEASE.md` now states: the tag is the immutable artifact the marketplace
`sha` pins, so the commit it names has to carry the release notes itself.

`hooks/release-check` gains two checks that were measured missing:

- Every README sample line is compared, not the first one per file. Reading
  only the first left two literals a release has to move compared by nothing —
  setting `README.md:261` to the previous version still printed
  `STATUS: pass`.
- The range from the tagged commit to the commit that recorded the pin may
  contain only the two marketplace catalogs. Anything else would ship under
  the pin without being in the release commit the tag names. Paths under
  `TaskFlowDocs/` are exempt: task documents are not distributed.

Two claims in the Todo entry did not survive measurement and are corrected in
the PRD rather than implemented: the tagged commits for v1.0.7 and v1.0.8
already carry their `CHANGELOG.md` sections, so "the tag lacks the release
body" was not a defect — what was missing was the stated ordering. The literal
count was eight in six files, not six in seven.

Verified: `bash hooks/smoke-test` ALL SMOKE PASSED; `bash hooks/release-check .`
pass on the unmodified repository; `git diff --check` clean. Five mutations,
one per new check, each caught by the suite.
@hkwuks
hkwuks merged commit 895e102 into main Sep 22, 2026
6 checks passed
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