tv-anarchy/run
Natalie 4a2ceb9781 feat(offline): inline star-to-keep and trash-to-cull on cache rows
Surface the existing pin (keep-from-cull) and per-file delete actions as
visible inline buttons on each offline cache row instead of context-menu-only:
a star toggles protection from auto-cull (and restore-if-missing), a trash
culls that file early. Aligns wording/icons to the star metaphor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 00:12:41 -04:00

171 lines
No EOL
5.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# TVAnarchy task runner. Thin, discoverable wrapper over the repo's build/test
# scripts so the common actions have one obvious name. Add a target by giving it
# a `task::<name>` function below — it shows up in `./run help` automatically.
#
# ./run # Debug build + relaunch (the everyday dev loop)
# ./run dev # same
# ./run deploy # Release install + relaunch (+ iOS when a phone is up)
# ./run test # Run Xcode unit tests
# ./run clean # Remove generated xcodeproj + build/
# ./run governor # Run the governor (portable-net-tv)
# ./run mcp # Run the MCP server (stdio)
# ./run bridge # Run the HTTP bridge for iOS
# ./run typecheck # TS typecheck for helpers
# ./run test:all # App tests + governor + mcp + search
set -euo pipefail
cd "$(dirname "$0")"
DD="${TVANARCHY_DD:-build/dd}"
relaunch_tv_anarchy() {
local app="$1"
if pgrep -fq "TVAnarchy.app/Contents/MacOS"; then
echo "→ quit running TVAnarchy"
osascript -e 'quit app "TVAnarchy"' || true
for _ in $(seq 1 20); do
pgrep -fq "TVAnarchy.app/Contents/MacOS" || break
sleep 0.5
done
fi
echo "→ open $app"
open "$app"
}
# Debug build from build/dd and relaunch — the default `./run`.
# Everyday loop: stamp → xcodegen → debug build → install to Applications → relaunch.
task::dev() {
echo "→ stamp build identity"
tools/stamp-build.sh
echo "→ xcodegen generate"
xcodegen generate >/dev/null
local app="$DD/Build/Products/Debug/TVAnarchy.app"
echo "→ xcodebuild (Debug → $app)"
xcodebuild -scheme TVAnarchy -configuration Debug -derivedDataPath "$DD" \
-destination 'platform=macOS' build CODE_SIGNING_ALLOWED=NO \
2>&1 | grep -E 'BUILD SUCCEEDED|BUILD FAILED|error:' || true
[ -d "$app" ] || { echo "✗ build produced no app at $app" >&2; exit 1; }
# Install to /Applications (or ~/Applications) so Spotlight launches this build,
# not a stale copy left from an old release cut.
. tools/platform.sh
local dest
dest="$(tva_resolve_dest mac)"
mkdir -p "$(dirname "$dest")"
rm -rf "$dest"
cp -R "$app" "$dest"
VER=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$dest/Contents/Info.plist")
BUILD=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$dest/Contents/Info.plist")
echo "✓ installed v$VER (build $BUILD) → $dest"
relaunch_tv_anarchy "$dest"
}
# Release install to Applications (+ iOS when reachable). See deploy.sh.
task::deploy() { ./deploy.sh "$@"; }
# plum: build Release and install to ~/Applications or /Applications (no relaunch).
task::update:plum() { ./build-install.sh "$@"; }
# Regenerate the Xcode project from project.yml.
task::generate() { xcodegen generate; }
# Run the unit-test bundle (regenerates the project first so new files are picked
# up). Pass extra args straight through, e.g. `./run test -only-testing:...`.
task::help() { usage; }
task::test() {
xcodegen generate >/dev/null
xcodebuild test -project TVAnarchy.xcodeproj -scheme TVAnarchy \
-destination 'platform=macOS' "$@"
}
# Clean generated Xcode project and derived data (safe; no source touch).
task::clean() {
echo "→ rm -rf build/ TVAnarchy.xcodeproj"
rm -rf build/ TVAnarchy.xcodeproj
}
# Typecheck the TypeScript helpers (governor + mcp).
task::typecheck() {
echo "→ governor typecheck"
(cd governor && bun run typecheck)
echo "→ mcp typecheck"
(cd mcp && bun run typecheck)
}
# Run the governor (portable-net-tv) — watch tracking + fleet engine on plum.
# Example: ./run governor fleet status
task::governor() {
(cd governor && bun run src/index.ts "$@")
}
# Run the mcp stdio server (for MCP clients like Claude).
task::mcp() {
(cd mcp && bun run src/index.ts "$@")
}
# Run the HTTP bridge (for iOS companion; default :8787).
task::bridge() {
(cd mcp && bun run src/http.ts "$@")
}
# Deploy to phone (iOS build + sideload via tools/deploy-phone.sh).
task::deploy:phone() { tools/deploy-phone.sh "$@"; }
# Run full tests: app unit tests + governor + mcp (+ search pytest if present).
task::test:all() {
task::test
echo "→ governor test"
(cd governor && bun test)
echo "→ mcp test"
(cd mcp && bun test)
if [ -f search/pyproject.toml ]; then
echo "→ search pytest"
(cd search && uv run pytest -q || true)
fi
}
usage() {
echo "usage: ./run [target] [args...]"
echo
echo " ./run, ./run dev Debug build (stamp + xcodegen + Debug xcodebuild) + install to"
echo " Applications (or ~/Applications) + quit + relaunch TVAnarchy."
echo " This is the normal local dev loop (uses build/dd by default;"
echo " set TVANARCHY_DD to relocate)."
echo
echo "Common targets:"
echo " deploy Release build + publish flow (see deploy.sh)"
echo " update:plum Release build + install (no relaunch; see build-install.sh)"
echo " deploy:phone Build + install to connected iOS device"
echo " test Run macOS unit tests (xcodebuild test)"
echo " test:all App tests + governor bun test + mcp bun test + search pytest"
echo " clean rm -rf build/ TVAnarchy.xcodeproj"
echo " generate xcodegen generate (project.yml → .xcodeproj)"
echo " governor [...] Run governor (portable-net-tv) with args (e.g. fleet status)"
echo " mcp [...] Run mcp stdio server"
echo " bridge [...] Run mcp HTTP bridge (for iOS companion)"
echo " typecheck tsc --noEmit in governor/ and mcp/"
echo
echo "All targets (auto-discovered):"
declare -F | sed -n 's/^declare -f task::/ /p' | grep -v ' help$'
echo
echo "See docs/operations.md and the top of this file for more."
}
main() {
local target="${1:-dev}"
[ "$target" != help ] || { usage; exit 0; }
shift || true
if ! declare -F "task::$target" >/dev/null; then
echo "✗ unknown target: $target" >&2
echo >&2
usage >&2
exit 1
fi
"task::$target" "$@"
}
main "$@"