[GH-ISSUE #4834] [Bug] Plist inspection reports a negative-zero real as observed positive zero #3006

Closed
opened 2026-10-31 00:34:43 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @xu91102 on GitHub (Oct 17, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4834

Before submitting

  • I searched open and closed issues and PRs for this behavior.
  • The examples contain only self-authored fixtures and no private target data.

Observed behavior

On current main 742b6f587f3c4ef1b8212e7376d6f3a305b194dc, the rebuilt CLI reports a serialized negative-zero real as ordinary JSON 0, with object status and Evidence confidence observed. Positive zero produces the same scalar. No limitation discloses the lost sign.

This reproduces for an XML keyed archive, its native plutil binary conversion, and an actual binary archive generated by Foundation NSKeyedArchiver from NSNumber(value: -Double.zero). The native conversion/Python plist reader retains -0.0; the generated Foundation number reports sign minus. Positive zero and 1.25 controls retain their expected values. All input digests remained unchanged.

Reproduction

The XML fixture actually inspected is:

<plist version="1.0"><dict>
<key>$archiver</key><string>NSKeyedArchiver</string>
<key>$version</key><integer>100000</integer>
<key>$objects</key><array><string>$null</string><real>-0.0</real></array>
<key>$top</key><dict><key>root</key><dict><key>CF$UID</key><integer>1</integer></dict></dict>
</dict></plist>

Run the built source CLI with inspect-keyed-archive /absolute/path/to/negative-zero.plist --json. The second object is returned as {"id":1,"kind":"scalar","status":"observed","value":0} (other fields omitted here). Replacing only the real with 0.0 or 1.25 supplies the controls.

I also generated three real Foundation archives using NSKeyedArchiver.archivedData(withRootObject: number, requiringSecureCoding: false) for NSNumber(value: -Double.zero), NSNumber(value: Double.zero), and NSNumber(value: 1.25). Each was 146 bytes. The negative archive SHA-256 was 8abae6e31ae9c6b8f08874b9feff070dfc2da0e3b14bbc786e01f616bc872924; its decoded $objects[1] remained negative zero before REA's JSON projection. All three CLI calls exited 0.

The actual native inspect-plist CLI also reproduces the loss for that negative-zero Foundation archive through its plutil XML fallback. No MCP result or installed-package result has been claimed yet.

Expected behavior and impact

Preserve the distinction between a negative-zero real and positive zero in the JSON-safe plist scalar representation, or disclose an explicit unknown instead of asserting positive zero. These are distinguishable serialized IEEE floating-point values; changing the sign loses a fact in numeric/geometry data being inspected. Observed impact is deterministic on these small fixtures; occurrence in third-party applications is unknown.

Analysis and duplicate check

The decoded number retains negative zero, but projectPlistValue passes finite numbers through unchanged. JSON serialization erases the sign. The existing typed-scalar producer already preserves data, dates, big integers, and non-finite reals, so this belongs at that shared projection boundary and its consumers, rather than in CLI-only formatting.

I read the current production diffs of #4317, #4422, #4047 and #4054. They address scalar kind identity, wide binary integers, or XML real character data; none preserves negative zero at JSON projection. This report is distinct from #3876's large-integer precision and #4042's CDATA decoding.

Environment and limits

Source main above; Node 24.18.0; macOS arm64; source build. Read-only self-authored XML/binary plists and actual Foundation-generated archives. Windows/Linux, external application frequency, and performance are NOT RUN. The separate exploratory split-date fixture was rejected by native plutil and is not evidence for this issue.

Local follow-up and overlap

Apple plutil -convert json retains a -0 token, while its XML conversion can erase the original zero sign even for the real Foundation archive above. Converted XML real zero therefore has a known magnitude but an unverified sign; it must not be reported as an observed positive sign. Integer zero and UID 0 remain numeric.

PR #4839 now changes the same shared negative-zero projection and native JSON root. I read its complete current diff and will not submit a duplicate PR. I have not run that PR head, so this is a source-overlap observation, not a claim that its complete range or native XML conversion behavior has been verified. My local experiments and fixes remain unpublished.

Originally created by @xu91102 on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4834 ### Before submitting - [x] I searched open and closed issues and PRs for this behavior. - [x] The examples contain only self-authored fixtures and no private target data. ### Observed behavior On current main `742b6f587f3c4ef1b8212e7376d6f3a305b194dc`, the rebuilt CLI reports a serialized negative-zero real as ordinary JSON `0`, with object status and Evidence confidence `observed`. Positive zero produces the same scalar. No limitation discloses the lost sign. This reproduces for an XML keyed archive, its native `plutil` binary conversion, and an actual binary archive generated by Foundation `NSKeyedArchiver` from `NSNumber(value: -Double.zero)`. The native conversion/Python plist reader retains `-0.0`; the generated Foundation number reports sign `minus`. Positive zero and `1.25` controls retain their expected values. All input digests remained unchanged. ### Reproduction The XML fixture actually inspected is: ```xml <plist version="1.0"><dict> <key>$archiver</key><string>NSKeyedArchiver</string> <key>$version</key><integer>100000</integer> <key>$objects</key><array><string>$null</string><real>-0.0</real></array> <key>$top</key><dict><key>root</key><dict><key>CF$UID</key><integer>1</integer></dict></dict> </dict></plist> ``` Run the built source CLI with `inspect-keyed-archive /absolute/path/to/negative-zero.plist --json`. The second object is returned as `{"id":1,"kind":"scalar","status":"observed","value":0}` (other fields omitted here). Replacing only the real with `0.0` or `1.25` supplies the controls. I also generated three real Foundation archives using `NSKeyedArchiver.archivedData(withRootObject: number, requiringSecureCoding: false)` for `NSNumber(value: -Double.zero)`, `NSNumber(value: Double.zero)`, and `NSNumber(value: 1.25)`. Each was 146 bytes. The negative archive SHA-256 was `8abae6e31ae9c6b8f08874b9feff070dfc2da0e3b14bbc786e01f616bc872924`; its decoded `$objects[1]` remained negative zero before REA's JSON projection. All three CLI calls exited 0. The actual native `inspect-plist` CLI also reproduces the loss for that negative-zero Foundation archive through its `plutil` XML fallback. No MCP result or installed-package result has been claimed yet. ### Expected behavior and impact Preserve the distinction between a negative-zero real and positive zero in the JSON-safe plist scalar representation, or disclose an explicit unknown instead of asserting positive zero. These are distinguishable serialized IEEE floating-point values; changing the sign loses a fact in numeric/geometry data being inspected. Observed impact is deterministic on these small fixtures; occurrence in third-party applications is unknown. ### Analysis and duplicate check The decoded number retains negative zero, but `projectPlistValue` passes finite numbers through unchanged. JSON serialization erases the sign. The existing typed-scalar producer already preserves data, dates, big integers, and non-finite reals, so this belongs at that shared projection boundary and its consumers, rather than in CLI-only formatting. I read the current production diffs of #4317, #4422, #4047 and #4054. They address scalar kind identity, wide binary integers, or XML real character data; none preserves negative zero at JSON projection. This report is distinct from #3876's large-integer precision and #4042's CDATA decoding. ### Environment and limits Source main above; Node 24.18.0; macOS arm64; source build. Read-only self-authored XML/binary plists and actual Foundation-generated archives. Windows/Linux, external application frequency, and performance are NOT RUN. The separate exploratory split-date fixture was rejected by native plutil and is not evidence for this issue. ### Local follow-up and overlap Apple `plutil -convert json` retains a `-0` token, while its XML conversion can erase the original zero sign even for the real Foundation archive above. Converted XML real zero therefore has a known magnitude but an unverified sign; it must not be reported as an observed positive sign. Integer zero and UID 0 remain numeric. PR #4839 now changes the same shared negative-zero projection and native JSON root. I read its complete current diff and will not submit a duplicate PR. I have not run that PR head, so this is a source-overlap observation, not a claim that its complete range or native XML conversion behavior has been verified. My local experiments and fixes remain unpublished.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3006
No description provided.