ralph-loop[epic-a-to-d-mainline]: iteration 2

This commit is contained in:
zhukang
2026-03-23 17:35:05 +08:00
parent 0550568a2b
commit 78ecca3a15
15 changed files with 731 additions and 40 deletions

View File

@@ -0,0 +1,50 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FIXTURE_SCRIPT="$SCRIPT_DIR/apps-manual-fixtures.sh"
print_guide() {
cat <<'EOF'
Apps Evidence Acceptance Guide
1. Run Atlas and open the Apps screen.
2. Verify these fixture apps appear:
- Atlas Fixture Browser
- Atlas Fixture Dev
- Atlas Fixture Sparse
3. For each fixture app, build the uninstall plan and confirm:
- preview categories match the expected review-only evidence
- recoverable bundle removal is separated from review-only evidence
- observed paths are listed for review-only groups
4. Execute uninstall for Atlas Fixture Dev and confirm:
- completion summary mentions real removal and review-only categories
- History shows the uninstall with review-only evidence still informational
5. Restore the Atlas Fixture Dev recovery item and confirm:
- the app reappears in Apps after the restore-driven inventory refresh
- stale uninstall preview is cleared
- History shows restore-path evidence when supported
6. Re-run Apps refresh and verify leftover counts remain consistent with current disk state.
7. Clean up fixtures when done.
EOF
}
case "${1:-guide}" in
setup)
"$FIXTURE_SCRIPT" create
print_guide
;;
status)
"$FIXTURE_SCRIPT" status
;;
cleanup)
"$FIXTURE_SCRIPT" cleanup
;;
guide)
print_guide
;;
*)
echo "Usage: $0 [setup|status|cleanup|guide]" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,178 @@
#!/bin/bash
set -euo pipefail
APPS_ROOT="$HOME/Applications"
SUPPORT_ROOT="$HOME/Library/Application Support"
CACHE_ROOT="$HOME/Library/Caches"
PREFERENCES_ROOT="$HOME/Library/Preferences"
LOG_ROOT="$HOME/Library/Logs"
STATE_ROOT="$HOME/Library/Saved Application State"
LAUNCH_AGENTS_ROOT="$HOME/Library/LaunchAgents"
FIXTURES=(
"Atlas Fixture Browser|com.example.atlas.fixture.browser|support,caches,preferences"
"Atlas Fixture Dev|com.example.atlas.fixture.dev|support,caches,logs,launch"
"Atlas Fixture Sparse|com.example.atlas.fixture.sparse|saved-state"
)
create_blob() {
local path="$1"
local size_kb="$2"
mkdir -p "$(dirname "$path")"
if command -v mkfile > /dev/null 2>&1; then
mkfile "${size_kb}k" "$path"
else
dd if=/dev/zero of="$path" bs=1024 count="$size_kb" status=none
fi
}
write_info_plist() {
local plist_path="$1"
local bundle_id="$2"
local app_name="$3"
cat > "$plist_path" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>${bundle_id}</string>
<key>CFBundleName</key>
<string>${app_name}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleExecutable</key>
<string>fixture</string>
</dict>
</plist>
EOF
}
create_app_bundle() {
local app_name="$1"
local bundle_id="$2"
local bundle_path="$APPS_ROOT/${app_name}.app"
local contents_path="$bundle_path/Contents"
local executable_path="$contents_path/MacOS/fixture"
local plist_path="$contents_path/Info.plist"
mkdir -p "$(dirname "$executable_path")"
printf '#!/bin/sh\nexit 0\n' > "$executable_path"
chmod +x "$executable_path"
write_info_plist "$plist_path" "$bundle_id" "$app_name"
create_blob "$bundle_path/Contents/Resources/fixture.dat" 128
}
create_leftovers() {
local app_name="$1"
local bundle_id="$2"
local categories="$3"
IFS=',' read -r -a parts <<< "$categories"
for category in "${parts[@]}"; do
case "$category" in
support)
create_blob "$SUPPORT_ROOT/$bundle_id/settings.json" 32
;;
caches)
create_blob "$CACHE_ROOT/$bundle_id/cache.bin" 48
;;
preferences)
create_blob "$PREFERENCES_ROOT/$bundle_id.plist" 4
;;
logs)
create_blob "$LOG_ROOT/$bundle_id/runtime.log" 24
;;
launch)
mkdir -p "$LAUNCH_AGENTS_ROOT"
cat > "$LAUNCH_AGENTS_ROOT/$bundle_id.plist" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${bundle_id}</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/true</string>
</array>
</dict>
</plist>
EOF
;;
saved-state)
create_blob "$STATE_ROOT/$bundle_id.savedState/data.data" 8
;;
esac
done
}
cleanup_fixture() {
local app_name="$1"
local bundle_id="$2"
rm -rf \
"$APPS_ROOT/${app_name}.app" \
"$SUPPORT_ROOT/$bundle_id" \
"$CACHE_ROOT/$bundle_id" \
"$PREFERENCES_ROOT/$bundle_id.plist" \
"$LOG_ROOT/$bundle_id" \
"$STATE_ROOT/$bundle_id.savedState" \
"$LAUNCH_AGENTS_ROOT/$bundle_id.plist"
}
print_status() {
local found=false
for fixture in "${FIXTURES[@]}"; do
IFS='|' read -r app_name bundle_id categories <<< "$fixture"
local bundle_path="$APPS_ROOT/${app_name}.app"
if [[ -d "$bundle_path" ]]; then
found=true
echo "Fixture: $app_name ($bundle_id)"
du -sh "$bundle_path" "$SUPPORT_ROOT/$bundle_id" "$CACHE_ROOT/$bundle_id" \
"$PREFERENCES_ROOT/$bundle_id.plist" "$LOG_ROOT/$bundle_id" \
"$STATE_ROOT/$bundle_id.savedState" "$LAUNCH_AGENTS_ROOT/$bundle_id.plist" 2> /dev/null || true
echo "Expected review-only categories: $categories"
echo ""
fi
done
if [[ "$found" == false ]]; then
echo "No Apps manual fixtures found."
fi
}
create_fixtures() {
for fixture in "${FIXTURES[@]}"; do
IFS='|' read -r app_name bundle_id categories <<< "$fixture"
cleanup_fixture "$app_name" "$bundle_id"
create_app_bundle "$app_name" "$bundle_id"
create_leftovers "$app_name" "$bundle_id" "$categories"
done
echo "Created Apps manual fixtures:"
print_status
}
cleanup_fixtures() {
for fixture in "${FIXTURES[@]}"; do
IFS='|' read -r app_name bundle_id _ <<< "$fixture"
cleanup_fixture "$app_name" "$bundle_id"
done
echo "Removed Apps manual fixtures."
}
case "${1:-create}" in
create)
create_fixtures
;;
status)
print_status
;;
cleanup)
cleanup_fixtures
;;
*)
echo "Usage: $0 [create|status|cleanup]" >&2
exit 1
;;
esac

View File

@@ -34,35 +34,40 @@ run_ui_acceptance() {
return 1
}
echo "[1/10] Shared package tests"
echo "[1/11] Shared package tests"
swift test --package-path Packages
echo "[2/10] App package tests"
echo "[2/11] App package tests"
swift test --package-path Apps
echo "[3/10] Worker and helper builds"
echo "[3/11] Worker and helper builds"
swift build --package-path XPC
swift test --package-path Helpers
swift build --package-path Testing
echo "[4/10] Native packaging"
echo "[4/11] Fixture automation scripts"
bash -n ./scripts/atlas/smart-clean-manual-fixtures.sh
bash -n ./scripts/atlas/apps-manual-fixtures.sh
bash -n ./scripts/atlas/apps-evidence-acceptance.sh
echo "[5/11] Native packaging"
./scripts/atlas/package-native.sh
echo "[5/10] Bundle structure verification"
echo "[6/11] Bundle structure verification"
./scripts/atlas/verify-bundle-contents.sh
echo "[6/10] DMG install verification"
echo "[7/11] DMG install verification"
KEEP_INSTALLED_APP=1 ./scripts/atlas/verify-dmg-install.sh
echo "[7/10] Installed app launch smoke"
echo "[8/11] Installed app launch smoke"
./scripts/atlas/verify-app-launch.sh
echo "[8/10] Native UI automation"
echo "[9/11] Native UI automation"
run_ui_acceptance
echo "[9/10] Signing preflight"
echo "[10/11] Signing preflight"
./scripts/atlas/signing-preflight.sh || true
echo "[10/10] Acceptance summary"
echo "[11/11] Acceptance summary"
echo "Artifacts available in dist/native"
ls -lah dist/native

View File

@@ -4,8 +4,11 @@ set -euo pipefail
CACHE_ROOT="$HOME/Library/Caches/AtlasExecutionFixturesCache"
LOG_ROOT="$HOME/Library/Logs/AtlasExecutionFixturesLogs"
DERIVED_ROOT="$HOME/Library/Developer/Xcode/DerivedData/AtlasExecutionFixturesDerivedData"
CORESIM_ROOT="$HOME/Library/Developer/CoreSimulator/Caches/AtlasExecutionFixturesCoreSimulator"
PYCACHE_ROOT="$HOME/Library/Caches/AtlasExecutionFixturesPycache"
PNPM_ROOT="$HOME/Library/pnpm/store/v3/files/AtlasExecutionFixturesPnpm"
GRADLE_ROOT="$HOME/.gradle/caches/AtlasExecutionFixturesGradle"
IVY_ROOT="$HOME/.ivy2/cache/AtlasExecutionFixturesIvy"
create_blob() {
local path="$1"
@@ -20,7 +23,7 @@ create_blob() {
print_status() {
local existing=false
for path in "$CACHE_ROOT" "$LOG_ROOT" "$DERIVED_ROOT" "$PYCACHE_ROOT" "$PNPM_ROOT"; do
for path in "$CACHE_ROOT" "$LOG_ROOT" "$DERIVED_ROOT" "$CORESIM_ROOT" "$PYCACHE_ROOT" "$PNPM_ROOT" "$GRADLE_ROOT" "$IVY_ROOT"; do
if [[ -e "$path" ]]; then
existing=true
du -sh "$path"
@@ -39,9 +42,12 @@ create_fixtures() {
create_blob "$CACHE_ROOT/cache-b.bin" 12
create_blob "$LOG_ROOT/app.log" 8
create_blob "$DERIVED_ROOT/Build/Logs/build-products.bin" 16
create_blob "$CORESIM_ROOT/device-cache.db" 6
mkdir -p "$PYCACHE_ROOT/project/__pycache__"
create_blob "$PYCACHE_ROOT/project/__pycache__/sample.cpython-312.pyc" 4
create_blob "$PNPM_ROOT/package.tgz" 10
create_blob "$GRADLE_ROOT/modules.bin" 10
create_blob "$IVY_ROOT/artifact.bin" 6
echo "Created Smart Clean manual fixtures:"
print_status
@@ -50,7 +56,7 @@ create_fixtures() {
}
cleanup_fixtures() {
rm -rf "$CACHE_ROOT" "$LOG_ROOT" "$DERIVED_ROOT" "$PYCACHE_ROOT" "$PNPM_ROOT"
rm -rf "$CACHE_ROOT" "$LOG_ROOT" "$DERIVED_ROOT" "$CORESIM_ROOT" "$PYCACHE_ROOT" "$PNPM_ROOT" "$GRADLE_ROOT" "$IVY_ROOT"
echo "Removed Smart Clean manual fixtures."
}