From 71130761eb58116fb8746e6180930c00f2ab850b Mon Sep 17 00:00:00 2001 From: fOuttaMyPaint <154358121+TMHSDigital@users.noreply.github.com> Date: Sun, 24 May 2026 13:55:59 -0400 Subject: [PATCH 1/2] feat: decouple STANDARDS_VERSION from meta release VERSION Add STANDARDS_VERSION file (1.10.0) as the single source of truth for the ecosystem standards surface. The drift checker and scaffold now read this file instead of VERSION, so registry additions and other meta-repo releases no longer force a fleet-wide re-stamp. - Add STANDARDS_VERSION at repo root containing 1.10.0 - Update scripts/drift_check/cli.py to read STANDARDS_VERSION - Update scaffold/create-tool.py to stamp from STANDARDS_VERSION - Update standards/versioning.md to define both files and when each moves - Bump VERSION to 1.12.0 Signed-off-by: fOuttaMyPaint <154358121+TMHSDigital@users.noreply.github.com> --- STANDARDS_VERSION | 1 + VERSION | 2 +- scaffold/create-tool.py | 16 ++++++++-------- scripts/drift_check/cli.py | 12 ++++++------ standards/versioning.md | 24 ++++++++++++++++++------ 5 files changed, 34 insertions(+), 21 deletions(-) create mode 100644 STANDARDS_VERSION diff --git a/STANDARDS_VERSION b/STANDARDS_VERSION new file mode 100644 index 0000000..81c871d --- /dev/null +++ b/STANDARDS_VERSION @@ -0,0 +1 @@ +1.10.0 diff --git a/VERSION b/VERSION index 169f19b..0eed1a2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.11.0 \ No newline at end of file +1.12.0 diff --git a/scaffold/create-tool.py b/scaffold/create-tool.py index ae7cc36..1b41d8b 100644 --- a/scaffold/create-tool.py +++ b/scaffold/create-tool.py @@ -20,7 +20,7 @@ TEMPLATES_DIR = Path(__file__).parent / "templates" -VERSION_FILE = Path(__file__).parent.parent / "VERSION" +STANDARDS_VERSION_FILE = Path(__file__).parent.parent / "STANDARDS_VERSION" LICENSE_FILES = { "cc-by-nc-nd-4.0": "CC-BY-NC-ND-4.0", @@ -42,23 +42,23 @@ def slugify(name: str) -> str: def read_standards_version() -> str: - """Read the meta-repo VERSION at generation time. + """Read the meta-repo STANDARDS_VERSION at generation time. New tool repos are pre-aligned with the current standards version, so the - value here is not a runtime decision. If VERSION is missing or unreadable, - fail loudly rather than silently substituting a default - a wrong version - would defeat the drift-checker invariant. + value here is not a runtime decision. If STANDARDS_VERSION is missing or + unreadable, fail loudly rather than silently substituting a default - a + wrong version would defeat the drift-checker invariant. """ try: - raw = VERSION_FILE.read_text(encoding="utf-8").strip() + raw = STANDARDS_VERSION_FILE.read_text(encoding="utf-8").strip() except FileNotFoundError: print( - f"Error: VERSION file not found at {VERSION_FILE}. " + f"Error: STANDARDS_VERSION file not found at {STANDARDS_VERSION_FILE}. " "The scaffold must run from a working copy of Developer-Tools-Directory." ) sys.exit(1) except OSError as e: - print(f"Error: could not read {VERSION_FILE}: {e}") + print(f"Error: could not read {STANDARDS_VERSION_FILE}: {e}") sys.exit(1) if not re.fullmatch(r"\d+\.\d+\.\d+", raw): print( diff --git a/scripts/drift_check/cli.py b/scripts/drift_check/cli.py index 898553e..237a74f 100644 --- a/scripts/drift_check/cli.py +++ b/scripts/drift_check/cli.py @@ -86,19 +86,19 @@ def _find_repo_root() -> Path: - """Walk up from this file to the repo that contains ``VERSION``.""" + """Walk up from this file to the repo that contains ``STANDARDS_VERSION``.""" here = Path(__file__).resolve() for candidate in (here.parent, *here.parents): - if (candidate / "VERSION").is_file(): + if (candidate / "STANDARDS_VERSION").is_file(): return candidate return here.parents[2] def _read_meta_version(repo_root: Path) -> Version: - raw = (repo_root / "VERSION").read_text(encoding="utf-8").strip() + raw = (repo_root / "STANDARDS_VERSION").read_text(encoding="utf-8").strip() v = parse_version(raw) if v is None: - raise SystemExit(f"meta-repo VERSION is not a valid semver: {raw!r}") + raise SystemExit(f"meta-repo STANDARDS_VERSION is not a valid semver: {raw!r}") return v @@ -199,7 +199,7 @@ def build_parser() -> argparse.ArgumentParser: default=None, help=( "path to the meta-repo root for resolving standards/*.md references " - "(defaults to the repo that contains VERSION)" + "(defaults to the repo that contains STANDARDS_VERSION)" ), ) p.add_argument( @@ -355,7 +355,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int: except SystemExit: raise except Exception as exc: # pragma: no cover - defensive - print(f"error: cannot read VERSION: {exc}", file=sys.stderr) + print(f"error: cannot read STANDARDS_VERSION: {exc}", file=sys.stderr) return 2 try: diff --git a/standards/versioning.md b/standards/versioning.md index 5743c5a..2a009b8 100644 --- a/standards/versioning.md +++ b/standards/versioning.md @@ -72,12 +72,24 @@ The release workflow auto-generates release notes grouped by commit type: `CHANGELOG.md` is maintained manually for curated, human-readable release history. It is not auto-generated. -## What a MINOR bump means for ecosystem standards +## Two version files in the meta-repo -The meta-repo's `VERSION` file carries the ecosystem-wide standards version. It follows the same SemVer rules, but each component has a second, standards-specific meaning for tool repos that embed a `standards-version` signal in their agent files. +The meta-repo root contains two separate version files that serve distinct purposes and move independently. -- **MAJOR** (e.g., `1.x.y` → `2.0.0`) — an incompatible change to the standards themselves. New required elements, removed fields, or restructured file conventions that existing tool repos will fail to validate against without re-alignment. -- **MINOR** (e.g., `1.6.x` → `1.7.0`) — ecosystem standards changed in a way that tool repos need to re-align with. Typical triggers: new required elements in agent files, changed frontmatter schemas, new required standards references, restructured validation rules, or new checks in the drift checker that introduce findings for existing tool-repo content. A mechanical rollout session across the tool repos is typically scheduled after a MINOR bump. -- **PATCH** (e.g., `1.7.0` → `1.7.1`) — bug fixes, clarifications, or additions that do not change the standards surface. Tool repos with a PATCH-behind signal are reported as `info` by the drift checker — visible in verbose runs but not blocking CI. +### `VERSION` - meta-repo release version -The drift checker enforces this mapping via the `same-major-minor` signal policy (see `standards/drift-checker.config.json`). Tool repos whose `standards-version` differs from the meta-repo's `VERSION` in MAJOR or MINOR are reported as `error`; PATCH differences are `info`; tool values ahead of meta are `warn` (either an in-flight rollout or a missed meta-repo bump, both worth surfacing). +Tracks the release history of the meta-repo itself (registry additions, scaffold changes, doc updates, new CI workflows). Bumped by `release.yml` on every qualifying push to `main` using the same conventional-commit rules as tool repos. Registry additions (`feat:`) force a MINOR bump here. This number appears in GitHub Releases and the release changelog but has no direct meaning to tool repos. + +### `STANDARDS_VERSION` - ecosystem standards surface version + +Tracks the version of the standards that tool repos are expected to comply with. Tool repos embed this value in their `` markers in CLAUDE.md, AGENTS.md, and ROADMAP.md. The drift checker compares each tool repo's embedded marker against this file, not against `VERSION`. + +`STANDARDS_VERSION` moves **only** when the standards surface actually changes in a way that requires tool repos to update: + +- **MAJOR** (e.g., `1.x.y` to `2.0.0`) - an incompatible change to the standards themselves. New required elements, removed fields, or restructured file conventions that existing tool repos will fail to validate against without re-alignment. +- **MINOR** (e.g., `1.6.x` to `1.7.0`) - standards changed in a way that tool repos need to re-align with. Typical triggers: new required elements in agent files, changed frontmatter schemas, new required standards references, restructured validation rules, or new checks in the drift checker that introduce findings for existing tool-repo content. A fleet-wide re-stamp session is typically scheduled after a MINOR bump. +- **PATCH** (e.g., `1.7.0` to `1.7.1`) - clarifications or additions that do not change the standards surface. Tool repos with a PATCH-behind marker are reported as `info` by the drift checker - visible in verbose runs but not blocking CI. + +Registry-only changes, scaffold improvements, docs additions, and other meta-repo work that does not change what tool repos are required to contain **do not** bump `STANDARDS_VERSION`, even if they bump `VERSION`. + +The drift checker enforces this mapping via the `same-major-minor` signal policy (see `standards/drift-checker.config.json`). Tool repos whose `standards-version` marker differs from `STANDARDS_VERSION` in MAJOR or MINOR are reported as `error`; PATCH differences are `info`; tool values ahead of meta are `warn`. From ae1cd2326871e325a98f454ec41f9fa9e8da560d Mon Sep 17 00:00:00 2001 From: fOuttaMyPaint <154358121+TMHSDigital@users.noreply.github.com> Date: Sun, 24 May 2026 13:59:47 -0400 Subject: [PATCH 2/2] fix: update test fixtures to write STANDARDS_VERSION instead of VERSION Signed-off-by: fOuttaMyPaint <154358121+TMHSDigital@users.noreply.github.com> --- tests/test_cli.py | 4 ++-- tests/test_cli_remote_flags.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index a8d58ad..2e61965 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -9,11 +9,11 @@ @pytest.fixture def meta_repo(tmp_path: Path) -> Path: - """Isolated meta-repo for CLI tests. Pins meta VERSION to 1.6.3 so that + """Isolated meta-repo for CLI tests. Pins STANDARDS_VERSION to 1.6.3 so that the on-disk fixtures (which still carry 1.6.3 signals) read as clean.""" root = tmp_path / "meta" root.mkdir() - (root / "VERSION").write_text("1.6.3", encoding="utf-8") + (root / "STANDARDS_VERSION").write_text("1.6.3", encoding="utf-8") (root / "standards").mkdir() (root / "standards" / "required-refs.json").write_text( '{"version": 1, "requirements": {"cursor-plugin": {}, "mcp-server": {}}}', diff --git a/tests/test_cli_remote_flags.py b/tests/test_cli_remote_flags.py index c1834a6..26325ad 100644 --- a/tests/test_cli_remote_flags.py +++ b/tests/test_cli_remote_flags.py @@ -16,7 +16,7 @@ def meta_repo(tmp_path: Path) -> Path: root = tmp_path / "meta" root.mkdir() - (root / "VERSION").write_text("1.6.3", encoding="utf-8") + (root / "STANDARDS_VERSION").write_text("1.6.3", encoding="utf-8") (root / "standards").mkdir() (root / "standards" / "required-refs.json").write_text( '{"version": 1, "requirements": {"cursor-plugin": {}, "mcp-server": {}}}', @@ -48,7 +48,7 @@ def test_remote_without_token_errors(capsys, meta_repo: Path, monkeypatch): def test_all_without_registry_errors(capsys, tmp_path: Path): bare = tmp_path / "bare-meta" bare.mkdir() - (bare / "VERSION").write_text("1.6.3", encoding="utf-8") + (bare / "STANDARDS_VERSION").write_text("1.6.3", encoding="utf-8") rc = cli.main([ "--all", "--meta-repo", str(bare),