feat(devkit): enforce governed prompt adoption
This commit is contained in:
+75
@@ -0,0 +1,75 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user