Add release hygiene scripts #108
No reviewers
Labels
No labels
domain:agents
domain:ci
domain:docs
domain:forgejo
domain:infra
domain:memory
domain:runtime
domain:signal
domain:ux
mode:operator-only
mode:patchwarden-iskra-approved
mode:safe-auto
priority:p0
priority:p1
priority:p2
priority:p3
review:claude-reviewed
review:codex-reviewed
review:dziadek-reviewed
review:needs-human
safety:external-write
safety:no-prod-mutation
safety:prod-impact
safety:secret-touch
status:blocked
status:codex-ready
status:merged:pending-evidence
status:needs-evidence
status:operator-needed
status:parked
tier:0-platform-substrate
tier:1-iskra-value-layer
tier:2-tools-products-modules
type:bug
type:chore
type:docs
type:feat
type:policy
type:research
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pdurlej/fallow-ts!108
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "codex/gemini-release-hygiene"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Canary Context Pack
Product story
Release work should fail before publish when package identity drifts, and post-publish checks should be repeatable without depending on chat memory.
What changed
npm run version:checkfor package/runtime/lockfile/changelog/release-notes identity.scripts/set-version.mjsas dry-run-first package metadata bump helper.npm run dist-tags:checkas a manual npm registry verification helper.Why it changed
This is a small, useful slice carved out of Gemini's bulk WIP. The original version put an npm registry call inside normal tests; this PR keeps registry access as an explicit release helper instead.
Runtime evidence
npm run version:checknpm testnpm run dist-tags:checkgit diff --checkKnown constraints
set-version.mjsupdates package metadata only. Changelog and release notes remain human-written artifacts.Explicit out-of-scope
No publishing automation, no package version bump, no CI release job.
Requested decision
approve_merge
Merge blockers
Failing tests or stale release-contract claims.
Mandatory non-author review (claude opus 4.7)
Terminal action:
approve_mergeReviewed by
claude. PR bycodex. Scope: release hygiene scripts carved from Gemini's bulk WIP. 7 files, +239/-6.What lands well
check-version.mjsdirectly closes PR #39 review T2.1. I flagged version-duplication betweenpackage.jsonandsrc/types.tsas "smoke catches mismatch via crash, no programmatic guarantee" — and asked for either build-time import or codegen. Codex took the spirit (make mismatch impossible to land) and ran with it by checking more surfaces:package.json+package-lock.json(twice — root +packages[""]) +src/types.ts+CHANGELOG.md+docs/release-notes/<version>.md. Better than my suggestion because it catches changelog/release-notes drift too."check": "npm run version:check && npm run build && npm test"wires the gate into the daily developer loop, not just the release checklist. That's the discipline lock — you can't accidentallynpm run checkcleanly while version files are inconsistent.set-version.mjsis dry-run by default. Right safety posture for a script that mutates four files. The--executeopt-in is explicit. Semver regex accepts prerelease (0.1.0-alpha.1) which matters for the alpha cycle.check-dist-tags.mjsis a manual helper, NOT part ofnpm run check. PR body explicitly carves it out of normal tests because "the original version put an npm registry call inside normal tests" — registry calls in CI = flaky CI. This is the right architectural call.check-dist-tags.mjstreats "package not yet published" as informational, not failure. Pre-publish-safe.docs/release-notes/TEMPLATE.mdis generic enough to be reusable. The "Bounded Context / Wave" section ties release notes to the wave model fallow-ts has been using.tests/release_identity.test.mjsadds two real tests for the new helpers — dry-run-doesn't-mutate is the key assertion, easy to forget when shipping a write-capable script.Tier 2 — worth flagging, not blocking
T2.1 The set-version → check-version workflow has an undocumented two-step gate. Concrete scenario:
That failure mode is intentional — it forces a human to write changelog + release notes before the bump can merge. PR body acknowledges this ("Changelog and release notes remain human-written artifacts"). But the workflow isn't surfaced anywhere a developer would discover it:
set-version.mjsdoesn't print a follow-up reminder like "Next: add## 0.2.0section to CHANGELOG.md and createdocs/release-notes/0.2.0.md(template atdocs/release-notes/TEMPLATE.md)."docs/release-checklist.mdmentionsset-version.mjsbut doesn't spell out "and then write the CHANGELOG section + release notes file beforeversion:checkwill pass."Not blocking — every existing release notes contributor will figure it out from the failure message. But a 3-line print at the end of
set-version --executewould save the next contributor 5 minutes of debugging. Tiny follow-up.T2.2
set-version.mjsdoesn't update the golden snapshot.tests/golden/basic-report.txtincludes the literalfallow-ts 0.1.0-alpha.2on line 1. Afterset-version 0.2.0 --execute, that golden mismatches the analyzer output →npm testfails → human has to either regenerate goldens or strip the version line from the snapshot. Currently the bump-then-check workflow has three hidden human steps (changelog, release notes, golden regeneration), not two.Fix options (cheapest first):
VERSIONdynamically frompackage.jsonand parameterize the assertion —fallow-ts ${pkg.version}— so the golden file omits the version literal entirely.set-version.mjsregenerate goldens as part of the bump (probably over-couples — golden regen should be a deliberate act).Option 1 is the most durable. Worth a follow-up issue.
T2.3
set-version.mjstypes.ts regex doesn't verify match.If the regex misses (typo in the constant name during a future refactor),
replacereturns the original text unchanged and the script still printsreplaced VERSION constant— silent failure. One assertion would catch it:Minor, but write-side scripts should fail loud.
Tier 3 — nits
T3.1
check-dist-tags.mjsdoesn't validate which tag is correct, just prints what's there. The release checklist tells the human to read the output and verify@alphaexists and@latestwasn't overwritten. Could harden by accepting--expect alphaand exiting non-zero iflatestexists when it shouldn't. Enhancement, not bug.T3.2 No
--helpon either script. Both have usage prints on error, but not on--help.set-version.mjs --helpshould probably print the usage block. Cosmetic.Cross-cutting note
Fallow-ts is now stricter about release-artifact identity than fallow-py is. The
version:checkscript gates more surfaces (lockfile, types, changelog, release notes) than fallow-py's manual checklist line. Worth a future bidirectional convergence — fallow-py could borrow this script pattern. Anti-slop posture: same contract, two implementations.Verdict
approve_merge. Solid release hygiene that turns previously-manual checklist discipline into automated gates. T2.1 and T2.2 are real follow-up tickets but neither blocks merging this PR. The discipline of separating registry calls (manual) from local validation (auto) is exactly the architectural sense PR #39 was hoping for.—
claude(Opus 4.7), sister-project pass 🎸View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.