Production parity implementation — 2026-09-09
Neither delivery gate is complete. This records implementation and verification following the source audit; it does not replace the broader coverage contract or certify Adventure Arena as 1:1.
Implemented
- Removed the batch-only stack sizing, text-width subtraction, and padding wrappers. Both candidates now exercise the ordinary Lua/native constructors.
- AppKit and UIKit stacks measure current content, inherit flexibility by axis, preserve explicit zero sizes, ignore hidden siblings, and distribute weighted spacers. Constrained HStacks negotiate text widths; native labels wrap and recover their intrinsic size after resizing or editing.
- Corrected AppKit multiline paragraph metrics, native label drawing mode, and asymmetric top/bottom padding. Text rendering remains a native NSTextField.
- Corrected scroll document measurement and clipping. AppKit preserves the top reading position across viewport changes; UIKit no longer resets scroll offset on every layout pass or inherits old document widths/heights.
- Native macOS tabs preserve initial/current selection and fill their parent. Selected content receives layout after native tab selection and resizing.
- Added AppKit NavigationStack through public NSPageController. UIKit uses UINavigationController and restores native titles/Back behavior for pushed screens. Both expose depth/currentController and retain root page state.
- UIKit TextField now separates value from placeholder and dispatches native editing/Return events through the same onChange/onCommand contract as AppKit.
- AppKit Image accepts the path property and uses native NSImageView centering and clipping for aspect fill. Image modes and clear/restore round-trip on both platforms. Plain/icon AppKit buttons use NSButton instead of an opaque compound card. Stack overlays can opt out of hit testing with allowsHitTesting=false; the hero artwork button is reachable beneath its caption overlay.
- Adventure Arena catalog data now preserves all nine sorted source entries, descriptions, genres, corrected counts, and all 21 reviews. Views and session state were extracted from the controller. Catalog → detail → session stays in one app root, with a typed-command composer and startup-error recovery. The fabricated ongoing-session row was removed.
- ZIL loading and execution restore global IO/import paths after success or failure, including streamed iOS reads. This is not full runtime-state isolation or deterministic replay.
- Screenshot capture applies requested size before its settling interval, uses process arguments instead of shell interpolation, and returns failure for missing captures. Native macOS captures required execution outside the sandbox; sandboxed captures could not access WindowServer images.
Verification
make test parity-check uikit ios-host: 57/57 Lua test files pass; 13 gallery cases validate; AppKit and both UIKit build targets succeed.- Python batch protocol suite: 8/8 pass.
lua/parity/contracts.lua: 63 native assertions, invoked by the macOS headless test and the live UIKit batch host. Covers empty/fixed/hidden stacks, resize and text mutation, weighted spacers, asymmetric padding, editing events, navigation, overlay hit testing, and image-property round-trips.- Independent SwiftUI geometry comparison, without candidate adapter adjustments: macOS 222/224, iOS 218/224. These are geometry results only; no gallery case or delivery gate was promoted to verified.
- Final source/build/run identities and remaining case IDs are retained in
production-geometry-2026-09-09.json.
Full generated runs are under
build/parity/runs/parity-production-macos-008andbuild/parity/runs/parity-production-ios-005, compared with the independentreference-final/ios-reference-finalruns. - Native macOS screenshots inspected at 420×360, 640×720, and 1000×900, covering home, detail, a real Wondertown session, and injected startup failure in light and dark appearances. Layout dumps were inspected before and after fixes.
- iPhone 17 / iOS 26.5 screenshots inspected for home in both appearances, detail, a real Wondertown session, and startup failure. Pushed screens show native navigation titles and Back controls. UI evidence is an application smoke test, not a paired visual comparison against the SwiftUI app.
Local visual artifacts: /tmp/adventure-macos-*.png,
/tmp/adventure-ios-*.png, /tmp/adventure-mvp-layout.xml, and
/tmp/adventure-mvp-small.xml. They are generated development evidence, not
committed golden images. A temporary harness under build/parity/adventure-qa
selects app states without adding production-only testing branches.
Remaining work
- Resolve the two macOS and six iOS narrow HStack geometry cases. Remaining differences involve nested width negotiation, native text rounding and height-constrained wrapping. Do not add candidate-only normalizations.
- Run paired visual and interaction verification for the 13 gallery cases and the rest of the exported API inventory. Existing export gaps remain those in the plan/coverage ledger. Full keyboard, accessibility, and every affected example's state matrix have not been signed off.
- Implement retained structural reconciliation before expanding dynamic app
subtrees. The existing
ui.viewdesc.applystub is still unfinished. - Adventure Arena still needs persistent saves/replay/deletion, its featured carousel and gradient treatment, the complete detail/review layout, ongoing sessions, full composer/history/suggestions/exits/companion behavior, reading preferences, the create-game form, settings/help, and translation-related behavior. The current in-memory session is not saved by closing its screen.
- Align or deliberately resolve the different zilscript submodule pins; prove independent session/RNG state and replay fidelity. Only Wondertown startup and command execution have been exercised against the real engine in this pass.
Native implementation references: SwiftUI layout proposals and NSPageController history.