Files
AptXmlAI/ra3apt-cli/ROUNDTRIP_REPORT.md
lanyi e0b8dedc04 Fix APT CLI roundtrip visual and script preservation
Preserve edittext channels, alpha/color transforms, inactive placement fields,
zero ratio/clipping and null ClipAction presence. Keep unlabelled flag bits,
quoted/escaped script strings, export declarations and correctly typed CONST
and pushdata values. Validate signed integers and write byte-aligned UTF-8.

Add 23 public CLI regressions and record the native 174-resource batch plus
bounded retests: four discovered pages are repaired, while the sound placeholder
and native float formatting remain explicit accuracy limits. Rebuild the 1.0.1
Windows executable and leave unrelated SDK changes untouched.
2026-10-13 02:40:37 +02:00

7.8 KiB

Native roundtrip verification — 2026-10-13

The demonstrated JavaScript defects are repairable and have been fixed. Globally exact roundtrips are not established: native float32 output loses precision, and one SDK resource's sound character cannot be rebuilt from the native XML placeholder.

Full resource regression

All 174 SDK Data/original-aptui APTs were tested through the real public Node CLI and cc3tools in three isolated batches of 58. The first repair draft produced these results:

Result Pages Finding
Expanded UI fields equal 169 No represented script/layout/color/geometry differences
Expanded UI flag changed 3 Empty HasClipAction array omitted by apt2xml, then presence bit cleared by build
expand rejected 1 VerticalScrollBar button 171, third buttonaction flags=64; missing symbolic name for 0x40
build rejected 1 sampleMissionBriefing contains a valid sound character that cc3tools exports incompletely

The final repair preserves the original active clip-action bit with its null pointer, without adding an empty array, in HUDVoiceChatControlPanel, TacticalHUDBeaconStage and TacticalQuickChatDialog. It preserves unlabelled flag bits explicitly as hexadecimal terms, without assigning guessed engine meanings. Fresh final-source and final-EXE native roundtrips on all four affected pages had zero expanded UI differences. sampleMissionBriefing now fails with an accurate unsupported sound-payload diagnostic instead of Duplicate ids: undefined.

Thus 173/174 resources have successful, matching expanded representations using the first-draft results plus the four bounded retests. This is not a claim that all 174 were rerun with the final source, nor that the original float32 values are bit-exact. The later code changes affect missing empty-array markers, previously unknown flag bits and native not-implemented placeholders; the original successful cases and raw comparisons provide the unchanged-path evidence.

The XML comparison included every represented attribute, child order, instruction/string and RU geometry record. Only XML indentation/blank lines and outer assembly/RU line indentation were normalized. Native raw checks covered the 172 initially successful pages separately, including fields omitted by the human-readable expansion. Their 7136 definefunction2 records retained flags, sizes and argument fields; there is no observed Suppress-flags loss in this corpus. Raw differences comprised 28500 constant-pool record/order changes, 88621 pool-reference index changes and the three known clip-action flags; there were no other raw field/structure changes. Final-EXE raw retests of the four repaired pages and author loading/disconnect pages retained all non-pool raw fields.

All 172 initially successful pages retained resolved DAT -> Texture declaration -> material file/format/mipmap/resize attributes. Original raw manifest/DAT order and numbering differences were retained as differences; a separate check compared resolved attributes, unused texture declarations and other manifest declarations. Texture pixels were not copied or rendered. Only 4 APTs and 15 CONSTs were byte-identical in the initial native batch; most are repooled/relocated, and equal raw decimal output cannot prove all original float bits.

Author pages and targeted tests

The first repair source and first EXE draft also tested all eight author Core13 modified pages with zero expanded UI differences and unchanged resolved resources. Their native raw differences were pool records/indices only; all function2 fields matched. Final-source/EXE changes were independently checked on the fault pages, and the final EXE again tested the author loading/disconnect pages. No author-before package was inferred: Core13 modified APT/CONST/geometry streams were combined with SDK manifest/DAT descriptions and author geometry overrides.

All 23 public CLI tests passed after installing the final source, with no skips. They use the actual Node dispatcher, XML transformations and CONST writer, substituting explicit test envelopes only at the cc3tools subprocess boundary. Tests cover deliberate height/RGB/translation edits with unrelated-field assertions, alpha/additive flags, active zero ratio/clipping, empty clip arrays, quotes/backslashes/commas/entities/CDATA, prototype-name pools/exports, signed32/overflow/fractional rejection, UTF-8 byte lengths/alignment, pushdata and the two full-corpus diagnostics. See test/README.md for the transport limit.

Eight previously failing minimal raw APT cases were also rebuilt through real converters with the final source; expanded state, exports and decoded action attributes matched. Separate real native cases retained 512-byte ASCII and Chinese UTF-8 constants and rejected pushconst 1.25. UTF-8 readback proves stored bytes and decoding here, not game font support.

Remaining native limitations

  1. Float precision: apt2xml emits many float32 fields with six decimal places. A valid pushfloat 0.3333333432674408 writes opcode/payload b4 ab aa aa 3e, but expands to 0.333333 and rebuilds to b4 9f aa aa 3e at offset 132. The final CLI still reproduces this loss. Both binaries expand to the same decimal text. A precise native formatter or separately designed binary-preservation method is required; the JavaScript parser cannot recover digits already lost.
  2. Sound payload: sampleMissionBriefing has a valid non-null character at slot 31, APT offset 932, type 6, signature 0x09876543. Native apt2xml produces only <sound code="6" comment="not implemented yet!"/>, without its character ID/payload. The CLI now identifies that limitation and stops; it does not delete the character, replace it with null, or declare the original input invalid. Supporting this page requires native type-6 write support or a verified preservation path.

Native converter binaries were unchanged. Therefore these repairs do not justify saying every original APT can undergo an accurate, lossless roundtrip. Game resource replacement and gameplay acceptance remain separate from this CLI regression.

Identity and reproduction

Starting source revision: 5511354, aptxmlai Git repository. The initial source was frozen throughout the three original batches and the eight-page author/EXE batches; later fixes were isolated in separate source copies. test/original-roundtrip-inputs.json records all 174 relative APT paths plus APT/CONST/DAT/manifest input sizes and SHA-256 identities.

Author Core13 SHA-256: 0d22861bff7e1b947215017d2c3e9e0d632dada9c6ea7af48a3d78ebeec28c49. Final Windows EXE: 1.0.1, 94110008 bytes, SHA-256 341d53a34bff107d60d16a34b0401930e00f13f22917ef355d2e2153353548a0. Built with installed @yao-pkg/pkg 6.12.0 and cached Node 24 Windows runtime. Source tests and final executable tests are reported separately above.

For each original, run expand to a private same-basename edit XML, build to a private same-basename APT, then expand that output and compare. Use explicit --tools-path and keep original CONST/DAT/manifest/geometry together. Compare manifest/DAT separately, resolve coordinated numeric indices, and run raw apt2xml on private copies to inspect fields hidden by expansion. Re-expand with this CLI before editing: older edit XML may contain inactive defaults or ambiguous string escapes.

Transient scripts, logs, command/identity receipts and full diffs were isolated under the RA3 analysis workspace .work/ui_author_compare_20261012/cli_fix_20261013. Commands recorded begin/end state before proceeding and bound TEMP/TMP/cwd to private directories. Large duplicate texts were losslessly gzipped with verified original hashes; bulk generated binaries/payloads were cleaned after analysis while retaining receipts/diffs and small failure evidence. No game was launched for this repair, no priority resource or production Native source was changed, and unrelated SDK working-tree changes were left intact.