diff --git a/src/scripts/bump_project_version.py b/src/scripts/bump_project_version.py index 08d7726..89e2edf 100644 --- a/src/scripts/bump_project_version.py +++ b/src/scripts/bump_project_version.py @@ -80,12 +80,23 @@ try: before_raw = pi.version before_str = str(before_raw) if before_raw is not None else None - before_parts = parse_version(before_raw) - after_parts = bump(before_parts, LEVEL) - after_str = '%d.%d.%d.%d' % after_parts - print("DEBUG: bump_project_version: level=%s before=%s -> after=%s" % ( - LEVEL, before_str, after_str)) + # First-run convention: if no version is set yet, seed at 1.0.0.0 instead + # of treating "no version" as 0.0.0.0 + bump (which would give 0.0.0.1 + # for level=build, awkward for a first canonical version). Most projects + # start tracking at 1.0.0.0 when they first turn on versioning, and the + # level argument is moot for the seed step. + seed_check = parse_version(before_raw) + if seed_check == (0, 0, 0, 0) and (before_raw is None or str(before_raw).strip() in ('', '0.0.0.0', 'None')): + after_parts = (1, 0, 0, 0) + after_str = '1.0.0.0' + print("DEBUG: bump_project_version: no prior version -- seeding to 1.0.0.0 (level=%s ignored on first run)" % LEVEL) + else: + before_parts = seed_check + after_parts = bump(before_parts, LEVEL) + after_str = '%d.%d.%d.%d' % after_parts + print("DEBUG: bump_project_version: level=%s before=%s -> after=%s" % ( + LEVEL, before_str, after_str)) pi.version = after_str diff --git a/src/server.ts b/src/server.ts index 9cb9310..54a6722 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1350,7 +1350,7 @@ export async function startMcpServer(config: ServerConfig): Promise { s.tool( 'bump_project_version', - "Bumps one part of the 4-part Project Information.Version field of the primary project (Major.Minor.Revision.Build) and saves the project. Convention: major = incompatible API break (rename FB / change public signature / remove method); minor = backward-compatible feature add (new FB / GVL / method); revision = bug fix only; build = internal counter, often 0 for hand-released versions. Bumping a higher part resets all lower parts to 0 (e.g. bumping minor resets revision and build to 0). Treats None / empty / unset version as '0.0.0.0'. The Version is exposed at runtime via the Project Information library's GetVersion() helper, which IEC code can call to surface the running version.", + "Bumps one part of the 4-part Project Information.Version field of the primary project (Major.Minor.Revision.Build) and saves the project. Convention: major = incompatible API break (rename FB / change public signature / remove method); minor = backward-compatible feature add (new FB / GVL / method); revision = bug fix only; build = internal counter, often 0 for hand-released versions. Bumping a higher part resets all lower parts to 0 (e.g. bumping minor resets revision and build to 0). FIRST-RUN: if no version is set yet (None/empty/0.0.0.0), seeds at 1.0.0.0 regardless of level so a first-time bump gives a canonical starting point instead of 0.0.0.1. The Version is exposed at runtime via the Project Information library's GetVersion() helper, which IEC code can call to surface the running version.", { projectFilePath: z.string().describe("Path to the project file."), level: z.enum(['major', 'minor', 'revision', 'build']).describe("Which part of the 4-part version to bump. Major = incompatible API break. Minor = backward-compatible feature add. Revision = bug fix only. Build = internal / CI counter."),