Skip to content

Fix build_macos_swift_app.sh silently omitting shipped scripts - #71

Merged
heznpc merged 2 commits into
mainfrom
fix/bundled-runtime-missing-scripts
Aug 13, 2026
Merged

Fix build_macos_swift_app.sh silently omitting shipped scripts#71
heznpc merged 2 commits into
mainfrom
fix/bundled-runtime-missing-scripts

Conversation

@heznpc

@heznpc heznpc commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • release_smoke.py's manifest-completeness checks (MACOS_BASE_FILES) and build_macos_swift_app.sh's own, completely separate RUNTIME_FILES array (which controls what actually gets copied into the signed app bundle) were never cross-checked against each other. A script could pass every existing manifest guard while still being silently absent from the real shipped app.
  • Confirmed for real against this machine's actual installed runtime (~/Library/Application Support/Modore/runtime/), staged by a real build of the app: scripts/modules/macos/idle_cpu.sh, privacy.sh, and devtool_updates.sh were all missing. Ran scanner.sh directly from that installed copy -- source failed for each module (no set -e, so the scan kept going with three collector functions permanently undefined), printing command not found to stderr for each, and the resulting scan_result.json silently reported collection.complete: true with all three sections simply absent from sections.
  • Separately, scripts/login_items.sh and scripts/modules/approval_token.sh were also missing. That path fails closed instead: pinnedApprovalTokenModule() returns nil when the sealed payload doesn't contain the module, and the calling Swift code refuses to run rather than silently proceeding. In practice this means every cleanup preview/execute and every login-item removal has failed outright in a real signed build since approval_token.sh was extracted out of cleanup.sh (Extract shared modules/approval_token.sh from cleanup.sh and login_items.sh #67) -- confirmed by reproducing the exact "봉인한 정리 프로그램을 확인하지 못해 실행하지 않았습니다" failure against a locally built app.
  • No existing test caught any of this because every test in the suite runs against the checkout directly -- never against the actual installed runtime tree a real user's app uses.

Fix

  • Added the 6 missing entries to RUNTIME_FILES in build_macos_swift_app.sh.
  • Added a permanent glob-based regression guard (test_bundled_app_runtime_includes_every_macos_script), matching the same pattern already used for release_smoke.py's own manifest gaps (caught 4 times already this cycle): any new scripts/**/*.sh file is now required to appear in RUNTIME_FILES unless it's one of the three build-time-only tools (build_macos_swift_app.sh, build_macos_icon.sh, package_macos_release.sh).

Test plan

  • pytest tests/ -- 358 passed
  • New regression test proven via revert/restore: stashed the fix and confirmed it fails with the exact 6 missing files (scripts/login_items.sh, scripts/modules/approval_token.sh, scripts/modules/macos/devtool_updates.sh, scripts/modules/macos/idle_cpu.sh, scripts/modules/macos/privacy.sh, scripts/network_watch.sh), then restored and confirmed it passes
  • Real-world repro against the actual installed runtime on this machine (not simulated): ran scanner.sh from ~/Library/Application Support/Modore/runtime/, observed the three command not found errors and confirmed the resulting scan_result.json had backgroundCpu/privacyPermissions/devtoolUpdates all silently empty while collection.complete: true

This is being shipped as its own PR ahead of the in-progress CPU/network monitoring work (which is what surfaced it) since it's a standalone, severe production bug affecting already-merged features, not something the current work introduced.

🤖 Generated with Claude Code

heznpc added 2 commits August 13, 2026 18:24
release_smoke.py's manifest-completeness checks and the app's own
RUNTIME_FILES array (which controls what actually gets copied into
the signed bundle) were never cross-checked, so a script could pass
every existing guard while still being silently absent from the real
shipped app.

Confirmed for real against this machine's actual installed runtime:
modules/macos/idle_cpu.sh, privacy.sh, and devtool_updates.sh were all
missing. scanner.sh's sibling-relative `source` failed for each with
no `set -e` to stop it, so the scan kept going with three collector
functions permanently undefined -- "command not found" on stderr, and
the resulting scan_result.json silently reported
`collection.complete: true` with all three sections simply absent.

Separately, scripts/login_items.sh and modules/approval_token.sh were
also missing -- that path fails closed instead (pinnedApprovalTokenModule
returns nil when the sealed payload lacks the module), meaning every
cleanup preview/execute and login-item removal has failed outright in
a real signed build since approval_token.sh was extracted out of
cleanup.sh (#67). No test caught it because every existing test runs
against the checkout directly, never the installed runtime tree a
real user's app uses.

Adds a permanent glob-based regression guard, matching the same
pattern already used for release_smoke.py's own manifest gaps: any new
scripts/**/*.sh file is now required to appear in RUNTIME_FILES unless
explicitly build-time-only.
That file doesn't exist on this branch -- it's part of the separate,
not-yet-merged Phase 5-1 work, and CI correctly caught the reference
to a nonexistent path. It belongs in that PR instead, alongside the
file itself.
@heznpc
heznpc merged commit ff17d02 into main Aug 13, 2026
8 checks passed
@heznpc
heznpc deleted the fix/bundled-runtime-missing-scripts branch August 13, 2026 09:38
heznpc added a commit that referenced this pull request Aug 13, 2026
* Add on-demand CPU/network observation window (Phase 5-1)

New "CPU·네트워크 관찰" section on the Activity page: the owner picks
a window (30s-5min) and triggers idle_cpu.sh and network_watch.sh
concurrently over the same period, showing real CPU deltas and any
newly-appeared connections/listening ports.

Scoped this as synchronous and user-triggered rather than a scheduled
background watch after investigating the existing options: schedule.sh
is entirely hardcoded to one job (storage-watch's own label/plist),
not a generic scheduler, so extending it would mean building new
scheduling infrastructure in the most security-sensitive part of the
codebase. CPU/network are also fast, bursty signals where a fixed
hourly sample would almost always just catch them idle -- unlike free
disk space, which changes slowly enough for that cadence to make
sense. Windows' own scripts/monitor.ps1 is the existing cross-platform
precedent for this shape: synchronous, foreground, user-triggered,
never scheduled.

New scripts/network_watch.sh mirrors idle_cpu.sh's two-sample delta
pattern: identity for established connections is (process, remote
host:port), ignoring the local ephemeral port, so an ordinary
reconnect to an already-seen server isn't reported as "new" -- proven
with a fixture and a revert/restore of the fix (it also caught the
"no changes" case, not just the one it targeted). idle_cpu.sh needed
no changes at all; it's invoked with a longer window than the scan's
own 3s default, same script either way.

Verified end-to-end in the actual signed app (built via
build_macos_swift_app.sh, after #71 fixed the runtime bundle): the
window picker, in-flight state, and results all render correctly, and
triggering it for real over a 30s window surfaced genuine CPU usage
and network connections happening on this machine during the run.

* Skip network_watch.sh's injection-mode tests on non-macOS CI

network_watch.sh checks uname -s before its PCH_TEST_MODE branch, same
as idle_cpu.sh -- the injection path is unreachable on Linux, so these
tests need the same skipif guard test_macos_idle_cpu.py already uses
for its own analogous tests. Missed this the first time; the argument-
validation test doesn't need it since that check runs before the
platform gate.

---------

Co-authored-by: Heznpc <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant