[PR #2106] [MERGED] fix(artifacts): preserve NIB field and class identities #5031

Closed
opened 2026-10-31 00:59:22 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2106
Author: @1NormalGuy
Created: 10/12/2026
Status: ✅ Merged
Merged: 10/13/2026
Merged by: @morluto

Base: main ← Head: fix/nib-field-identities


📝 Commits (1)

  • 1a1667b fix(artifacts): preserve NIB field and class identities

📊 Changes

2 files changed (+120 additions, -2 deletions)

View changed files

📝 src/artifacts/apple/NibArchive.ts (+10 -2)
➕ tests/acceptance/applications/nibFieldIdentity.test.ts (+110 -0)

📄 Description

Summary

Preserve literal NIBArchive field and class names in Interface Builder evidence. Two data-loss defects were reproduced against upstream 0d5033ad1; no related issue was found.

Problem and expected behavior

A serialized __proto__ field was assigned through an ordinary object's inherited setter, so it disappeared from the result. Separately, the UTF-8 decoder stripped an initial U+FEFF from length-prefixed keys and class names. Distinct keys enabled and \uFEFFenabled consequently collapsed, with the second value overwriting the first.

For the regression fixture, both public adapters previously returned nibValues: { constructor: 7, enabled: false }. They now retain __proto__: { objectID: "1" }, constructor: 7, enabled: true, and \uFEFFenabled: false, as well as the exact \uFEFFCustomView class name and a numeric __proto__ field on the second object.

Change and scope

Create own data properties at the NIB field-decoding boundary and disable BOM consumption for the format's length-prefixed UTF-8 names. Malformed UTF-8 remains rejected. The graph projection already uses Object.fromEntries, and the shared JSON-value boundary preserves literal keys, so no downstream repair is needed.

Contract and boundary impact

  • Semantic owner and earliest changed stage: NIBArchive field/name decoding.
  • CLI and MCP/tool-catalog contract: unchanged schemas; corrected decode-interface-builder / decode_interface_builder evidence.
  • Provider, bridge, target-format, or platform compatibility: static NIBArchive reader; no external provider changes.
  • Evidence, artifact, provenance, or reconstruction contract: preserve field/class identities, both distinct values, original archive digest and bytes.
  • Process execution, authorization, cleanup, or containment impact: none; fixture target is not executed.
  • Generated metadata, package, or installation impact: none.

Evidence and regression coverage

  • Added a compiled CLI plus real stdio MCP acceptance workflow using a generated NIBArchive byte fixture. It covers object-valued and numeric __proto__, distinct BOM-prefixed keys, class identity, adapter parity and source integrity.

  • The new workflow failed on the unmodified base with the missing and overwritten fields shown above, then passed after the fix.

  • Native Xcode production of these unusual names was not verified; the new regression uses the existing format fixture encoder, not a simulated provider.

  • Observed, derived, and inferred claims remain distinguishable.

  • Artifact identity, source provenance, and failed attempts remain preserved.

  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

Using Node 24.18.0 and npm 11.16.0 on macOS:

  • npm run test:focused -- tests/acceptance/applications/nibFieldIdentity.test.ts src/artifacts/apple/NibArchive.test.ts src/artifacts/apple/NibViewHierarchy.test.ts tests/boundary/mcp/promptCompletion.test.ts — 23 passed on the rebased branch, including CLI, stdio MCP and cold/warm prompt completion.
  • npm run test:local -- src/artifacts/apple/NibArchive.test.ts src/artifacts/apple/NibViewHierarchy.test.ts — 16 passed.
  • Expanded focused run including tests/boundary/filesystem/interfaceBuilderBundle.test.ts — 56 passed, 2 failed because this host lacks Xcode ibtool and its Swift compiler rejects a trailing comma in the existing keyed-archive-hierarchy.swift fixture. These host/toolchain gaps remain unverified; the new acceptance test passed in that run.
  • npm run verify:test-discovery — all 916 files discovered exactly once.
  • npm run check — passed, including typecheck, lint (0 errors), formatting, module boundaries and architecture guards.
  • npm run verify:package — passed on macOS arm64, including packaged MCP prompt completion and lifecycle. Local loopback addresses were excluded from this host's HTTP proxy.
  • git diff --check — passed.
  • Rebased onto upstream e4d3e1399; the prior CI failures in prompt completion and macOS packaged smoke were corrected upstream by 621cee192 and fe4b94a66.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: macOS filesystem, compiled CLI and stdio MCP; external engines are not involved. Xcode coverage is limited as described above.
  • Package or release metadata impact: none.
  • Security/privacy review: archive keys become own data properties instead of invoking prototype setters; no target execution or global prototype mutation.

Review checklist

  • Concrete, reproduced problem and focused Conventional Commit title.
  • No related issue; regression discovered during source review.
  • Observable behavior covered through public workflows.
  • Contracts and generated metadata unchanged.
  • Representative before/after evidence included.
  • Final diff checked for secrets, unrelated cleanup and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2106 **Author:** [@1NormalGuy](https://github.com/1NormalGuy) **Created:** 10/12/2026 **Status:** ✅ Merged **Merged:** 10/13/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/nib-field-identities` --- ### 📝 Commits (1) - [`1a1667b`](https://github.com/morluto/rea/commit/1a1667b6fea7c7c88fbc38a6b97fcd722ab6db23) fix(artifacts): preserve NIB field and class identities ### 📊 Changes **2 files changed** (+120 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `src/artifacts/apple/NibArchive.ts` (+10 -2) ➕ `tests/acceptance/applications/nibFieldIdentity.test.ts` (+110 -0) </details> ### 📄 Description ## Summary Preserve literal NIBArchive field and class names in Interface Builder evidence. Two data-loss defects were reproduced against upstream `0d5033ad1`; no related issue was found. ## Problem and expected behavior A serialized `__proto__` field was assigned through an ordinary object's inherited setter, so it disappeared from the result. Separately, the UTF-8 decoder stripped an initial U+FEFF from length-prefixed keys and class names. Distinct keys `enabled` and `\uFEFFenabled` consequently collapsed, with the second value overwriting the first. For the regression fixture, both public adapters previously returned `nibValues: { constructor: 7, enabled: false }`. They now retain `__proto__: { objectID: "1" }`, `constructor: 7`, `enabled: true`, and `\uFEFFenabled: false`, as well as the exact `\uFEFFCustomView` class name and a numeric `__proto__` field on the second object. ## Change and scope Create own data properties at the NIB field-decoding boundary and disable BOM consumption for the format's length-prefixed UTF-8 names. Malformed UTF-8 remains rejected. The graph projection already uses `Object.fromEntries`, and the shared JSON-value boundary preserves literal keys, so no downstream repair is needed. ## Contract and boundary impact - Semantic owner and earliest changed stage: NIBArchive field/name decoding. - CLI and MCP/tool-catalog contract: unchanged schemas; corrected `decode-interface-builder` / `decode_interface_builder` evidence. - Provider, bridge, target-format, or platform compatibility: static NIBArchive reader; no external provider changes. - Evidence, artifact, provenance, or reconstruction contract: preserve field/class identities, both distinct values, original archive digest and bytes. - Process execution, authorization, cleanup, or containment impact: none; fixture target is not executed. - Generated metadata, package, or installation impact: none. ## Evidence and regression coverage - Added a compiled CLI plus real stdio MCP acceptance workflow using a generated NIBArchive byte fixture. It covers object-valued and numeric `__proto__`, distinct BOM-prefixed keys, class identity, adapter parity and source integrity. - The new workflow failed on the unmodified base with the missing and overwritten fields shown above, then passed after the fix. - Native Xcode production of these unusual names was not verified; the new regression uses the existing format fixture encoder, not a simulated provider. - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed Using Node 24.18.0 and npm 11.16.0 on macOS: - `npm run test:focused -- tests/acceptance/applications/nibFieldIdentity.test.ts src/artifacts/apple/NibArchive.test.ts src/artifacts/apple/NibViewHierarchy.test.ts tests/boundary/mcp/promptCompletion.test.ts` — 23 passed on the rebased branch, including CLI, stdio MCP and cold/warm prompt completion. - `npm run test:local -- src/artifacts/apple/NibArchive.test.ts src/artifacts/apple/NibViewHierarchy.test.ts` — 16 passed. - Expanded focused run including `tests/boundary/filesystem/interfaceBuilderBundle.test.ts` — 56 passed, 2 failed because this host lacks Xcode `ibtool` and its Swift compiler rejects a trailing comma in the existing `keyed-archive-hierarchy.swift` fixture. These host/toolchain gaps remain unverified; the new acceptance test passed in that run. - `npm run verify:test-discovery` — all 916 files discovered exactly once. - `npm run check` — passed, including typecheck, lint (0 errors), formatting, module boundaries and architecture guards. - `npm run verify:package` — passed on macOS arm64, including packaged MCP prompt completion and lifecycle. Local loopback addresses were excluded from this host's HTTP proxy. - `git diff --check` — passed. - Rebased onto upstream `e4d3e1399`; the prior CI failures in prompt completion and macOS packaged smoke were corrected upstream by `621cee192` and `fe4b94a66`. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: macOS filesystem, compiled CLI and stdio MCP; external engines are not involved. Xcode coverage is limited as described above. - Package or release metadata impact: none. - Security/privacy review: archive keys become own data properties instead of invoking prototype setters; no target execution or global prototype mutation. ## Review checklist - [x] Concrete, reproduced problem and focused Conventional Commit title. - [x] No related issue; regression discovered during source review. - [x] Observable behavior covered through public workflows. - [x] Contracts and generated metadata unchanged. - [x] Representative before/after evidence included. - [x] Final diff checked for secrets, unrelated cleanup and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 00:59:22 +00:00
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#5031
No description provided.