[PR #3426] [CLOSED] fix(plist): preserve complete XML character-data key names #5737

Closed
opened 2026-10-31 01:09:03 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3426
Author: @thangldw
Created: 10/14/2026
Status: ❌ Closed

Base: main ← Head: codex/fix-3371-xml-key-identity


📝 Commits (1)

  • 789e8a6 fix(plist): preserve complete XML character-data key names

📊 Changes

4 files changed (+176 additions, -25 deletions)

View changed files

📝 docs/native-investigation.md (+3 -2)
📝 src/domain/propertyListKeys.test.ts (+24 -4)
📝 src/domain/propertyListKeys.ts (+71 -19)
📝 tests/boundary/cli/keyedArchivePrototypeKeyCli.test.ts (+78 -0)

📄 Description

Summary

Fixes #3371. XML dictionary keys split across text and CDATA now retain their complete names. For example, ma<![CDATA[in]]> stays main, so named-root selection succeeds; user<![CDATA[ID]]> stays userID.

Problem and expected behavior

The pinned plist decoder reads only the first child of a <key>. Inspection therefore returned roots.ma and value.user, with truncated: false, and rejected --root main. Native plutil, plain XML and binary controls retained the complete names. Inspection must preserve those identities and their UID reference paths.

Change and scope

Normalize complete character-data key names at the existing shared XML plist boundary, before the pinned value decoder. Prototype-key omission and placeholder collision checks consume the same identity. Replace only key contents, preserving source values, encoded line endings, depth preflight and the existing handling of unsupported nested markup. Update the owning documentation. No consumer-specific fallback or new dependency.

Contract and boundary impact

  • Semantic owner: parseXmlPropertyList in src/domain/propertyListKeys.ts; callers consume its decoded keys.
  • Contribution scope: ordinary correction within existing inert decoding authority; separate maintainer scope decision not applicable.
  • CLI/MCP: existing schemas and commands; corrected root/field names and root selection.
  • Compatibility: shared XML plist consumers, including keyed archives, Interface Builder and app metadata. OpenStep and binary decoding stay on their existing paths.
  • Evidence: preserve original archive digest, object indices, reference targets and source bytes.
  • Authority/cleanup: no new target execution, network or mutation authority.
  • Generated metadata/package/install: no schema, dependency or version change; ignored outputs are not committed.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Reproduced through compiled CLI on main 322506d0c0d3; four regressions failed before repair (36 other tests passed).

  • Public regression covers root selection, field identity, UID path, original digest and unchanged source bytes, with plain XML and independently encoded binary controls.

  • Owner controls cover segmented prototype keys, placeholder collisions, literal CDATA entities/closing-tag text, encoded line endings and unsupported nested elements.

  • Original compiled CLI and real stdio MCP replay after repair return main, userID: 42, reference path ["main"] and the original digest. Root selection succeeds.

  • Independent subagent review found no actionable findings, independently ran 39 owner tests and 64 compiled-owner stress combinations. It did not rerun the full checks or public transports; the stress oracle uses xmldom.

  • 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

Head 789e8a6e1e9e, rebased onto main 1b97b0f3707b, Node 24.18.0 / npm 11.16.0, macOS arm64. The authored XML fix is preserved. OpenStep scanner/helpers from #4105 are byte-identical to main, and both newer regression cases remain included. The rebased tree matches the independently checked three-way integration tree.

  • npm run test:focused with 15 exact parser/consumer/CLI/MCP files — 227 passed, one platform skip. Includes keyed-archive number/nesting/encoding controls and Interface Builder consumers.
  • npm run check — passed typecheck, lint, formatting, knip, metadata, module boundaries and architecture guards.
  • npm run docs:check — passed, including five consistency tests.
  • npm run verify:test-discovery — all 1,412 test files discovered exactly once.
  • git diff --check — passed.
  • Fresh real stdio MCP replay on the rebased head — both full and root: "main" inspection retain main, userID: 42, the UID edge and original archive digest.
  • GitHub CI for the rebased head will run separately; previous green checks apply to the pre-rebase head.

Compatibility, safety, and release

Corrects XML key decoding without a caller migration or package/release change. Local validation is macOS arm64; Linux/Windows and the full CI suite have not been executed locally. Synthetic archives and native plutil controls do not measure occurrence in real application archives. No near-64-MiB peak-memory qualification or real disassembler run is claimed.

Author readiness

Human owner: @thangldw

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff 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/3426 **Author:** [@thangldw](https://github.com/thangldw) **Created:** 10/14/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `codex/fix-3371-xml-key-identity` --- ### 📝 Commits (1) - [`789e8a6`](https://github.com/morluto/rea/commit/789e8a6e1e9e531f7402dc94752bf03980d0c43a) fix(plist): preserve complete XML character-data key names ### 📊 Changes **4 files changed** (+176 additions, -25 deletions) <details> <summary>View changed files</summary> 📝 `docs/native-investigation.md` (+3 -2) 📝 `src/domain/propertyListKeys.test.ts` (+24 -4) 📝 `src/domain/propertyListKeys.ts` (+71 -19) 📝 `tests/boundary/cli/keyedArchivePrototypeKeyCli.test.ts` (+78 -0) </details> ### 📄 Description ## Summary Fixes #3371. XML dictionary keys split across text and CDATA now retain their complete names. For example, `ma<![CDATA[in]]>` stays `main`, so named-root selection succeeds; `user<![CDATA[ID]]>` stays `userID`. ## Problem and expected behavior The pinned plist decoder reads only the first child of a `<key>`. Inspection therefore returned `roots.ma` and `value.user`, with `truncated: false`, and rejected `--root main`. Native `plutil`, plain XML and binary controls retained the complete names. Inspection must preserve those identities and their UID reference paths. ## Change and scope Normalize complete character-data key names at the existing shared XML plist boundary, before the pinned value decoder. Prototype-key omission and placeholder collision checks consume the same identity. Replace only key contents, preserving source values, encoded line endings, depth preflight and the existing handling of unsupported nested markup. Update the owning documentation. No consumer-specific fallback or new dependency. ## Contract and boundary impact - Semantic owner: `parseXmlPropertyList` in `src/domain/propertyListKeys.ts`; callers consume its decoded keys. - Contribution scope: ordinary correction within existing inert decoding authority; separate maintainer scope decision not applicable. - CLI/MCP: existing schemas and commands; corrected root/field names and root selection. - Compatibility: shared XML plist consumers, including keyed archives, Interface Builder and app metadata. OpenStep and binary decoding stay on their existing paths. - Evidence: preserve original archive digest, object indices, reference targets and source bytes. - Authority/cleanup: no new target execution, network or mutation authority. - Generated metadata/package/install: no schema, dependency or version change; ignored outputs are not committed. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Reproduced through compiled CLI on main `322506d0c0d3`; four regressions failed before repair (36 other tests passed). - Public regression covers root selection, field identity, UID path, original digest and unchanged source bytes, with plain XML and independently encoded binary controls. - Owner controls cover segmented prototype keys, placeholder collisions, literal CDATA entities/closing-tag text, encoded line endings and unsupported nested elements. - Original compiled CLI and real stdio MCP replay after repair return `main`, `userID: 42`, reference path `["main"]` and the original digest. Root selection succeeds. - Independent subagent review found no actionable findings, independently ran 39 owner tests and 64 compiled-owner stress combinations. It did not rerun the full checks or public transports; the stress oracle uses xmldom. - [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 Head `789e8a6e1e9e`, rebased onto main `1b97b0f3707b`, Node 24.18.0 / npm 11.16.0, macOS arm64. The authored XML fix is preserved. OpenStep scanner/helpers from #4105 are byte-identical to main, and both newer regression cases remain included. The rebased tree matches the independently checked three-way integration tree. - `npm run test:focused` with 15 exact parser/consumer/CLI/MCP files — 227 passed, one platform skip. Includes keyed-archive number/nesting/encoding controls and Interface Builder consumers. - `npm run check` — passed typecheck, lint, formatting, knip, metadata, module boundaries and architecture guards. - `npm run docs:check` — passed, including five consistency tests. - `npm run verify:test-discovery` — all 1,412 test files discovered exactly once. - `git diff --check` — passed. - Fresh real stdio MCP replay on the rebased head — both full and `root: "main"` inspection retain `main`, `userID: 42`, the UID edge and original archive digest. - GitHub CI for the rebased head will run separately; previous green checks apply to the pre-rebase head. ## Compatibility, safety, and release Corrects XML key decoding without a caller migration or package/release change. Local validation is macOS arm64; Linux/Windows and the full CI suite have not been executed locally. Synthetic archives and native `plutil` controls do not measure occurrence in real application archives. No near-64-MiB peak-memory qualification or real disassembler run is claimed. ## Author readiness Human owner: @thangldw - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff 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 01:09:03 +00:00
bsakaguchi changed title from [PR #3426] [CLOSED] fix(plist): preserve complete XML character-data key names to [PR #3426] fix(plist): preserve complete XML character-data key names 2026-11-03 13:30:28 +00:00
bsakaguchi changed title from [PR #3426] fix(plist): preserve complete XML character-data key names to [PR #3426] [CLOSED] fix(plist): preserve complete XML character-data key names 2026-11-03 14:32:12 +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#5737
No description provided.