# ODS — Developer Targets
# Run `make help` to see available commands.

SHELL_FILES := $(shell find . -name '*.sh' -not -path './node_modules/*' -not -path './.git/*' -not -path './data/*' -not -path './token-spy/*')

.PHONY: help lint test bats smoke simulate fleet-distros fleet-vms verify-bootstrap gate doctor

help: ## Show this help
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
		awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'

lint: ## Syntax check all shell scripts + Python compile check
	@echo "=== Shell syntax ==="
	@fail=0; for f in $(SHELL_FILES); do bash -n "$$f" || fail=1; done; [ $$fail -eq 0 ]
	@echo "=== Python compile ==="
	@python3 -m py_compile extensions/services/dashboard-api/main.py extensions/services/dashboard-api/agent_monitor.py
	@echo "All lint checks passed."

test: ## Run unit and contract tests
	@python3 scripts/verify-pixel-bundle.py
	@python3 tests/test-seeded-content-privacy.py
	@bash tests/test-pixel-bundled-source.sh
	@echo "=== Install documentation contract ==="
	@bash tests/test-install-docs.sh
	@bash tests/test-hosted-bootstrap-verifier.sh
	@bash tests/test-summary-quick-commands.sh
	@echo ""
	@echo "=== Tier map tests ==="
	@bash tests/test-tier-map.sh
	@python3 tests/test-model-library-pinned-urls.py
	@python3 tests/test-tier-map-catalog-pins.py
	@bash tests/test-installer-context-parity.sh
	@bash tests/test-embeddings-prefetch-service-cache.sh
	@bash tests/test-hermes-context-floor.sh
	@bash tests/test-install-menu-hermes-flag.sh
	@bash tests/test-custom-menu-agent-flags.sh
	@bash tests/test-native-llm-flags.sh
	@bash tests/test-preflight-external-gpu.sh
	@bash tests/test-wsl-whisper-port-reservation.sh
	@echo ""
	@echo "=== Hermes slash worker prune ==="
	@bash tests/test-hermes-slash-worker-prune.sh
	@python3 tests/contracts/test-hermes-worker-guardrails.py
	@echo ""
	@echo "=== OpenCode managed launchers confine Bun temp copies ==="
	@bash tests/test-opencode-bun-tmpdir.sh
	@echo ""
	@echo "=== Installer contracts ==="
	@bash tests/contracts/test-installer-contracts.sh
	@bash tests/test-external-services.sh
	@bash tests/test-phase11-litellm-reload.sh
	@bash tests/test-resolve-compose-resilient.sh
	@bash tests/test-phase03-multigpu-tty.sh
	@bash tests/test-pixel-support-services.sh
	@bash tests/test-phase03-no-gpu-assignment-message.sh
	@bash tests/contracts/test-preflight-fixtures.sh
	@bash tests/test-preflight-resolver-bug.sh
	@bash tests/test-linux-cloud-mode.sh
	@echo ""
	@echo "=== Linux install preflight ==="
	@bash tests/test-linux-install-preflight.sh
	@bash tests/test-phase05-podman-shim.sh
	@bash tests/test-linux-host-agent-stop.sh
	@bash tests/test-preflight-dashboard-port.sh
	@bash tests/test-wsl-broken-docker-shim.sh
	@bash tests/test-wsl-nvidia-driver-guard.sh
	@bash tests/test-ui-missing-container-fast-fail.sh
	@echo ""
	@echo "=== ods-doctor rootless subordinate IDs ==="
	@bash tests/test-ods-doctor-rootless-subid.sh
	@echo "=== ods-test.sh reports HTTP 000 for a failed probe ==="
	@bash tests/test-ods-test-http-code.sh
	@echo "=== ods-test.sh completes and reports when checks fail ==="
	@bash tests/test-ods-test-complete-run.sh
	@echo "=== ods-test.sh judges Tool Calling and LLM replies by their JSON ==="
	@bash tests/test-ods-test-tool-calling.sh
	@echo "=== phase 10 skips templated system units in the user scope ==="
	@bash tests/test-phase10-skip-templated-user-units.sh
	@echo "=== pre-download --tier is non-interactive ==="
	@bash tests/test-pre-download-tier-noninteractive.sh
	@echo "=== ods-doctor reads .env through lib/safe-env.sh ==="
	@bash tests/test-ods-doctor-env-reader.sh
	@echo "=== Docker rootless bind-mount ownership ==="
	@bash tests/test-rootless-docker-ownership.sh
	@echo "=== APE private state bind ownership ==="
	@bash tests/test-ape-data-ownership.sh
	@bash tests/test-dashboard-data-permissions.sh
	@python3 tests/test_dashboard_data_permissions.py
	@bash tests/test-token-spy-install-owner.sh
	@bash tests/test-cli-status-docker-error.sh
	@bash tests/test-cli-status-optional-webui.sh
	@bash tests/test-macos-status-optional-opencode.sh
	@python3 tests/test-cli-stt-env.py
	@echo ""
	@echo "=== AMD llama.cpp contracts ==="
	@bash tests/contracts/test-amd-llamacpp-contracts.sh
	@bash tests/test-wsl-agent-start.sh
	@python3 tests/test-router-transport.py
	@python3 tests/test-wsl-runtime-proof.py
	@python3 tests/test-wsl-runtime-control.py
	@python3 tests/test-configure-wsl-model-store.py
	@python3 tests/test-retire-wsl-runtime.py
	@bash tests/test-litellm-amd-auth-enforced.sh
	@bash tests/contracts/test-windows-strix-tier-map.sh
	@bash tests/contracts/test-windows-llm-model-readiness.sh
	@bash tests/contracts/test-windows-lemonade-swap-wait.sh
	@bash tests/contracts/test-windows-hermes-config-patching.sh
	@bash tests/contracts/test-llama-metrics-flag.sh
	@bash tests/contracts/test-llama-reasoning-format.sh
	@echo ""
	@echo "=== Overlay/plist contracts ==="
	@bash tests/contracts/test-overlay-map-coherence.sh
	@bash tests/contracts/test-plist-log-paths.sh
	@python3 tests/contracts/test-llama-cpp-compat.py
	@python3 tests/contracts/test-llama-runtime-tunables.py
	@python3 tests/contracts/test-llama-spec-default.py
	@bash tests/test-llama-mtp-args.sh
	@python3 -m unittest tests/test_macos_runtime_llama_args.py tests/test_macos_checkpoint_args.py
	@echo ""
	@echo "=== safe .env loading (quote/CRLF handling) ==="
	@bash tests/test-safe-env.sh
	@bash tests/test-env-example-inline-comments.sh
	@bash tests/test-phase06-secret-generation.sh
	@bash tests/test-phase06-env-rerun-quoting.sh
	@echo ""
	@echo "=== health-check.sh --json output contract ==="
	@bash tests/test-health-check-json-output.sh
	@echo ""
	@echo "=== QR code helper LAN detection ==="
	@bash tests/test-qrcode-helper.sh
	@echo ""
	@echo "=== mode switch status and switching ==="
	@bash tests/test-mode-switch-status.sh
	@bash tests/test-env-append-final-newline.sh
	@echo ""
	@echo "=== Bind address sweep ==="
	@bash tests/test-bind-address-sweep.sh
	@bash tests/test-n8n-cookie-policy.sh
	@echo ""
	@echo "=== config migration (version check under set -e) ==="
	@bash tests/test-migrate-config.sh
	@echo "=== installer simulation harness records real exit codes ==="
	@bash tests/test-simulate-installers-exit-codes.sh
	@echo ""
	@echo "=== restore refuses empty backup config ==="
	@bash tests/test-restore-empty-config.sh
	@bash tests/test-lifecycle-prompts-noninteractive.sh
	@echo ""
	@echo "=== atomic .env writes ==="
	@bash tests/test-atomic-env-writes.sh
	@echo ""
	@echo "=== upgrade-model compose stack ==="
	@bash tests/test-upgrade-model-compose-stack.sh
	@echo ""
	@echo "=== brave-search searxng compat contract ==="
	@bash tests/test-brave-search-searxng-compat.sh
	@echo ""
	@echo "=== SearXNG factory config contract ==="
	@bash tests/test-searxng-config-contract.sh
	@echo ""
	@echo "=== ods-cli pipefail tolerance ==="
	@bash tests/test-ods-cli-pipefail-tolerance.sh
	@bash tests/test-cli-prompts-noninteractive.sh
	@bash tests/test-agent-restart-nonfatal.sh
	@bash tests/test-unix-restart-recreate-env.sh
	@bash tests/test-ods-cli-host-cpu-fallback.sh
	@echo ""
	@echo "=== ods-cli install directory resolution ==="
	@bash tests/test-cli-install-dir-resolution.sh
	@echo ""
	@echo "=== offline model validation ==="
	@python3 tests/test-offline-model-validation.py
	@echo ""
	@echo "=== Bash 3.2 guard contracts ==="
	@bash tests/test-bash32-guards.sh
	@bash tests/test-ods-doctor-bash32-guard.sh
	@echo ""
	@echo "=== CLI update post-verification ==="
	@bash tests/test-cli-update-verification.sh
	@echo ""
	@echo "=== ods config show secret-mask matrix ==="
	@bash tests/test-ods-config-secret-mask.sh
	@echo ""
	@echo "=== Manifest schema source of truth ==="
	@bash tests/test-validate-manifest-schema.sh
	@echo "=== ComfyUI user directory is persisted ==="
	@bash tests/test-comfyui-user-dir-persisted.sh
	@echo ""
	@echo "=== macOS ods config show secret-mask ==="
	@bash tests/test-macos-config-show-secret-mask.sh
	@bash tests/test-macos-config-without-docker.sh
	@echo ""
	@echo "=== CLI preset restore user extensions ==="
	@bash tests/test-cli-preset-restore-user-extensions.sh
	@bash tests/test-preset-export-permissions.sh
	@bash tests/test-preset-host-only-services.sh
	@echo ""
	@echo "=== ods-update.sh backup command ==="
	@bash tests/test-update-backup-retention-labels.sh
	@bash tests/test-update-script-backup.sh
	@bash tests/test-update-backup-retention-spaces.sh
	@bash tests/test-update-current-version.sh
	@bash tests/test-update-rollback-restore-failure.sh
	@bash tests/test-backup-data-coverage.sh
	@echo ""
	@echo "=== backup integrity and restore round-trip ==="
	@bash tests/test-backup-integrity.sh
	@bash tests/test-backup-restore-roundtrip.sh
	@bash tests/test-backup-macos-appledouble.sh
	@python3 tests/test-rsync-transfer-failures.py
	@echo ""
	@echo "=== ods-update.sh rollback picks the newest backup ==="
	@bash tests/test-update-rollback-latest-backup.sh
	@echo ""
	@echo "=== bootstrap-upgrade spawn closes inherited FDs ==="
	@bash tests/test-bootstrap-upgrade-close-inherited-fds.sh
	@echo ""
	@echo "=== bootstrap-upgrade compose-flags recovery ==="
	@bash tests/test-bootstrap-upgrade-compose-flags-recovery.sh
	@echo ""
	@echo "=== macOS doctor reports honest failure ==="
	@bash tests/test-macos-doctor-honest-failure.sh
	@echo ""
	@echo "=== macOS ods-host-agent bootstrap verification ==="
	@bash tests/test-macos-host-agent-verification.sh
	@bash tests/test-macos-intel-preflight-blocker.sh
	@echo ""
	@echo "=== desktop host-agent environment contract ==="
	@bash tests/test-desktop-agent-host-env.sh
	@echo ""
	@echo "=== macOS model download retry contract ==="
	@bash tests/test-macos-download-retries.sh
	@echo ""
	@echo "=== macOS CLI .env quote handling ==="
	@bash tests/test-macos-env-quote-strip.sh
	@echo "=== macOS generated .env validates against the schema ==="
	@bash tests/test-macos-env-schema.sh
	@echo "=== macOS native llama port is relocatable ==="
	@bash tests/test-macos-native-llama-port.sh
	@echo ""
	@echo "=== macOS uninstall LaunchAgent cleanup ==="
	@bash tests/test-macos-uninstall-launchagents.sh
	@echo "=== uninstall removes the ods-mdns systemd unit ==="
	@bash tests/test-uninstall-mdns-unit.sh
	@echo ""
	@echo "=== token-spy session manager active-id extraction ==="
	@bash tests/test-token-spy-session-manager.sh
	@echo ""
	@echo "=== fleet-multi-distro keep-going on docker pull failure ==="
	@bash tests/test-fleet-multi-distro-keep-going.sh
	@echo ""
	@echo "=== fleet host lock behavior ==="
	@bash tests/test-fleet-host-lock.sh
	@echo ""
	@echo "=== documented security suites (SECURITY_AUDIT.md) ==="
	@bash tests/test-secret-security.sh
	@bash tests/contracts/test-security-suites-wired.sh
	@echo ""
	@echo "=== NVIDIA multi-GPU visibility contract ==="
	@bash tests/test-multigpu-nvidia-visibility.sh
	@bash tests/test-multigpu-nvidia-service-pinning.sh
	@echo ""
	@echo "=== CLI user-extension dependency resolution ==="
	@bash tests/test-cli-user-extension-deps.sh

bats: ## Run BATS unit tests for shell libraries
	@echo "=== BATS unit tests ==="
	@bash tests/run-bats.sh

smoke: ## Run platform smoke tests
	@echo "=== Smoke tests ==="
	@bash tests/smoke/linux-amd.sh
	@bash tests/smoke/linux-nvidia.sh
	@bash tests/smoke/wsl-logic.sh
	@bash tests/smoke/macos-dispatch.sh
	@echo "All smoke tests passed."

simulate: ## Run installer simulation harness
	@bash scripts/simulate-installers.sh

fleet-distros: ## Run disposable Docker multi-distro fleet checks
	@bash tests/fleet-multi-distro.sh

fleet-vms: ## Run disposable Incus VM fleet checks
	@bash tests/fleet-incus-vm.sh

verify-bootstrap: ## Verify hosted bootstrap against EXPECTED_REF (defaults to HEAD)
	@bash scripts/verify-hosted-bootstrap.sh "$${EXPECTED_REF:-$$(git rev-parse HEAD)}" $${ENDPOINTS:-}

doctor: ## Run diagnostic report
	@bash scripts/ods-doctor.sh

gate: lint test bats smoke simulate ## Full pre-release validation (lint + test + bats + smoke + simulate)
	@echo ""
	@echo "Release gate passed."
