ReviewOS

also looking at this

craft-native/craft

fix(native): preserve workspace sources and native overlay lifecycle

#384
Merged chris wants to merge codex/windows-zig-cache-diagnostics into main
20 files +500 -227

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

.github/workflows/mobile-e2e.ymlmodified+3-0
Changes to .github/workflows/mobile-e2e.yml
@@ -623,6 +623,9 @@ jobs:
623623 artifacts/mobile-e2e/ios-zig-slice/console.plain
624624 artifacts/mobile-e2e/ios-zig-slice/app-stdout.log
625625 artifacts/mobile-e2e/ios-zig-slice/app-stderr.log
626 artifacts/mobile-e2e/ios-zig-slice/failure.png
627 artifacts/mobile-e2e/ios-zig-slice/failure-screenshot.log
628 artifacts/mobile-e2e/ios-zig-slice/failure-location.log
626629 if-no-files-found: error
627630 retention-days: 30
628631
packages/ios/fixtures/native-screen/NativeRenderUnitTests.swiftmodified+1-1
Changes to packages/ios/fixtures/native-screen/NativeRenderUnitTests.swift
@@ -2614,7 +2614,7 @@ final class NativeRenderUnitTests: XCTestCase {
26142614 let controller = CraftNativeScreenController(config: CraftConfig())
26152615 controller.loadViewIfNeeded()
26162616 let screen: ([String: Any]) -> [String: Any] = { props in
2617 document([[
2617 self.document([[
26182618 "type": "Switch",
26192619 "props": ["key": "consent", "value": props["value"] as Any],
26202620 "events": ["onValueChange": "consentChanged"],
packages/ios/fixtures/zig-slice/build-and-run.shmodified+21-1
Changes to packages/ios/fixtures/zig-slice/build-and-run.sh
@@ -137,6 +137,26 @@ SIMCTL_CHILD_NSUnbufferedIO=YES xcrun simctl launch --terminate-running-process
137137
138138gather_log() { cat "$STDOUT_LOG" "$STDERR_LOG" > "$LOG" 2>/dev/null || true; }
139139
140collect_failure_diagnostics() {
141 # Read-only evidence from this simulator, bounded independently of the
142 # unchanged assertion deadline. Never dismiss alerts or change permissions.
143 python3 - "$UDID" "$OUT" <<'PY'
144import pathlib, subprocess, sys
145device, output = sys.argv[1], pathlib.Path(sys.argv[2])
146commands = [
147 ("failure-screenshot.log", ["xcrun", "simctl", "io", device, "screenshot", str(output / "failure.png")]),
148 ("failure-location.log", ["xcrun", "simctl", "spawn", device, "log", "show", "--style", "compact", "--last", "20m", "--predicate", 'process == "locationd" OR process == "tccd"']),
149]
150for name, command in commands:
151 with (output / name).open("w") as evidence:
152 try:
153 result = subprocess.run(command, stdout=evidence, stderr=subprocess.STDOUT, timeout=10)
154 evidence.write(f"\nDiagnostic exit: {result.returncode}\n")
155 except (OSError, subprocess.TimeoutExpired) as error:
156 evidence.write(f"\nDiagnostic unavailable: {error}\n")
157PY
158}
159
140160# The round trip is fast, but a cold simulator is not. Poll rather than sleep a
141161# fixed amount, so a slow boot does not read as a failure.
142162#
@@ -179,7 +199,7 @@ while :; do
179199 cat "$LOG" || true
180200 echo "FAIL: timed out after ${SLICE_TIMEOUT}s waiting for:$MISSING"
181201 echo " The app never got that far — this is a timeout, not a wrong answer."
182 echo " Raise CRAFT_SLICE_TIMEOUT if the machine is simply slow."
202 collect_failure_diagnostics
183203 xcrun simctl terminate "$UDID" "$BUNDLE_ID" 2>/dev/null || true
184204 exit 1
185205 fi
scripts/native-renderer-contract.test.tsmodified+9-2
Changes to scripts/native-renderer-contract.test.ts
@@ -1882,8 +1882,15 @@ describe('native renderer component contract', () => {
18821882 expect(guide).toContain('each ancestor `onScroll` event as placement invalidations')
18831883 expect(iosReadme).toContain('host-neutral invalidation signals for')
18841884 expect(androidReadme).toContain('host-neutral invalidation signals for')
1885 expect(androidReadme).toContain('do not claim Health Services')
1886 expect(guide).toContain('provide Health Services background execution or live sensor samples')
1885 })
1886
1887 it('documents optional native Health Services with capability checks and explicit failures', () => {
1888 expect(androidReadme).toContain('`enableHealthServices: true` to retain `ExerciseClient` in a foreground')
1889 expect(androidReadme).toContain('"enableHealthServices": false')
1890 expect(androidReadme).toContain('emit a typed `error` event and leave the Health Connect fallback untouched')
1891 expect(guide).toContain('`enableHealthServices: true`. Craft retains `ExerciseClient` in a foreground')
1892 expect(guide).toContain('checks device capabilities before starting')
1893 expect(guide).toContain('produce an `error` event rather than silently upgrading the fallback')
18871894 })
18881895
18891896 it('exposes screen-owned scrolling for mounted native scroll views', () => {