From 7479b5c4232e98a46d1119ccc6700ac5b3943298 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 31 Jul 2026 20:23:15 -0700 Subject: [PATCH 1/4] Choose the version floor at standup instead of inheriting it Step 2 lists version.json among the files a new repo carries and says nothing about the number inside it, so the file arrives with a floor that describes someone else's release history. WORKFLOW.md D3.3 makes that field the repo's own major.minor floor with NBGV appending the git height as the patch, which means a carried floor is a claim the new repo cannot support. Four operational config repos run on a floor none of them chose, and each has released against it: HomeAutomation-Config at 2.0.14, ESPHome-Config at 2.0.60, HomeAssistant-Config at 2.0.23, and Vantage-Config at 2.0.13. The repos that were versioned deliberately show the rule already exists in practice and only lacked a statement. A project with history keeps its scheme, as Utilities at 4.0, PlexCleaner at 3.22, NxWitness at 2.15, LanguageTags at 1.5, ESPHome-NonRoot at 1.9 and VSCode-Server-DotNetCore at 1.1 all do, and a new project starts at 1.0, as aiopurpleair, MediaTools, PhotoCleaner and homeassistant-purpleair do, or at 0.1 while it is pre-release, as Financial-Modeling does. Step 2 now states the three cases and requires the floor to be set before the first release. It also states the case that produced the four, which is a repo shipping no package: an operational or source-only repo still releases a tag and a source archive, so having no consumer is not a reason to leave the carried number alone. The step is placed with the decision rather than with the repair because the decision is one-way. Once a repo publishes against a floor, lowering it regresses the released version order, so the four keep the floor they have. The rule stays hub-only. WORKFLOW.md D3.3 already defines what the field means and is carried fleet-wide, and how a floor is chosen the first time is standup work rather than a fact any downstream repo re-reads. Co-Authored-By: Claude Opus 5 (1M context) --- STANDUP.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/STANDUP.md b/STANDUP.md index 5602d1fa..def12dae 100644 --- a/STANDUP.md +++ b/STANDUP.md @@ -57,6 +57,14 @@ Then **read** `CODESTYLE.md` and the `GOVERNANCE.md` documentation-style rules, Copy every [`spec/files.json`][files] entry whose `appliesTo` matches the repo's **selector set**, **adapted, not cloned**. The selector set is the repo's `types` plus its `workflowModel`, `releaseTrigger`, and `consumerModel`, so filtering on type alone silently drops the entries a non-type selector carries ([`spec/scope-model.md`][scope-model] defines the four namespaces and how they resolve). The prose files (`CODESTYLE.md`, `README.md`, and the like) describe the repo's own toolchain, so adapt them to reality rather than propagating template specifics verbatim (see the "Adapt before propagating" callout in [`CODESTYLE.md`][codestyle], since a verbatim copy that misdescribes the repo is rejected in review). The baseline covers `WORKFLOW.md`, `version.json`, the two rulesets, `.github/dependabot.yml`, `.editorconfig`, `.gitattributes`, the linter configs, and the per-type files (`.vscode/tasks.json` from the language's snippet, `codecov.yml`, `.dockerignore`, `Docker/README.md`). **Every repo carries `repo-config/main.json`**, and only the `develop` payload varies by workflow model: `repo-config/develop.json` for a release repo, `repo-config/operational/develop.json` for an operational one. +**`version.json` is a file to carry and a floor to choose.** [`WORKFLOW.md`][workflow] D3.3 makes its `version` field the repo's own major.minor floor, with NBGV appending the git height as the patch, so the number carried in with the file is a claim about a release history the new repo does not have. Set it deliberately, at standup, before the first release: + +- **A new project starts at `1.0`**, or at `0.1` while it is deliberately pre-release and its consumers are told so. +- **A project with releases behind it keeps its established scheme**, adapted to NBGV rather than restarted. Put the floor at or above the highest version already published, because NBGV derives the patch from the git height and a floor under an existing tag emits versions that sort backwards. +- **A repo that ships no package still chooses.** An operational or source-only repo releases a tag and a source archive, which is a published version like any other, so "nothing consumes it" is not a reason to leave the carried number in place. + +**This decision is effectively one-way, which is why it belongs here.** Once a repo publishes against a floor, lowering it regresses the released version order, so a floor that was never chosen is kept rather than corrected. Inherited floors are the observed failure, not a hypothetical one: four operational config repos run on a floor none of them picked and have released against it. + **Repo-specific content has a declared destination, not a judgment call.** The baseline is what a repo *carries*. Anything the repo knows that the fleet does not needs somewhere to live, and improvising a location per repo is what the destinations in [`spec/section-model.md`][section-model] exist to prevent. Three topical docs take it, chosen by what the content **is**: - [`CODESTYLE.md`][codestyle]: the repo's language and formatting conventions beyond the carried rules. From c8679743c8e86dad1098f685b4088032f8c7c2d3 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 31 Jul 2026 20:26:53 -0700 Subject: [PATCH 2/4] State that a version floor cannot resume a patch sequence The continuing-scheme bullet said to put the floor at or above the highest published version. The field carries major.minor only, so "above" a full semver is not expressible, and the wording hid the mechanism that makes the case fail. NBGV counts the patch from the git height rather than from the last published patch, so a floor matching the published major.minor emits a patch counted from that floor's first commit. Wherever the published patch ran ahead of the height, the computed version lands under an existing tag. The bullet now says to set the floor above the highest published major.minor rather than matching it, and names nbgv get-version as the check that the computed version sorts above the latest tag before the first release. Co-Authored-By: Claude Opus 5 (1M context) --- STANDUP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STANDUP.md b/STANDUP.md index def12dae..5163184e 100644 --- a/STANDUP.md +++ b/STANDUP.md @@ -60,7 +60,7 @@ Copy every [`spec/files.json`][files] entry whose `appliesTo` matches the repo's **`version.json` is a file to carry and a floor to choose.** [`WORKFLOW.md`][workflow] D3.3 makes its `version` field the repo's own major.minor floor, with NBGV appending the git height as the patch, so the number carried in with the file is a claim about a release history the new repo does not have. Set it deliberately, at standup, before the first release: - **A new project starts at `1.0`**, or at `0.1` while it is deliberately pre-release and its consumers are told so. -- **A project with releases behind it keeps its established scheme**, adapted to NBGV rather than restarted. Put the floor at or above the highest version already published, because NBGV derives the patch from the git height and a floor under an existing tag emits versions that sort backwards. +- **A project with releases behind it keeps its established scheme**, adapted to NBGV rather than restarted. The field carries a major.minor floor and NBGV counts the patch from the git height, so it cannot resume a published patch sequence. Set the floor to a major.minor **above** the highest one already published rather than matching it, because a matched floor emits a patch counted from that floor's first commit, which lands under an existing tag whenever the published patch ran ahead of the height. `nbgv get-version` prints the computed version, and it has to sort above the latest tag before the first release. - **A repo that ships no package still chooses.** An operational or source-only repo releases a tag and a source archive, which is a published version like any other, so "nothing consumes it" is not a reason to leave the carried number in place. **This decision is effectively one-way, which is why it belongs here.** Once a repo publishes against a floor, lowering it regresses the released version order, so a floor that was never chosen is kept rather than corrected. Inherited floors are the observed failure, not a hypothetical one: four operational config repos run on a floor none of them picked and have released against it. From ebed0cfdd1f45df07bea05fe0cde3a30615ab977 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 31 Jul 2026 20:30:13 -0700 Subject: [PATCH 3/4] Name the offset rather than calling the sequence unresumable The bullet said NBGV cannot resume a published patch sequence. It does not resume one on its own, but versionHeightOffset shifts the computed height, and homeassistant-purpleair runs with an offset of -1 today, so the claim was an overstatement that the fleet's own audit reports contradict. The mechanism is unchanged and now stated as what it is. NBGV counts the patch from the git height rather than from where the published sequence stopped, so a matched floor lands under an existing tag whenever the published patch ran ahead of the height. Raising the minor stays the recommendation, because it clears the collision and leaves nothing to maintain, and the offset is named as the alternative with its cost rather than left out. Co-Authored-By: Claude Opus 5 (1M context) --- STANDUP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STANDUP.md b/STANDUP.md index 158c5bc6..52a6f2ff 100644 --- a/STANDUP.md +++ b/STANDUP.md @@ -66,7 +66,7 @@ Copy every [`spec/files.json`][files] entry whose `appliesTo` matches the repo's **`version.json` is a file to carry and a floor to choose.** [`WORKFLOW.md`][workflow] D3.3 makes its `version` field the repo's own major.minor floor, with NBGV appending the git height as the patch, so the number carried in with the file is a claim about a release history the new repo does not have. Set it deliberately, at standup, before the first release: - **A new project starts at `1.0`**, or at `0.1` while it is deliberately pre-release and its consumers are told so. -- **A project with releases behind it keeps its established scheme**, adapted to NBGV rather than restarted. The field carries a major.minor floor and NBGV counts the patch from the git height, so it cannot resume a published patch sequence. Set the floor to a major.minor **above** the highest one already published rather than matching it, because a matched floor emits a patch counted from that floor's first commit, which lands under an existing tag whenever the published patch ran ahead of the height. `nbgv get-version` prints the computed version, and it has to sort above the latest tag before the first release. +- **A project with releases behind it keeps its established scheme**, adapted to NBGV rather than restarted. The field carries a major.minor floor and NBGV counts the patch from the git height rather than from where the published sequence stopped, so a floor matching the published major.minor emits a patch counted from that floor's first commit, which lands under an existing tag whenever the published patch ran ahead of the height. Raise the minor above the highest published one, which clears the collision and leaves nothing to maintain. `versionHeightOffset` shifts the height instead, at the cost of an offset the repo carries from then on. Either way `nbgv get-version` prints the computed version, and it has to sort above the latest tag before the first release. - **A repo that ships no package still chooses.** An operational or source-only repo releases a tag and a source archive, which is a published version like any other, so "nothing consumes it" is not a reason to leave the carried number in place. **This decision is effectively one-way, which is why it belongs here.** Once a repo publishes against a floor, lowering it regresses the released version order, so a floor that was never chosen is kept rather than corrected. Inherited floors are the observed failure, not a hypothetical one: four operational config repos run on a floor none of them picked and have released against it. From c01dee407df4bc2787648effb274e8947f465163 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Fri, 31 Jul 2026 20:30:35 -0700 Subject: [PATCH 4/4] Drop the packaging block a non-publishing repo never reads version.json carries nugetPackageVersion, which configures how a NuGet publisher stamps a package version. A repo that publishes no package carries the block anyway, because the file reads as mechanical and invites a straight copy the way .editorconfig does, while its content is a per-repo decision. Step 2 now says to drop it, and states that publicReleaseRefSpec names the repo's own default branch, which D3.2 already requires the gate literal, the prerelease expression and this file to agree on. Raised from the Blog carry (#489, finding 5), whose first half this step already covers. Co-Authored-By: Claude Opus 5 (1M context) --- STANDUP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/STANDUP.md b/STANDUP.md index 52a6f2ff..04794090 100644 --- a/STANDUP.md +++ b/STANDUP.md @@ -68,6 +68,7 @@ Copy every [`spec/files.json`][files] entry whose `appliesTo` matches the repo's - **A new project starts at `1.0`**, or at `0.1` while it is deliberately pre-release and its consumers are told so. - **A project with releases behind it keeps its established scheme**, adapted to NBGV rather than restarted. The field carries a major.minor floor and NBGV counts the patch from the git height rather than from where the published sequence stopped, so a floor matching the published major.minor emits a patch counted from that floor's first commit, which lands under an existing tag whenever the published patch ran ahead of the height. Raise the minor above the highest published one, which clears the collision and leaves nothing to maintain. `versionHeightOffset` shifts the height instead, at the cost of an offset the repo carries from then on. Either way `nbgv get-version` prints the computed version, and it has to sort above the latest tag before the first release. - **A repo that ships no package still chooses.** An operational or source-only repo releases a tag and a source archive, which is a published version like any other, so "nothing consumes it" is not a reason to leave the carried number in place. +- **Carry only the fields the repo uses.** `nugetPackageVersion` is packaging configuration for a NuGet publisher, so a repo that publishes no package drops the block rather than carrying a setting nothing reads. `publicReleaseRefSpec` names the repo's own default branch, which D3.2 requires it to agree with. **This decision is effectively one-way, which is why it belongs here.** Once a repo publishes against a floor, lowering it regresses the released version order, so a floor that was never chosen is kept rather than corrected. Inherited floors are the observed failure, not a hypothetical one: four operational config repos run on a floor none of them picked and have released against it.