Process: enforce SemVer tag on arch/requirements-change commits #5

Open
opened 2026-06-08 13:51:01 +00:00 by mathias · 0 comments
Owner

Problem

The standing rule (workspace CLAUDE.md behavior rules + agent memory
feedback_semver_every_req_arch_change): tag + bump SemVer on every
requirements/architecture change, docs in the same commit, for the audit
trail.
It is not being followed and nothing enforces it.

Evidence: at the v0.8.0 work, the repo was v0.7.0 + 49 untagged commits,
several of them architecture changes. The recency-window arch change (ADR-020)
landed across multiple commits with the ADR batched at the end and no tag
caught only on review, then corrected by tagging v0.8.0 after the fact.

Root cause (process, not code)

Observed drift was treated as license: "the repo already has 49 untagged
commits, so per-change tagging isn't the practice here." That inverts the rule —
the untagged backlog is a symptom of the rule being violated, not permission
to keep violating it. There is no mechanism that makes the omission visible at
commit time.

What "fixed" looks like

An arch/requirements-change commit cannot land green without a corresponding
SemVer tag + its ADR in the same commit.

Proposed options (pick one, smallest that works)

  1. Definition-of-done gate in task check — fail if HEAD touches
    DECISIONS.md (new ## ADR- heading) or declared requirements but git describe --exact-match finds no tag on it. Cheap, local, catches the common
    case (ADR == arch change).
  2. commit-msg / pre-push hook — on a commit that adds an ADR, require a
    vX.Y.Z tag pointing at it (or a Release: vX.Y.Z trailer) before push.
  3. task release target — one command that bumps, tags, and writes the
    changelog, so tagging is the path of least resistance instead of an extra
    manual step. Pair with (1) as the backstop.

Scope

The rule is workspace-global (every repo, every harness). If the chosen check
works here, promote it to the shared mathias/skills library (e.g. the
gitea-ci skill or a new release-discipline skill) so every repo inherits it,
rather than re-implementing per repo.

Also

  • Backfill: there are 49 commits between v0.7.0 and v0.8.0 — decide whether
    any intermediate arch changes warrant retroactive annotated tags or whether
    v0.8.0 absorbs them (it currently does).
  • CLAUDE.md "Current build state" drifts (cited v0.4.0 at v0.8.0); a check
    that asserts the cited tag == latest tag would stop that too.

Filed after the v0.8.0 review surfaced the miss.

## Problem The standing rule (workspace `CLAUDE.md` behavior rules + agent memory `feedback_semver_every_req_arch_change`): **tag + bump SemVer on every requirements/architecture change, docs in the same commit, for the audit trail.** It is not being followed and nothing enforces it. Evidence: at the v0.8.0 work, the repo was `v0.7.0` + **49 untagged commits**, several of them architecture changes. The recency-window arch change (ADR-020) landed across multiple commits with the ADR batched at the end and **no tag** — caught only on review, then corrected by tagging `v0.8.0` after the fact. ## Root cause (process, not code) Observed drift was treated as license: "the repo already has 49 untagged commits, so per-change tagging isn't the practice here." That inverts the rule — the untagged backlog is a *symptom of the rule being violated*, not permission to keep violating it. There is no mechanism that makes the omission visible at commit time. ## What "fixed" looks like An arch/requirements-change commit cannot land green without a corresponding SemVer tag + its ADR in the same commit. ## Proposed options (pick one, smallest that works) 1. **Definition-of-done gate in `task check`** — fail if `HEAD` touches `DECISIONS.md` (new `## ADR-` heading) or declared requirements but `git describe --exact-match` finds no tag on it. Cheap, local, catches the common case (ADR == arch change). 2. **commit-msg / pre-push hook** — on a commit that adds an ADR, require a `vX.Y.Z` tag pointing at it (or a `Release: vX.Y.Z` trailer) before push. 3. **`task release` target** — one command that bumps, tags, and writes the changelog, so tagging is the path of least resistance instead of an extra manual step. Pair with (1) as the backstop. ## Scope The rule is workspace-global (every repo, every harness). If the chosen check works here, **promote it to the shared `mathias/skills` library** (e.g. the `gitea-ci` skill or a new `release-discipline` skill) so every repo inherits it, rather than re-implementing per repo. ## Also - Backfill: there are 49 commits between `v0.7.0` and `v0.8.0` — decide whether any intermediate arch changes warrant retroactive annotated tags or whether `v0.8.0` absorbs them (it currently does). - `CLAUDE.md` "Current build state" drifts (cited `v0.4.0` at `v0.8.0`); a check that asserts the cited tag == latest tag would stop that too. _Filed after the v0.8.0 review surfaced the miss._
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/tapir#5