From 1e365e1500e061a848e9d77a509ff0e91ce9a7ef Mon Sep 17 00:00:00 2001 From: Jim Schaff Date: Fri, 21 Aug 2026 09:48:52 -0400 Subject: [PATCH 1/4] fix(core): read PATCH from the PATCH position in VCellSoftwareVersion getPatchVersion() returned a copy of getMinorVersion(): the version number was split correctly but PATCH was read from parts[1] instead of parts[2]. The line dates from 2018, when the same statement used split(".") -- a regex matching any character, so the split returned an empty array and every part stayed -1. A 2022 fix to that argument made MAJOR and MINOR work for the first time and made this typo live along with them. Its only consumer compared it against an equally wrong value, so nothing surfaced in four years. Adds the class's first tests, including one that distinguishes 8.1.0 from 8.0.1 -- a pair the old parser could not tell apart. Closes #2011 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FUd61NUJgz88h4PZs5MqHn --- .../util/document/VCellSoftwareVersion.java | 2 +- .../document/VCellSoftwareVersionTest.java | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 vcell-core/src/test/java/org/vcell/util/document/VCellSoftwareVersionTest.java diff --git a/vcell-core/src/main/java/org/vcell/util/document/VCellSoftwareVersion.java b/vcell-core/src/main/java/org/vcell/util/document/VCellSoftwareVersion.java index 0b47cac377..060db74a37 100644 --- a/vcell-core/src/main/java/org/vcell/util/document/VCellSoftwareVersion.java +++ b/vcell-core/src/main/java/org/vcell/util/document/VCellSoftwareVersion.java @@ -77,7 +77,7 @@ private VCellSoftwareVersion(String softwareVersionString){ minorVersion = safeParse(minor); } if (parts.length > 2) { - String patch = parts[1]; + String patch = parts[2]; patchVersion = safeParse(patch); } } catch (Exception exc) { diff --git a/vcell-core/src/test/java/org/vcell/util/document/VCellSoftwareVersionTest.java b/vcell-core/src/test/java/org/vcell/util/document/VCellSoftwareVersionTest.java new file mode 100644 index 0000000000..e3306ebcbe --- /dev/null +++ b/vcell-core/src/test/java/org/vcell/util/document/VCellSoftwareVersionTest.java @@ -0,0 +1,44 @@ +package org.vcell.util.document; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * The four-part version is carried as "_Version__build_". + * PATCH was read from the MINOR position for four years (issue #2011) without anything + * noticing, because its only consumer compared it against a value that was equally wrong. + */ +@Tag("Fast") +public class VCellSoftwareVersionTest { + + @Test + public void parsesAllFourParts() { + VCellSoftwareVersion v = VCellSoftwareVersion.fromString("Alpha_Version_8.0.28_build_01"); + assertEquals(VCellSoftwareVersion.VCellSite.alpha, v.getSite()); + assertEquals(8, v.getMajorVersion()); + assertEquals(0, v.getMinorVersion()); + assertEquals(28, v.getPatchVersion()); + assertEquals("01", v.getBuildNumber()); + } + + @Test + public void patchIsNotAliasedToMinor() { + // 8.1.0 and 8.0.1 differ only by which of the two middle numbers is set, so a + // parser that reads PATCH from the MINOR position cannot tell them apart. + VCellSoftwareVersion a = VCellSoftwareVersion.fromString("Rel_Version_8.1.0_build_01"); + assertEquals(1, a.getMinorVersion()); + assertEquals(0, a.getPatchVersion()); + + VCellSoftwareVersion b = VCellSoftwareVersion.fromString("Rel_Version_8.0.1_build_01"); + assertEquals(0, b.getMinorVersion()); + assertEquals(1, b.getPatchVersion()); + } + + @Test + public void unparseableVersionIsUnknownRatherThanThrowing() { + VCellSoftwareVersion v = VCellSoftwareVersion.fromString("nonsense"); + assertEquals(VCellSoftwareVersion.VCellSite.unknown, v.getSite()); + } +} From 55263fd5f9ea46f0ba5056984a52c9e952590c4d Mon Sep 17 00:00:00 2001 From: Jim Schaff Date: Fri, 21 Aug 2026 09:48:52 -0400 Subject: [PATCH 2/4] feat(client): tell the user when the server is updated mid-session The client reconnects on its own after a deployment, but that path went straight to connectToServer() and skipped the version check entirely, so a user could work for hours against a server newer than their client with no sign that a new one had been published. The automatic reconnect now runs the check, and only once the reconnect has succeeded -- a failed attempt says nothing about the server's version, and the check makes an HTTP call of its own that the retry loop should not repeat. The two situations get the policy that suits them: ON_CONNECT login or a reconnect the user asked for. MAJOR or MINOR only; a PATCH difference is ordinary here. AFTER_SERVER_CHANGED the server moved underneath a running client, so any difference is worth reporting, PATCH included. The second message says the session is safe and to restart when convenient, rather than the "download the latest client" wording that suits a mismatch found at login. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FUd61NUJgz88h4PZs5MqHn --- .../vcell/api/server/ClientServerManager.java | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java b/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java index 67eb1ff9fd..1d2ce62ebc 100644 --- a/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java +++ b/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java @@ -275,7 +275,25 @@ public MessageEvent[] getMessageEvents() throws RemoteProxyException, IOExceptio } } -private void checkClientServerSoftwareVersion(InteractiveClientServerContext requester, ClientServerInfo clientServerInfo) { +/** + * Which version differences are worth interrupting the user for. + */ +private enum VersionCheck { + /** + * At login, or a reconnect the user asked for. A PATCH difference is normal here -- + * PATCH moves with nearly every release while installed clients update on the user's + * own schedule -- so only MAJOR or MINOR is reported. + */ + ON_CONNECT, + /** + * After an automatic reconnect, which means the server was redeployed underneath a + * running client. Any difference is reported, PATCH included: the user is being told + * that a newer client exists, not that their session is wrong. + */ + AFTER_SERVER_CHANGED +} + +private void checkClientServerSoftwareVersion(InteractiveClientServerContext requester, ClientServerInfo clientServerInfo, VersionCheck when) { String clientSoftwareVersion = System.getProperty(PropertyLoader.vcellSoftwareVersion); if (clientSoftwareVersion != null && clientSoftwareVersion.toLowerCase().contains("devel") ) { return; @@ -293,13 +311,29 @@ private void checkClientServerSoftwareVersion(InteractiveClientServerContext req + "We have adopted a Release Early, Release Often software development approach\n\n" + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); } - if (clientVersion.getMajorVersion()!=serverVersion.getMajorVersion() || - clientVersion.getMinorVersion()!=serverVersion.getMinorVersion() || - clientVersion.getPatchVersion()!=serverVersion.getPatchVersion()) { - requester.showWarningDialog("software version mismatch between client and server:\n" - + "client VCell version : " + clientSoftwareVersion + "\n" - + "server VCell version : " + serverSoftwareVersion + "\n" - + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); + boolean bDiffers = clientVersion.getMajorVersion()!=serverVersion.getMajorVersion() || + clientVersion.getMinorVersion()!=serverVersion.getMinorVersion(); + if (when == VersionCheck.AFTER_SERVER_CHANGED) { + // + // The server was upgraded underneath a running client, so any difference at + // all is worth reporting -- a new client exists and the user should restart + // to pick it up. + // + bDiffers = bDiffers || clientVersion.getPatchVersion()!=serverVersion.getPatchVersion(); + } + if (bDiffers) { + if (when == VersionCheck.AFTER_SERVER_CHANGED) { + requester.showWarningDialog("The VCell server was updated while you were working:\n" + + "client VCell version : " + clientSoftwareVersion + "\n" + + "server VCell version : " + serverSoftwareVersion + "\n" + + "\nYour work is safe and you may keep using this session." + + "\nPlease exit and restart VCell when convenient to install the new version."); + } else { + requester.showWarningDialog("software version mismatch between client and server:\n" + + "client VCell version : " + clientSoftwareVersion + "\n" + + "server VCell version : " + serverSoftwareVersion + "\n" + + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); + } } } } @@ -318,7 +352,7 @@ public void connectNewServer(InteractiveClientServerContext requester, ClientSer public void connect(InteractiveClientServerContext requester) { asynchMessageManager.stopPolling(); reconnectStat = ReconnectStatus.NOT; - checkClientServerSoftwareVersion(requester,clientServerInfo); + checkClientServerSoftwareVersion(requester,clientServerInfo,VersionCheck.ON_CONNECT); // get new server connection VCellConnection newVCellConnection = connectToServer(requester,true); @@ -727,6 +761,12 @@ void reconnect() { changeConnection(requester,connection); rc.stop(); asynchMessageManager.startPolling(); + // + // Only once the reconnect has succeeded -- a failed attempt says nothing about + // the server's version, and this check makes an HTTP call of its own that the + // retry loop should not repeat. + // + checkClientServerSoftwareVersion(requester,clientServerInfo,VersionCheck.AFTER_SERVER_CHANGED); return; } setConnectionStatus(new ClientConnectionStatus(getClientServerInfo().getUsername(), getClientServerInfo().getApihost(), getClientServerInfo().getApiport(), ConnectionStatus.DISCONNECTED)); From 6801a9a15e2d1722115a0ce7c60063c36b396aa3 Mon Sep 17 00:00:00 2001 From: Jim Schaff Date: Fri, 21 Aug 2026 09:48:52 -0400 Subject: [PATCH 3/4] =?UTF-8?q?docs(release):=20cut=208.1.0.01=20=E2=80=94?= =?UTF-8?q?=20realign=20the=20build=20number=20with=20the=20release=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This work has been called VCell 8.1 in the release notes since it began, while its builds continued the 8.0.x sequence. From 8.1.0.01 the two agree. Published numbers up to 8.0.28.01 are unchanged. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FUd61NUJgz88h4PZs5MqHn --- CHANGELOG.md | 48 ++++++++++++++++++++++++++++++++++++++ docs/RELEASING.md | 8 ++++--- release-notes/major/8.1.md | 29 +++++++++++++++-------- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f8af99e08..cbbe115594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,54 @@ followed by flat Keep-a-Changelog categories. API consumers should scan _(Release-manager scratchpad. Populated at release-cut time.)_ +## [8.1.0.01] - 2026-08-21 + +**Highlights.** The build number now matches the release name. This work has +been called VCell 8.1 in the release notes since it began, while its builds +continued the `8.0.x` sequence; from this build the two agree. This is the +first release candidate for VCell 8.1. VCell also tells you when the server is +updated underneath you: if a deployment happens while you are working, the +reconnect now says a newer version exists and invites you to restart when +convenient, rather than reconnecting silently to a server your client no +longer matches. + +### Added +- When the server is updated during a session, VCell now says so. The client + reconnects automatically after a deployment, and that reconnect reports the + new version and suggests restarting when convenient. The message makes clear + the session is safe to continue. Previously the automatic reconnect was + silent, so a user could work for hours against a server newer than their + client without knowing a new one had been published. (#2012) + +### Fixed +- `VCellSoftwareVersion` read the PATCH number from the MINOR position, so + `getPatchVersion()` returned a copy of `getMinorVersion()`. The line dates + from 2018 but was dead until a 2022 fix to the same statement made it live. + Its only consumer compared it against an equally wrong value, so nothing + ever surfaced. (#2011) + +### Changed +- Version numbering realigned with the release narrative: builds are numbered + `8.1.x` from here, rather than continuing `8.0.x`. Published numbers up to + 8.0.28.01 are unchanged. (#2010) +- A desktop client older than this build now shows the "software version + mismatch" warning when connecting, asking the user to download the current + client. The warning is advisory and does not prevent use. At login VCell + reports a difference in the first two parts of the version only, so this + stayed silent for every build in the 8.0 line, where those parts were the + same throughout; moving to 8.1 gives it something to report. (#2012) +- The two version checks now apply the policy that suits each. At login, or a + reconnect the user asked for, only a MAJOR or MINOR difference is reported — + a PATCH difference is ordinary there, since patches ship most releases and + installed clients update on their own schedule. After an automatic reconnect + any difference is reported, PATCH included, because the server changed + underneath a running client and a newer client exists. (#2012) + +### Notes for API consumers +No API changes. Clients that parse the version string should note that +`MAJOR.MINOR` moves from `8.0` to `8.1`; the four-part +`MAJOR.MINOR.PATCH.BUILD` shape is unchanged. + ## [8.0.28.01] - 2026-08-20 **Highlights.** Dragging in the SpringSaLaD trajectory viewer turned the scene the wrong way — diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 1f8196b04b..9929b22769 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -122,12 +122,14 @@ This has already happened once. **VCell 8.0** is the 8.0.0 builds only — 8.0.0.01 through 8.0.0.03, the SpringSaLaD GA that ran in production from 2026-05-21 to 2026-08-14. Everything released after 8.0.0.03 is **VCell 8.1**, even though those builds are numbered 8.0.2.01 through -8.0.28.01 and beyond. +8.0.28.01. The numbering was realigned at **8.1.0.01**, so the two agree +again from that build onward; the divergence covers 8.0.2.01–8.0.28.01 +only. So, at release-cut time, add the user-facing items to the narrative file for the release **currently being accumulated** — today -`8.1.md` — not to the file whose name matches the build's -`MAJOR.MINOR`. `CHANGELOG.md` is unaffected: it is organised strictly +`8.1.md` — which is not necessarily the file whose name matches the +build's `MAJOR.MINOR`. `CHANGELOG.md` is unaffected: it is organised strictly by build version and always records the real number. When a long-running `MAJOR.MINOR` line accumulates multiple distinct diff --git a/release-notes/major/8.1.md b/release-notes/major/8.1.md index aec6adeb8b..4513d6bbb8 100644 --- a/release-notes/major/8.1.md +++ b/release-notes/major/8.1.md @@ -1,15 +1,19 @@ # VCell 8.1 -**Status:** pre-release. Rolled to the production site on 2026-08-14 -and updated since; not yet announced as a public release event. - -> **A note on version numbers.** VCell 8.1 is delivered by builds whose -> version numbers continue the `8.0.x` sequence — 8.0.2.01 through -> 8.0.28.01 so far. Those numbers are what they are and are not being -> restated. For release notes and user-facing announcements, **VCell 8.0 -> means the 8.0.0 builds** (8.0.0.01–8.0.0.03, the SpringSaLaD GA that -> ran in production from 2026-05-21 to 2026-08-14), and **everything -> released after 8.0.0.03 is VCell 8.1**. +**Status:** release candidate — **8.1.0.01**. An earlier form of this +release has been on the production site since 2026-08-14 under `8.0.x` +build numbers; from 8.1.0.01 the build number carries the release name. + +> **A note on version numbers.** VCell 8.1 was developed under build +> numbers that continued the `8.0.x` sequence — 8.0.2.01 through +> 8.0.28.01. Those numbers are published and are not being restated. +> **From 8.1.0.01 the two agree**, and the explanation below applies +> only to the builds before it. +> +> For release notes and user-facing announcements, **VCell 8.0 means +> the 8.0.0 builds** (8.0.0.01–8.0.0.03, the SpringSaLaD GA that ran in +> production from 2026-05-21 to 2026-08-14), and **everything released +> after 8.0.0.03 is VCell 8.1**. ## Headline @@ -72,6 +76,11 @@ where spatial visualization is heading, not because it is ready. ## Improvements +- VCell now tells you when the server is updated while you are working. The + client reconnects on its own after a deployment; that reconnect now reports + that a newer version exists and suggests restarting when convenient, rather + than reconnecting silently. The session remains safe to continue + (8.1.0.01). - Desktop window behaviour: child windows and dialogs now stay in front of the window that opened them — and minimize and travel with it — on modern macOS and Windows, where they could previously slip behind the From 5496bdb6f7e1fd6d2c278acdf2745e73c43022cc Mon Sep 17 00:00:00 2001 From: Jim Schaff Date: Fri, 21 Aug 2026 09:54:13 -0400 Subject: [PATCH 4/4] fix(client): compare MAJOR, MINOR and PATCH in one check A VCell patch release can carry a breaking API change, so a client and server differing in the patch number are not known to be compatible. That makes a patch mismatch worth reporting wherever it is found, not only after a mid-session server update -- and it is what the check has meant to do since 2018, which the parser bug in #2011 silently prevented. Drops the two-policy split from the previous commit. The context now selects only the wording: a mismatch found at login says to download the current client, one appearing mid-session says to save, exit and restart. Also removes the claim that the session is safe to continue after a mid-session update. If a patch can break the API, that promise cannot be made. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01FUd61NUJgz88h4PZs5MqHn --- CHANGELOG.md | 48 ++++++++----------- release-notes/major/8.1.md | 11 +++-- .../vcell/api/server/ClientServerManager.java | 39 ++++++--------- 3 files changed, 42 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbbe115594..bb69254bcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,43 +21,37 @@ _(Release-manager scratchpad. Populated at release-cut time.)_ **Highlights.** The build number now matches the release name. This work has been called VCell 8.1 in the release notes since it began, while its builds continued the `8.0.x` sequence; from this build the two agree. This is the -first release candidate for VCell 8.1. VCell also tells you when the server is -updated underneath you: if a deployment happens while you are working, the -reconnect now says a newer version exists and invites you to restart when -convenient, rather than reconnecting silently to a server your client no -longer matches. +first release candidate for VCell 8.1. VCell also checks properly now whether +your client matches the server it is talking to, including when the server is +updated part-way through a session — a mismatch it has been unable to detect +since 2022. ### Added - When the server is updated during a session, VCell now says so. The client - reconnects automatically after a deployment, and that reconnect reports the - new version and suggests restarting when convenient. The message makes clear - the session is safe to continue. Previously the automatic reconnect was - silent, so a user could work for hours against a server newer than their - client without knowing a new one had been published. (#2012) + reconnects on its own after a deployment, and that reconnect now reports the + change and asks the user to save, exit and restart to install the matching + version. Previously the automatic reconnect was silent, so a user could work + on against a server their client no longer matched. (#2012) ### Fixed -- `VCellSoftwareVersion` read the PATCH number from the MINOR position, so - `getPatchVersion()` returned a copy of `getMinorVersion()`. The line dates - from 2018 but was dead until a 2022 fix to the same statement made it live. - Its only consumer compared it against an equally wrong value, so nothing - ever surfaced. (#2011) +- VCell could not detect a client/server version mismatch that lay in the + PATCH number. `VCellSoftwareVersion` read PATCH from the MINOR position, so + the check that compares client against server was comparing MINOR twice and + ignoring PATCH entirely. Since a VCell patch release can carry a breaking + API change, this is the case that most needed catching. The line dates from + 2018 but was dead until a 2022 fix to the same statement made it live. + (#2011) ### Changed - Version numbering realigned with the release narrative: builds are numbered `8.1.x` from here, rather than continuing `8.0.x`. Published numbers up to 8.0.28.01 are unchanged. (#2010) -- A desktop client older than this build now shows the "software version - mismatch" warning when connecting, asking the user to download the current - client. The warning is advisory and does not prevent use. At login VCell - reports a difference in the first two parts of the version only, so this - stayed silent for every build in the 8.0 line, where those parts were the - same throughout; moving to 8.1 gives it something to report. (#2012) -- The two version checks now apply the policy that suits each. At login, or a - reconnect the user asked for, only a MAJOR or MINOR difference is reported — - a PATCH difference is ordinary there, since patches ship most releases and - installed clients update on their own schedule. After an automatic reconnect - any difference is reported, PATCH included, because the server changed - underneath a running client and a newer client exists. (#2012) +- The client/server version warning now appears whenever MAJOR, MINOR **or** + PATCH differ — which is what it was always meant to do, and could not. + Expect to see it more often than before: it was effectively dormant across + the whole 8.0 line, and a patch difference alone is now enough to raise it. + The warning is advisory and does not prevent use. Only the BUILD number is + ignored. (#2012) ### Notes for API consumers No API changes. Clients that parse the version string should note that diff --git a/release-notes/major/8.1.md b/release-notes/major/8.1.md index 4513d6bbb8..68203c3ac0 100644 --- a/release-notes/major/8.1.md +++ b/release-notes/major/8.1.md @@ -76,11 +76,12 @@ where spatial visualization is heading, not because it is ready. ## Improvements -- VCell now tells you when the server is updated while you are working. The - client reconnects on its own after a deployment; that reconnect now reports - that a newer version exists and suggests restarting when convenient, rather - than reconnecting silently. The session remains safe to continue - (8.1.0.01). +- VCell now checks properly whether your client matches the server, and says + so when it does not — including when the server is updated part-way through + a session, which it previously reconnected to in silence. A VCell patch + release can change the API, so a client and server differing in any part of + the version may not work together; the check had been unable to see a + difference in the patch number since 2022 (8.1.0.01). - Desktop window behaviour: child windows and dialogs now stay in front of the window that opened them — and minimize and travel with it — on modern macOS and Windows, where they could previously slip behind the diff --git a/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java b/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java index 1d2ce62ebc..9ff0395c54 100644 --- a/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java +++ b/vcell-apiclient/src/main/java/org/vcell/api/server/ClientServerManager.java @@ -276,20 +276,13 @@ public MessageEvent[] getMessageEvents() throws RemoteProxyException, IOExceptio } /** - * Which version differences are worth interrupting the user for. + * Why the version check is running. The comparison is the same either way -- any + * difference in MAJOR, MINOR or PATCH -- but the two situations need different advice. */ private enum VersionCheck { - /** - * At login, or a reconnect the user asked for. A PATCH difference is normal here -- - * PATCH moves with nearly every release while installed clients update on the user's - * own schedule -- so only MAJOR or MINOR is reported. - */ + /** At login, or a reconnect the user asked for: the client was already out of date. */ ON_CONNECT, - /** - * After an automatic reconnect, which means the server was redeployed underneath a - * running client. Any difference is reported, PATCH included: the user is being told - * that a newer client exists, not that their session is wrong. - */ + /** After an automatic reconnect: the server was redeployed underneath a running client. */ AFTER_SERVER_CHANGED } @@ -311,23 +304,21 @@ private void checkClientServerSoftwareVersion(InteractiveClientServerContext req + "We have adopted a Release Early, Release Often software development approach\n\n" + "\nPlease exit VCell and download the latest client from VCell Software page (http://vcell.org)."); } - boolean bDiffers = clientVersion.getMajorVersion()!=serverVersion.getMajorVersion() || - clientVersion.getMinorVersion()!=serverVersion.getMinorVersion(); - if (when == VersionCheck.AFTER_SERVER_CHANGED) { - // - // The server was upgraded underneath a running client, so any difference at - // all is worth reporting -- a new client exists and the user should restart - // to pick it up. - // - bDiffers = bDiffers || clientVersion.getPatchVersion()!=serverVersion.getPatchVersion(); - } - if (bDiffers) { + // + // MAJOR, MINOR and PATCH all matter. A VCell PATCH release can carry a breaking + // API change, so a client and server differing in any of the three are not known + // to be compatible. Only BUILD is ignored. This is what the check has always + // meant to do; it could not, because getPatchVersion() returned MINOR (#2011). + // + if (clientVersion.getMajorVersion()!=serverVersion.getMajorVersion() || + clientVersion.getMinorVersion()!=serverVersion.getMinorVersion() || + clientVersion.getPatchVersion()!=serverVersion.getPatchVersion()) { if (when == VersionCheck.AFTER_SERVER_CHANGED) { requester.showWarningDialog("The VCell server was updated while you were working:\n" + "client VCell version : " + clientSoftwareVersion + "\n" + "server VCell version : " + serverSoftwareVersion + "\n" - + "\nYour work is safe and you may keep using this session." - + "\nPlease exit and restart VCell when convenient to install the new version."); + + "\nThis client no longer matches the server." + + "\nPlease save your work, then exit and restart VCell to install the matching version."); } else { requester.showWarningDialog("software version mismatch between client and server:\n" + "client VCell version : " + clientSoftwareVersion + "\n"