Choose the version floor at standup instead of inheriting it - #488
Conversation
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) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates the standup procedure to require choosing an explicit version.json major.minor floor during repository bootstrap, rather than inheriting the carried template value, to prevent accidental version histories and backward-sorting releases in newly created repos.
Changes:
- Adds standup guidance clarifying that
version.jsonis both carried and must be deliberately set before the first release. - Documents three scenarios for selecting the floor (new project, existing release history, no-package/operational repos).
- Notes that floors become effectively one-way once releases exist, so prevention belongs in standup guidance.
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) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
STANDUP.md:63
- The sentence "so it cannot resume a published patch sequence" is overly absolute. The repo’s own audit reports note cases where
versionHeightOffsetis used (e.g.,reports/homeassistant-purpleair/audit.md:41), so while NBGV doesn’t automatically continue an old patch sequence, it’s not strictly impossible to align/avoid regressions via configuration + verification. Suggest softening the claim to avoid a factual overstatement.
- **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.
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) <noreply@anthropic.com>
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) <noreply@anthropic.com>
|
Answering the suppressed finding from round 2, since it reaches no thread to resolve. Accepted, and the claim was wrong. Fixed in Also in this round, |
…oor-bootstrap # Conflicts: # STANDUP.md
…to main (#498) Promotes eight commits from `develop`. Every one traces to a defect found in use rather than to a planned change, and five came from downstream agents reporting what the procedure did not cover. ## What lands | Commit | Change | | --- | --- | | `a0f6f24` (#487) | `docs/content-import.md`, the three capture-pass findings from the Blog migration: an export is not a media capture, a sitemap is not the URL contract, and an HTTP fetch is not the original | | `8bdfa22` (#494) | The write-guard scopes by **owner** rather than exact origin, with `GH_WRITE_GUARD_ALLOW` for a different owner. Four target-flag spellings that silently bypassed rule 3 are closed | | `981d92f` (#492) | The purpose is restated as agent enablement, in `README.md`, `HISTORY.md` and `AGENTS.md` | | `275705b` (#493) | `TODO.md` becomes the fleet backlog destination, and `spec/readme-structure.md` stops mandating the construction `GOVERNANCE.md` bans | | `b6ab6db` (#491) | `STANDUP.md` step 0A names the maintainer-only prerequisites, and step 4 asserts the remote | | `89e3868` (#488) | The `version.json` floor is chosen at standup rather than inherited | | `eed2e00` (#495) | `README.md` gains "What It Achieves", the objectives and the fidelity ladder | | `f6dc5e6` (#497) | `CODESTYLE.md` stops claiming CI runs the same checks as the clean-compile | ## Provenance Five of the eight answer issues filed by downstream agents: #456 (Blog intake), #489 and #490 (the Blog carry), and #496 (Financial-Modeling). That loop is the one "What It Achieves" now describes, and this promotion is it closing. ## Divergence, checked rather than assumed `main...develop` reports `8 ahead, 102 behind, diverged`. **The 102 are topology, not content.** They are 79 promotion merge commits, which are main-only by construction because a promotion is a two-parent merge, plus 23 `Update codegen files` bot commits from this repo's pre-2.0 life as a .NET sample template. `git diff --name-status origin/develop origin/main` returns exactly the 12 files these 8 commits touch, so there is **no main-only content** to reconcile. ## Verification on the merged `develop` Every gate re-run after the last merge, not inherited from the individual PRs: - `prose_lint.py . --check charset --check dupword --check spelling` clean tree-wide. - `repo_gate.py` clean (`eol`, `sha-pin`). - `spec/validate.py` clean, 21 cataloged repos classify. - `gh-write-guard.py --selftest` passes, including the nine new repository-scope cases. - `python3 -m unittest discover -s scripts`, 180 tests pass. - The `README.md` objectives list verified as one continuous list of 8 bullets with the fidelity table nested, since an unindented table split it in review. ## Merge mechanics This is a promotion, so it merges as a **merge commit** with two parents, never a squash. Its head **is** `develop`, so `--delete-branch` must not be used. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
STANDUP.mdstep 2 listsversion.jsonamong the files a new repo carries and says nothing about the number inside it, so the file arrives carrying a floor that describes a release history the new repo does not have.WORKFLOW.mdD3.3 makes that field the repo's own major.minor floor with NBGV appending the git height as the patch, so the carried value is a claim, not a default.The failure is observed, not hypothetical
Four operational config repos run on a floor none of them chose, and each has already released against it:
The repos versioned deliberately show the rule already exists in practice and only lacked a statement. A project with history keeps its scheme (Utilities 4.0, PlexCleaner 3.22, NxWitness 2.15, LanguageTags 1.5, ESPHome-NonRoot 1.9, VSCode-Server-DotNetCore 1.1), and a new project starts at 1.0 (aiopurpleair, MediaTools, PhotoCleaner, homeassistant-purpleair) or at 0.1 while pre-release (Financial-Modeling). Whether a repo got this right depended on who stood it up.
What lands
Step 2 gains the three cases and requires the floor to be set before the first release:
1.0, or0.1while deliberately pre-release.It also records that the decision is effectively one-way. Once a repo publishes against a floor, lowering it regresses the released version order, so the four keep the floor they have and this is prevention rather than a repair procedure.
Scope
Hub-only, and deliberately not in
WORKFLOW.md. D3.3 already defines what the field means and is carried fleet-wide atintentfidelity, so restating the bootstrap rule there would add re-vendor debt for guidance that only ever applies while a repo is being stood up.Two conformance findings surfaced by the same survey are not addressed here, since they are downstream repo changes rather than hub guidance: AudioCleaner and DevKitCIoT carry no
version.jsonat all, whichspec/files.jsonrequires for every repo (appliesTo: "*").Verification
version.jsonand latest release via the GitHub API, so every number above is measured rather than recalled.python3 scripts/prose_lint.py . --diff origin/developclean,STANDUP.mdclean whole.python3 scripts/repo_gate.pyclean, markdownlint-cli2 and editorconfig-checker clean.🤖 Generated with Claude Code