Skip to content

fix(python): Windows bindings invalidate canonical reference hashes #77

Description

@viktar-b

What happened

Generating bindings on Windows changes the byte identity of the canonical two-panel calculation's source closure, despite unchanged authored files and inputs. The checked-in independent reference no longer matches. Root npm run dev exits before launching the demo:

Error: two-panel-width-2: the canonical reference did not pass. Review source changes and reference bindings before regenerating.

Suggested priority: P1. This blocks the documented repository demo on native Windows. Cross-platform reference portability also breaks: callers can receive independentReferenceAgreement: not_applicable for the canonical inputs instead of the expected pass. This is not a numerical mismatch or a failed-reference check.

What you expected

Generated binding bytes and their source-closure identity are deterministic across Windows and Linux for identical source bytes, generation root layout, package version and inputs. The canonical width-2 reference should match after the documented binding generation step on either platform.

Keep exact-byte source provenance; do not solve this by ignoring changed hashes or automatically rebinding independent references.

How to reproduce

Prerequisites: native Windows Python 3.11+ and Git. Use a fresh directory. The clone explicitly disables CRLF checkout conversion so this isolates generated binding differences from authored-file checkout differences.

In PowerShell:

git -c core.autocrlf=false clone https://github.com/viktar-b/CalculationSourceObject.git cso-binding-repro
Set-Location cso-binding-repro
git checkout f3a5b7f16e4d7f964362bed3dcb717df04046b51
python -m venv .venv
$env:PYTHON = (Resolve-Path .venv\Scripts\python.exe).Path
& $env:PYTHON -m pip install ./packages/cso-python
& $env:PYTHON -I -m cso_python bindings examples/two-panel

$raw = & $env:PYTHON -I -m cso_python execute examples/two-panel/estimate.cso.py --function estimate --inputs-json '{}'
$capture = $raw | ConvertFrom-Json
$reference = Get-Content examples/two-panel/reference.json -Raw | ConvertFrom-Json
$capture.ok
$capture.execution.entry.sourceHash
$reference.cases[0].binding.entrySourceHash
$capture.execution.sourceClosureHash
$reference.cases[0].binding.sourceClosureHash
Get-Content examples/two-panel/_cso_bindings/geometry.py

The empty inputs object uses the declared defaults, including width 2, matching the canonical reference and avoiding embedded-quote differences between PowerShell versions.

Actual values in the tested environment:

capture.ok: True
entry source hash (actual and reference):
f68b3e04ef696441bf328127a4f438d34ae373e63c7f054b4b817f98bf2a18d3

actual Windows closure:
a3c6f084b2f6a4a1e1eec5ef4023bbc0d8e01b1c69a05cd16167c737cb27d67a

reference closure:
efd06bb6a77b704d0d342d465602659d8c2e81a45dd3d1239797be711035f0bd

To reproduce the visible startup failure, continue with native Node.js 24+ and npm:

npm ci
npm run dev

The canonical reference check fails before the app is launched. A separate Windows npm-launch problem exists downstream (#78) and should be fixed independently.

Cause and confirmation

Two platform-dependent details in binding generation are included in captured source hashes:

  1. os.path.relpath(source, target.parent) emits Windows backslash path literals.
  2. os.fdopen(descriptor, "w") writes CRLF with the default Windows newline convention.

In a disposable diagnostic copy, without changing any authored files or expected reference numbers:

Generated binding representation Closure SHA-256
Windows paths + CRLF a3c6f084b2f6a4a1e1eec5ef4023bbc0d8e01b1c69a05cd16167c737cb27d67a
Windows paths + LF d4e08cfa104eca3ff3cbe346e55d5c23e137660eaa0c3c7d185a629c18daa7eb
Forward-slash paths + LF efd06bb6a77b704d0d342d465602659d8c2e81a45dd3d1239797be711035f0bd

The last value exactly matches the checked-in reference. This diagnostic normalization was not applied as a source fix.

Environment

Windows 11 Pro x64; native Windows Node.js 24.19.0 and Python 3.12.14. Tested 28 September 2026. Repository commit: f3a5b7f16e4d7f964362bed3dcb717df04046b51 (current main at filing).

Installed Python wheel: cs-object==0.1.0 built from the tested checkout. Entry source bytes were LF. Native Windows execution, not Linux Python.

Relevant code

Acceptance criteria

  • Binding generation uses portable relative path literals and explicit UTF-8/LF serialization.
  • Identical LF source fixtures generate byte-identical runtime bindings on Windows and Linux.
  • The existing canonical width-2 reference passes after fresh Windows generation, without silently weakening provenance checks or regenerating expected values.
  • Add Windows regression coverage for generation and matching reference agreement.
  • Document/enforce authored-file line ending policy where needed; ordinary Windows Git CRLF conversion is a separate way to change exact source identity.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions