Q2 2026 — System.Text.Json migration + quarterly work#2
Conversation
SAM-BIM core migrated from Newtonsoft.Json to System.Text.Json.Nodes. - Replace each csproj's Newtonsoft package reference with System.Text.Json 10.0.8 - Variable / VariableType: FromJObject/ToJObject -> FromJsonObject/ToJsonObject; JObject -> JsonObject; .Value<JObject>(key) -> indexer + 'as JsonObject'; .Value<object>(key) -> indexer + Deserialize<object>(); .Add(key, value as dynamic) -> .Add(key, JsonValue.Create(value)) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
During the SAM-BIM Newtonsoft.Json -> System.Text.Json migration the quarterly sow/2026-Q2 branch carries the binary-breaking change. CI needs to consume the migrated SAM (and any sibling dep) from sow/2026-Q2, not from master, until the quarter-end merge. - Add "sow/2026-Q2" to push/pull_request branch triggers - For each dep clone, ls-remote sow/2026-Q2 and prefer it when present; fall back to default branch (e.g. master) otherwise. After the quarter merges back to master, this fallback naturally restores prior behaviour. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Refines the previous workflow patch so CI on the migration PR can succeed before anything has been merged. Each dep repo is cloned from: 1. github.head_ref (feature/remove-newtonsoft on these PRs) - has the migration right now on every dep 2. sow/2026-Q2 - source of truth after these PRs merge 3. default branch - source of truth after quarter-end merge Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The SPDX-check workflow requires the top 6 lines of every changed .cs file to contain both: // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright (c) 2020-2026 Michal Dengusiak & Jakub Ziolkowski and contributors (with an en-dash between the years). Migration commits modified existing files without preserving the header. Prepend the two lines now. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the older spdx-check.yml (literal en-dash grep, top 6 lines, PR-only trigger) with the modern template shipped on SAM core: - grep -qE with [-–] char class — accepts both hyphen-minus and en-dash - 20-line lookback (was 6) - BOM and CR stripping - mapfile + diff-filter for cleaner change detection - Adds workflow_dispatch trigger Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove Newtonsoft.Json — migrate to System.Text.Json.Nodes
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ede4661e4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (jObject.ContainsKey("Value")) | ||
| { | ||
| value = jObject.Value<object>("Value"); | ||
| value = jObject["Value"]?.Deserialize<object>(); |
There was a problem hiding this comment.
Deserialize Value using variable type instead of object
FromJsonObject now reads Value via Deserialize<object>(), but in System.Text.Json deserializing to object produces JsonElement rather than inferred CLR primitives (for example double, bool, DateTime). That changes the runtime type of Variable.Value after a JSON round-trip, so downstream consumers like scriptScope.SetVariable(input.Name, input.Value) can receive JsonElement and break Python execution/casting logic that previously got native values. Use the declared variableType (or a converter) when deserializing Value to preserve the original type.
Useful? React with 👍 / 👎.
Aligns the repo with the SAM-BIM workspace-wide pin to the LTS-aligned System.Text.Json 8.0.5, replacing the previously pinned 10.0.8 preview.
Pin System.Text.Json to 8.0.5
* fix: pin AssemblyVersion/FileVersion to 1.0.0.0 (drop 1.0.* wildcard) Eliminates CS1607 warnings and restores deterministic builds. Aligns with the workspace's existing fixed-version files. Scope: AssemblyInfo.cs + .csproj version attributes only. The // commented-out template example is left intact for documentation. * fix: add SPDX + copyright header to modified AssemblyInfo.cs and refresh .csproj <Copyright> Satisfies the spdx-check workflow which requires every changed .cs file to declare the LGPL-3.0-or-later SPDX identifier and the 2020-2026 attribution in its first 20 lines. Also updates the stale '<Copyright>Copyright (c) 2020</Copyright>' line in .csproj files to match the SPDX header style.
* build: Directory.Build.props for centralised SAMVersion stamping Mirrors SAM-BIM/SAM#7. Stage 2 of the AssemblyVersion versioning migration. * fix: replace literal u{2013} escape with actual en-dash in SPDX header PowerShell 5.1 doesn't support backtick-u escape sequences; the apply-stage2.ps1 script leaked them as literal text in 'Copyright (c) 2020u{2013}2026'. * fix: relax SAMVersion.g.cs Target condition to != 'true' Codex P1 on SAM_LadybugTools#4: classic (non-SDK) csprojs don't set GenerateAssemblyInfo at all, so the previous '== false' condition skipped them. Switching to '!= true' catches both GenerateAssemblyInfo=false (SDK projects with legacy AssemblyInfo.cs) AND empty (classic projects). * ci: Codex P2 fixes — four-part SAMVersion, prefer head_ref for sow PRs - Append .0 so SAMVersion is 4-part (AssemblyFileVersion expects 4 parts). - Prefer github.head_ref when it matches sow/yyyy-Qx (release-promotion PRs). - Mirrors SAM sow/2026-Q2 6d87d98e.
Mirrors SAM sow/2026-Q2. Adds AssemblyInformationalVersion attribute generation to Path D's SAMVersion.g.cs Target — covers Grasshopper / Tas-bridge assemblies that have GenerateAssemblyInfo=false, so they also get the CI commit SHA stamp in their ProductVersion field. SDK projects pick up InformationalVersion via PropertyGroup auto-gen as before. Local dev builds unchanged.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c470e45fb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # Current sow branch: base_ref on PR events, ref_name on push events. | ||
| $sowRef = if ($baseRef -match '^sow/') { $baseRef } elseif ($refName -match '^sow/') { $refName } else { '' } | ||
| if ($sowRef -and $sowRef -ne $headRef) { $candidates += $sowRef } | ||
| $candidates += 'sow/2026-Q2' |
There was a problem hiding this comment.
Clone dependencies from matching branch family
The new fallback candidate forces dependency repos to sow/2026-Q2 whenever head_ref/base_ref/ref_name are not sow branches (for example, a normal push to main). In that case CI can build this repo against quarter-branch dependencies instead of main/default, which can produce false failures or false greens due to cross-repo version skew.
Useful? React with 👍 / 👎.
| $ErrorActionPreference = 'Stop' | ||
| # Prefer head_ref when its a sow branch (release-promotion PRs from sow/* to main), | ||
| # else use base_ref on PR events / ref_name on push events. | ||
| $headRef = '${{ github.head_ref }}' |
There was a problem hiding this comment.
Escape GitHub refs before injecting into PowerShell
These assignments interpolate untrusted ref names directly inside single-quoted PowerShell literals. Branch names can legally contain apostrophes (for example feature/don't-break), which would terminate the string early and break the workflow script at parse time on PRs/pushes using such refs.
Useful? React with 👍 / 👎.
Mirrors SAM sow/2026-Q2. Adds AssemblyInformationalVersion attribute generation to Path D's SAMVersion.g.cs Target — covers Grasshopper / Tas-bridge assemblies that have GenerateAssemblyInfo=false, so they also get the CI commit SHA stamp in their ProductVersion field. SDK projects pick up InformationalVersion via PropertyGroup auto-gen as before. Local dev builds unchanged.
Summary
Quarterly Q2 2026 work from the SAM-BIM fork merging back into the upstream.
Includes the Newtonsoft.Json → System.Text.Json.Nodes migration of the
entire SAM-BIM stack (per-repo PRs already merged into SAM-BIM's
sow/2026-Q2).Highlights of this quarter
IJSAMObjectimplementations migrated fromJObject/JArray/JTokentoJsonObject/JsonArray/JsonNode.FromJObject/ToJObjectrenamed toFromJsonObject/ToJsonObject.System.Text.Json10.0.8 replacesNewtonsoft.Json13.0.3 in every csproj(except SAM_Revit which keeps Newtonsoft loadable for Revit's runtime).
Log identity loss, SearchWrapper missing type discriminator, RelationCollection
wrong-jObject-passed).
Verification
BuildAlls_v3 RestoreCleanRebuildagainst the merged sow/2026-Q2 chain:0 errors, 144 artifacts.
Test plan
IJSAMObjectAPI renamemasterfrom upstream🤖 Generated with Claude Code