From 09edec62a5dc299d5105473d2ac8913d7de7e61a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Jul 2026 09:20:29 +0000
Subject: [PATCH 1/7] Initial plan
From b6457d5fdc4a131dc09a5bd5792d8dff5a04b51a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Jul 2026 09:29:58 +0000
Subject: [PATCH 2/7] Read the Windows pin from the pin, not from an example in
a comment
---
Directory.Build.props | 31 +++++++++------
.../RepositoryConsistencyTests.cs | 38 +++++++++++++++++++
2 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 006cd49..934e257 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -22,7 +22,7 @@
makes the package invisible to `dotnet add package`.
-->
2.34.1
- 4
+ 5
$(OpenTokVersion).$(OpenTokBindingRevision)
2.34.1.4
diff --git a/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs b/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
index c1f4cd0..95ad7bd 100644
--- a/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
+++ b/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
@@ -122,16 +122,54 @@ public void The_solution_lists_exactly_the_packages_plus_the_test_projects()
[InlineData("OpenTokVersion")]
[InlineData("OpenTokIosPackageVersion")]
[InlineData("OpenTokAndroidPackageVersion")]
+ [InlineData("OpenTokWinPackageVersion")]
+ [InlineData("OpenTokClientPackageVersion")]
public void Version_properties_are_literal_dotted_version_numbers(string property)
{
// Literal, not an MSBuild expression: .github/workflows/release.yml reads these with sed and
// tests/OpenTok.Net.PackageTests compares them as strings. Neither evaluates MSBuild, so a
// "$(OpenTokVersion).1" here would reach the published release notes verbatim.
+ //
+ // The same pattern rules out a prerelease, which is the other way a pin goes wrong. Every
+ // pull request in the platform repositories publishes a -beta.., and
+ // pinning one is the obvious way to get this repository's Windows leg green while that
+ // repository's release is still in flight — but whatever is pinned when a tag is cut is what
+ // consumers of the umbrella resolve, and a released package that depends on something built
+ // from a branch is not a release. The platform repository publishes first; this one re-pins
+ // behind it.
var value = ReadProperty(property);
Assert.Matches(@"^\d+(\.\d+){1,3}$", value);
}
+ [Theory]
+ [InlineData("OpenTokVersion")]
+ [InlineData("OpenTokBindingRevision")]
+ [InlineData("OpenTokIosPackageVersion")]
+ [InlineData("OpenTokAndroidPackageVersion")]
+ [InlineData("OpenTokWinPackageVersion")]
+ [InlineData("OpenTokClientPackageVersion")]
+ public void Version_properties_are_declared_exactly_once(string property)
+ {
+ // Everything that reads these pins outside MSBuild — build/pins.sh, build/check-upstream.sh,
+ // release.yml, pr.yml, ReadProperty below — matches the element textually and keeps the
+ // first hit. An XML comment is not a comment to any of them, so a second element written
+ // into the prose above the real pin *is* the pin as far as they are concerned, and the two
+ // disagree exactly where it is least visible: MSBuild keeps building against the last value
+ // in the file while every report about the file describes the first.
+ //
+ // That is what an example beta above OpenTokWinPackageVersion did — the daily upstream check
+ // reported the Windows package as pinned to a prerelease nuget.org had never carried, while
+ // the packages were built against the release underneath it.
+ var props = File.ReadAllText(Path.Combine(RepositoryRoot, "Directory.Build.props"));
+
+ var occurrences = props.Split($"<{property}>").Length - 1;
+
+ Assert.True(
+ occurrences == 1,
+ $"Directory.Build.props opens <{property}> {occurrences} times; it must appear once, comments included.");
+ }
+
[Fact]
public void The_binding_revision_is_a_plain_integer()
{
From 3d97508a09b2eebe913f6255665ddc04b405adfb Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Jul 2026 09:32:41 +0000
Subject: [PATCH 3/7] Cut 2.34.1.5: the release 2.34.1.4 never became
---
README.md | 6 ++--
docs/release-notes/2.34.1.4.md | 6 ++++
docs/release-notes/2.34.1.5.md | 62 ++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 2 deletions(-)
create mode 100644 docs/release-notes/2.34.1.5.md
diff --git a/README.md b/README.md
index 9cd8cae..fc07ed3 100755
--- a/README.md
+++ b/README.md
@@ -183,8 +183,10 @@ Three suites, two of which run anywhere:
- **`tests/OpenTok.Net.UnitTests`** checks the repository's own bookkeeping with nothing built —
`build/packages.tsv` against the projects under `src/`, the solution against both, dependency
- ordering, and the version pins. Including the invariant this repository exists for: **both pinned
- platform packages wrapping the same native SDK generation.**
+ ordering, and the version pins: each declared exactly once in `Directory.Build.props`, comments
+ included, and each a released version rather than one of the platform repositories' betas.
+ Including the invariant this repository exists for: **both pinned platform packages wrapping the
+ same native SDK generation.**
- **`tests/OpenTok.Net.PackageTests`** inspects the packed `.nupkg` files: an assembly for every
target framework, the right platform binding depended on for each one, an exact-version link
between the two packages, and the same same-SDK-generation check read back out of the shipped
diff --git a/docs/release-notes/2.34.1.4.md b/docs/release-notes/2.34.1.4.md
index 4a08f6e..de54a3e 100644
--- a/docs/release-notes/2.34.1.4.md
+++ b/docs/release-notes/2.34.1.4.md
@@ -1,5 +1,11 @@
# OpenTok.Net 2.34.1.4
+> **Never published.** This note was merged before `auto-release.yml` existed, and a note only tags
+> the push that adds it — so no `v2.34.1.4` tag was ever cut and nuget.org has no such release.
+> Everything below shipped in
+> [2.34.1.5](https://github.com/sbokatuk/OpenTok.Net/blob/main/docs/release-notes/2.34.1.5.md)
+> instead. Kept as written, because it is where the Windows head is documented.
+
Adds Windows as a third platform. No change to the iOS or Android heads, and no change to the
platform pins beyond adding one — 2.34.1.3 already repointed Android.
diff --git a/docs/release-notes/2.34.1.5.md b/docs/release-notes/2.34.1.5.md
new file mode 100644
index 0000000..d7b2727
--- /dev/null
+++ b/docs/release-notes/2.34.1.5.md
@@ -0,0 +1,62 @@
+# OpenTok.Net 2.34.1.5
+
+The release 2.34.1.4 was supposed to be. The façade's own source is identical to it — what changes
+here is that it actually ships, and that the Windows pin is no longer readable as something it is
+not.
+
+2.34.1.4 was written, reviewed and merged, and then never tagged: merging a release note is what
+cuts a release in this repository, and `auto-release.yml` landed *after*
+`docs/release-notes/2.34.1.4.md` had already gone in. A note only tags the push that adds it, so
+nothing tagged that one, and nuget.org's newest release stayed 2.34.1.3 while Windows support sat
+on `main` unpublished. This note adds itself, which is that mechanism working as intended.
+
+## Windows, published this time
+
+Exactly as
+[2.34.1.4's note](https://github.com/sbokatuk/OpenTok.Net/blob/main/docs/release-notes/2.34.1.4.md)
+describes it: `OpenTokSession`, `OpenTokPublisher` and `OpenTokSubscriber` run on Windows over
+Vonage's `OpenTok.Client`, with the WinUI renderer supplied by
+[`OpenTok.Net.Win`](https://github.com/sbokatuk/OpenTok.Net.Win), and both packages carry nine
+target frameworks instead of six. Read that note for the two things Windows asks that the other
+platforms do not — x64 only, and the first OpenTok object created on the UI thread — and for the
+members that are documented no-ops there.
+
+## The pin is the pin, not an example of one
+
+`Directory.Build.props` explained how to point the Windows pin at an in-flight beta by spelling one
+out, as a complete `OpenTokWinPackageVersion` element, in the comment above the pin. MSBuild does
+not read comments at all, so the only assignment in the file was the real one: every package this
+repository has built was built against the released `2.34.1.4`, and the pin itself was never wrong.
+
+Nothing else that reads this file works that way. `build/pins.sh`, `build/check-upstream.sh`,
+`release.yml`, `pr.yml` and this repository's own consistency tests all match the element textually
+and keep the *first* hit, and the first hit was the example. So the daily upstream check reported
+`OpenTok.Net.Win` as pinned to `2.34.1.4-beta.7.3`, a prerelease nuget.org has never carried, and —
+correctly, for what it believed it was looking at — that the pinned version no longer downloads.
+Two findings about a pin that was fine, with the real one invisible behind them.
+
+The example is gone, and `RepositoryConsistencyTests` now keeps it gone with two checks: every
+pinned version property must appear exactly once in `Directory.Build.props`, comments included, and
+every one of them must be a plain release version. The second is the rule the first was hiding — a
+released umbrella must not depend on a package built from a branch, so the platform repository
+publishes first and this one re-pins behind it, rather than pinning a beta to turn a red leg green.
+
+## Pins
+
+Unchanged, and all four confirmed against nuget.org on 2026-07-30 — newest release published, and
+the artifact itself downloads rather than merely being indexed:
+
+| Property | Package | Version |
+| --- | --- | --- |
+| `OpenTokIosPackageVersion` | `OpenTok.Net.iOS` | [2.34.1.2](https://www.nuget.org/packages/OpenTok.Net.iOS/2.34.1.2) |
+| `OpenTokAndroidPackageVersion` | `OpenTok.Net.Android` | [2.34.1.4](https://www.nuget.org/packages/OpenTok.Net.Android/2.34.1.4) |
+| `OpenTokWinPackageVersion` | `OpenTok.Net.Win` | [2.34.1.4](https://www.nuget.org/packages/OpenTok.Net.Win/2.34.1.4) |
+| `OpenTokClientPackageVersion` | `OpenTok.Client` | [2.34.1](https://www.nuget.org/packages/OpenTok.Client/2.34.1) |
+
+Nothing is waiting on a platform release this time — all four are live, which is the ordering
+2.34.1.4's note asks for and 2.34.1.2 is what happens without.
+
+## If you are on 2.34.1.3
+
+Upgrade. Nothing to change in your code: no API and no behaviour moved on iOS or Android. What you
+gain is a Windows head that was not there before.
From 585e5d3f5f6e588ad4f3b1f7cd4a95745be2dcab Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Jul 2026 09:33:53 +0000
Subject: [PATCH 4/7] Point the drift report's re-pin hint at what this
repository actually does
---
.github/workflows/upstream-drift.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/upstream-drift.yml b/.github/workflows/upstream-drift.yml
index 5dab6c7..bcca78a 100644
--- a/.github/workflows/upstream-drift.yml
+++ b/.github/workflows/upstream-drift.yml
@@ -41,8 +41,10 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
# Named here rather than in the script so each repository says its own thing without the
- # shared checker growing repository-specific prose.
- REPIN_HINT: 'Pins live in `Directory.Build.props`; `./build/BumpNativeVersion.sh ` does the mechanical part.'
+ # shared checker growing repository-specific prose. There is no BumpNativeVersion.sh in this
+ # one — it binds nothing native, so a pin is a hand edit, and the two ways that goes wrong are
+ # worth naming in every report rather than once in a file nobody rereads.
+ REPIN_HINT: 'Pins live in `Directory.Build.props` and are edited by hand; this repository binds nothing native, so there is no bump script. Change the property value itself — never a prerelease, and never as an example element inside a comment, since everything that reads these pins outside MSBuild keeps the first textual match.'
steps:
- uses: actions/checkout@v4
From be46471a4828b7e0b00fd7d98a4c17ec560c005a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Jul 2026 09:36:35 +0000
Subject: [PATCH 5/7] Say precisely what MSBuild does with the comment
---
tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs b/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
index 95ad7bd..6de3b5e 100644
--- a/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
+++ b/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
@@ -155,8 +155,8 @@ public void Version_properties_are_declared_exactly_once(string property)
// release.yml, pr.yml, ReadProperty below — matches the element textually and keeps the
// first hit. An XML comment is not a comment to any of them, so a second element written
// into the prose above the real pin *is* the pin as far as they are concerned, and the two
- // disagree exactly where it is least visible: MSBuild keeps building against the last value
- // in the file while every report about the file describes the first.
+ // disagree exactly where it is least visible: MSBuild never sees the comment, so the build
+ // stays right while every report about the build is wrong.
//
// That is what an example beta above OpenTokWinPackageVersion did — the daily upstream check
// reported the Windows package as pinned to a prerelease nuget.org had never carried, while
From c95fba67efa03bf2012a2599b38c80eb737762b3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 30 Jul 2026 09:37:50 +0000
Subject: [PATCH 6/7] Fix a dropped verb in the Windows pin comment
---
Directory.Build.props | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 934e257..518e7c7 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -101,9 +101,9 @@
consistency tests — matches the element textually and keeps the first hit, so a second one
written into a comment above the real pin *is* the pin as far as all of them are concerned.
That is not hypothetical: an example beta spelled out here in full had the daily upstream check
- reporting this package as pinned to a prerelease nuget.org had never carried, while every
- package built against the release below it. RepositoryConsistencyTests now asserts both halves
- — one occurrence per pinned property, and no prerelease in any of them.
+ reporting this package as pinned to a prerelease nuget.org had never carried, while the
+ packages themselves were built against the release below it. RepositoryConsistencyTests now
+ asserts both halves — one occurrence per pinned property, and no prerelease in any of them.
-->
2.34.1.4
From df6c618865e1699c6ef40b708f4b331b2576b380 Mon Sep 17 00:00:00 2001
From: Sergei Bokatuk
Date: Thu, 30 Jul 2026 12:55:34 +0300
Subject: [PATCH 7/7] Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---
tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs b/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
index 6de3b5e..a380746 100644
--- a/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
+++ b/tests/OpenTok.Net.UnitTests/RepositoryConsistencyTests.cs
@@ -126,8 +126,8 @@ public void The_solution_lists_exactly_the_packages_plus_the_test_projects()
[InlineData("OpenTokClientPackageVersion")]
public void Version_properties_are_literal_dotted_version_numbers(string property)
{
- // Literal, not an MSBuild expression: .github/workflows/release.yml reads these with sed and
- // tests/OpenTok.Net.PackageTests compares them as strings. Neither evaluates MSBuild, so a
+ // Literal, not an MSBuild expression: the GitHub workflows (e.g. .github/workflows/release.yml)
+ // and ReadProperty below read these with plain text matching. Neither evaluates MSBuild, so a
// "$(OpenTokVersion).1" here would reach the published release notes verbatim.
//
// The same pattern rules out a prerelease, which is the other way a pin goes wrong. Every