Files
tiny-pattern-ts/development/workflow.md
T
tmu f6f820a648 📝 Require a changelog note before finishing a branch
A merged branch must carry a final commit adding a short summary of the
work under [Unreleased] in CHANGELOG.md. create:release derives the bump
heuristic from that body, so notes have to exist before release day;
rationale in development/workflow.md.
2026-09-15 22:08:08 +00:00

6.8 KiB
Raw Blame History

Workflow

How work moves through the repository. The rules are in CONTRIBUTING.md; this file records why they are shaped the way they are.

Branching model

The model is GitHub Flow (single-developer); the steps are in CONTRIBUTING.md § Branching model. Context behind it: Gitea has no collaborative review UI in use, so it is the lab, and the project moves to GitHub once it is tested and ready.

Decision (2026-09)

Work is opened and closed by create:branch / create:finish, not by prose plus hand-written git.

Why

  • The preconditions were prose, and prose rots: a rule nobody checks is a suggestion. A script asserts, then acts, so the branch or merge only exists if the assertions passed.
  • Type-driven work is only trustworthy if the baseline was green before the first edit. Cheap checks run first and npm run test last, so the expensive gate is not paid on an ineligible tree.
  • The merge half owns the post-merge npm run verify, so a merge cannot land unverified. The push stays with create:release so the merge is reviewed locally first.
  • Every failure is non-mutating except the baseline test, which runs on main after switching there: a red main restores the branch you started on, and a merge conflict aborts back to the feature branch rather than stranding a half-merged main.

Rejected

  • Hand-written git switch -c / git merge: same rules, no enforcement.
  • Reusing pubv's preflight for create:branch: release-shaped, third-party, and it would pay for a build and pack a new branch has no use for.
  • Leaving the merge to reviewer judgment: that judgment moved earlier, to the handover review before create:finish, rather than living in a command anyone can run from a dirty tree.
  • Fast-forward instead of --no-ff: --no-ff keeps each unit of work visible in git log.

Known issue

  • create:finish does not push, so main is ahead of origin/main between a merge and the next push. create:branch requires main to match its upstream and refuses until it is pushed; push main before starting the next branch.

Changelog notes

The rule is in CONTRIBUTING.md § Rules the tools don't enforce.

Decision (2026-09)

A merged branch carries its own summary under [Unreleased] in CHANGELOG.md, added before create:finish; create:release graduates it into the tagged section (see publishing.md).

Why

  • create:release derives the bump heuristic from the [Unreleased] body, so the notes must exist before release day.
  • The contributor has fresh context; at release day the intent of a branch is only its diff.
  • Gitmoji subjects are signposts, not semantic keys, so notes cannot be derived from the history.

Rejected

  • Generating notes from subjects at release time: subjects carry no parseable type/scope (see § Commit messages).
  • The maintainer writing one summary during create:release: reconstruction after the fact.
  • Enforcing it in create:finish: the front doors assert git state, not content — and notable is exactly the judgment a tool cannot make.

Script prefix convention

The prefix taxonomy is the rule, and it lives in CONTRIBUTING.md § Script prefix convention. The design behind it: bare scripts are the tier entry points — a single tool (build, clean) or an aggregator of a prefix:* family (check, fix, test, watch, maintain, setup) — while verify composes check + test:unit into the whole-project gate (it uses test:unit, not test, because check already runs check:tsc).

Decision (2026-09)

create: is the prefix for workflow front doors, with no bare create aggregator.

Why

  • Both members create something real: a branch, a release.
  • It joined both lists in CONTRIBUTING.md alongside its first members, so it could not go invisible the way the retired use: prefix did.
  • publish:* already set the precedent for a prefix without an aggregator.

Rejected

  • run: / perform:: they mean only "do the named thing", so every script fits and the taxonomy collapses.
  • git:: names the tool, not the lifecycle moment, and implies passthrough aliases.
  • start:: describes the branch half, not the release.
  • cut:: idiomatic but needs VCS slang to decode.
  • flow:: overloaded in a type-level matching library.
  • The existing families: check:* is read-only (CI would run a state-mutating command), fix:* reviews as a diff not a branch, maintain:* is advisory and never a gate.

Feedback tiers

The table and invocation rules are in CONTRIBUTING.md § Feedback tiers; this section explains the split.

Decision (2026-09)

Fast, offline, staged-file checks sit in pre-commit; whole-project test runs in pre-push and verify; slow or network-bound scans under maintain.

Why

  • watch:* runs until killed, in its own pane, so it is the earliest tier, firing on save before staging or commit.
  • check:tsc / check:oxlint / check:oxfmt / check:cspell are fast (~0.2–0.5s each), offline, and scope to staged files via LEFTHOOK_FILES, so pre-commit gives instant feedback on what you typed.
  • test (and its tsc) runs the whole suite over the whole project, and the staged-file convention does not apply to the test runner, so it belongs in pre-push, after the commits exist but before the push leaves the machine.

Rejected

  • maintain:* in check or pre-commit: advisory, whole-project and network-bound scans are not correctness gates and would slow the fast tier.
  • Treating a green pre-commit as the definition of done: it sees only staged files, hence npm run verify.
  • A separate git push hook for verify: the pre-push test tier already covers it.

Commit messages

The convention is in CONTRIBUTING.md § Commit messages. Examples: :sparkles: Add watch tier with watch:test child, :recycle: Move type-aware config to .oxlintrc.json; use source-level disable directives, :memo: Restore unique maintainer content as CONTRIBUTING.md. The body explains what and why, not how; link issues with Resolves #....

Decision (2026-09)

Gitmoji subjects, imperative mood, wrapped 50/72, not Conventional Commits.

Why

  • The history is gitmoji and predates any commit-lint tooling; switching would rewrite the convention for no gain.
  • The body carries the reasoning a reviewer needs; the subject is a signpost, not a semantic key.

Rejected

  • Conventional Commits: the release flow uses hand-written Keep-a-Changelog notes, not generated ones, so the prefix has no automation value here (see publishing.md).