#!/usr/bin/env bash set -euo pipefail DEVKIT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT TARGET="$WORK/existing-project" mkdir -p "$TARGET/.github" printf '# Existing agent rules\n' > "$TARGET/AGENTS.md" printf '# Existing Claude rules\n' > "$TARGET/CLAUDE.md" printf '# Existing Copilot rules\n' > "$TARGET/.github/copilot-instructions.md" install_project() { bash "$DEVKIT_ROOT/install.sh" \ --target "$TARGET" \ --project sample-project \ --domain "Sample Project" >/dev/null } install_project python3 - "$TARGET" <<'PY' import json, pathlib, sys root = pathlib.Path(sys.argv[1]) policy = json.loads((root / ".casan/prompt-policy.json").read_text(encoding="utf-8")) assert policy["mode"] == "enforced" assert policy["project_id"] == "sample-project" assert policy["domain_root"] == "apps/sample-project/domain" for relative in ("AGENTS.md", "CLAUDE.md", ".github/copilot-instructions.md"): text = (root / relative).read_text(encoding="utf-8") assert "Existing" in text assert text.count("CASAN_PROMPT_ENFORCEMENT_START") == 1 workflow = (root / ".gitea/workflows/casan-prompt-enforcement.yml").read_text(encoding="utf-8") assert "CASAN prompt enforcement contract" in workflow assert 'CASAN_PROJECT_ID: "sample-project"' in workflow assert "__PROJECT_ID__" not in workflow assert (root / "bin/casan-chat").exists() assert (root / "bin/casan-chat.ps1").exists() PY (cd "$TARGET" && bin/casan prompt verify) | grep -q 'CASAN_PROMPT_ENFORCEMENT_VALID project=sample-project' # A second adoption run upgrades managed files without duplicating instruction blocks. install_project python3 - "$TARGET" <<'PY' import pathlib, sys root = pathlib.Path(sys.argv[1]) for relative in ("AGENTS.md", "CLAUDE.md", ".github/copilot-instructions.md"): assert (root / relative).read_text(encoding="utf-8").count("CASAN_PROMPT_ENFORCEMENT_START") == 1 PY # Managed-file tampering must fail closed before a prompt reaches chat-turn. python3 - "$TARGET/CLAUDE.md" <<'PY' import pathlib, sys path = pathlib.Path(sys.argv[1]) path.write_text(path.read_text(encoding="utf-8").replace("CASAN_PROMPT_ENFORCEMENT_START", "REMOVED_MARKER"), encoding="utf-8") PY set +e (cd "$TARGET" && bin/casan prompt verify >"$WORK/tamper.out" 2>&1) TAMPER_RC=$? set -e if [[ "$TAMPER_RC" -ne 2 ]] || ! grep -q 'managed_marker_missing:CLAUDE.md' "$WORK/tamper.out"; then echo "adoption-install-tests: tampered contract was accepted" >&2 cat "$WORK/tamper.out" >&2 exit 1 fi # New-project scaffolding must continue into the same enforcement installation. FRESH="$WORK/fresh-project" bash "$DEVKIT_ROOT/install.sh" --target "$FRESH" --project fresh-app \ --domain "Fresh App" --template nestjs-react >/dev/null (cd "$FRESH" && bin/casan prompt verify) | grep -q 'CASAN_PROMPT_ENFORCEMENT_VALID project=fresh-app' test -f "$FRESH/apps/fresh-app/frontend/package.json" echo "ADOPTION_INSTALL_TESTS_PASS"