aboutsummaryrefslogtreecommitdiff
path: root/scripts/tests/install-lang-collision.bats
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/tests/install-lang-collision.bats')
-rw-r--r--scripts/tests/install-lang-collision.bats53
1 files changed, 42 insertions, 11 deletions
diff --git a/scripts/tests/install-lang-collision.bats b/scripts/tests/install-lang-collision.bats
index 36abb5b..e03e136 100644
--- a/scripts/tests/install-lang-collision.bats
+++ b/scripts/tests/install-lang-collision.bats
@@ -5,10 +5,14 @@
# (appended, deduped) and CLAUDE.md is seed-only, so both compose across
# bundles. Three do not:
#
-# claude/settings.json elisp, bash, go — cp -rT, silently overwritten
-# githooks/pre-commit elisp, bash, go — cp -rT, silently overwritten
+# claude/settings.json all 5 bundles — cp -rT, silently overwritten
+# githooks/pre-commit all 5 bundles — cp -rT, silently overwritten
# coverage-makefile.txt 4 bundles — [skip]ped, fragment dropped
#
+# The first two read "elisp, bash, go" until 2026-07-23, when python and
+# typescript gained the components they had been missing. The consequence is
+# that no two shipping bundles compose any more; see the polyglot task.
+#
# Installing a second bundle used to replace the first's settings.json and
# pre-commit while printing [ok], so a project could lose its paren check or
# secret scan and read the output as success. The guard refuses instead, naming
@@ -68,8 +72,11 @@ teardown() {
}
@test "install-lang: bundles colliding only on coverage-makefile.txt are refused too" {
- # python and typescript ship no settings.json or githooks, but both ship a
- # coverage fragment. The second one's used to be silently dropped.
+ # Named for the pre-2026-07-23 reason: python and typescript shipped no
+ # settings.json or githooks, so the coverage fragment was their only overlap
+ # and the second one's used to be silently dropped. They now overlap on all
+ # three, so this exercises the multi-file refusal path — the coverage
+ # fragment must still be named among them.
bash "$INSTALL" python "$PROJ"
run bash "$INSTALL" typescript "$PROJ"
[ "$status" -ne 0 ] || { echo "typescript installed over python's coverage fragment"; return 1; }
@@ -77,17 +84,41 @@ teardown() {
}
@test "install-lang: two bundles that share no overwritten file install together" {
- # bash ships settings.json + githooks and no coverage fragment; python ships
- # only the coverage fragment. Nothing overlaps, so the guard must stay out of
- # the way. This is the path where a false refusal would be easiest to
- # introduce: the bundle IS detected, and only the empty file-list stops it.
+ # The guard must stay out of the way when nothing overlaps. This is the path
+ # where a false refusal would be easiest to introduce: the bundle IS
+ # detected, and only the empty file-list stops it.
+ #
+ # This used to be tested with bash + python, which composed because python
+ # shipped no settings.json and no githooks. That was the incomplete-bundle
+ # bug (fixed 2026-07-23), not a design property — so no pair of *shipping*
+ # bundles is non-colliding any more, and the case needs a synthetic bundle.
+ # See the polyglot task in todo.org: whether every pair now colliding is
+ # acceptable is an open question, but the guard's own no-false-refusal
+ # behavior is not, and stays pinned here.
+ fake="${BATS_TEST_DIRNAME}/../../languages/zz-test-rulesonly"
+ mkdir -p "$fake/claude/rules"
+ printf '# rule\n' > "$fake/claude/rules/zz-testing.md"
+
bash "$INSTALL" bash "$PROJ"
- run bash "$INSTALL" python "$PROJ"
+ run bash "$INSTALL" zz-test-rulesonly "$PROJ"
+ rm -rf "$fake"
+
[ "$status" -eq 0 ] || { echo "guard falsely refused a non-colliding pair: $output"; return 1; }
- [ -f "$PROJ/coverage-makefile.txt" ] || { echo "python's coverage fragment did not land"; return 1; }
# bash's config survives untouched.
grep -q 'validate-bash.sh' "$PROJ/.claude/settings.json"
- [ -f "$PROJ/.claude/rules/bash.md" ] && [ -f "$PROJ/.claude/rules/python-testing.md" ]
+ [ -f "$PROJ/.claude/rules/bash.md" ] && [ -f "$PROJ/.claude/rules/zz-testing.md" ]
+}
+
+@test "install-lang: completing python made it collide with bash (documents the tradeoff)" {
+ # Pins the consequence of the 2026-07-23 bundle completion so it can't drift
+ # back unnoticed: python now ships settings.json + githooks/pre-commit, so
+ # bash + python is a genuine overwrite conflict and the guard refuses it.
+ # Whether that's the right trade is Craig's open call; that it IS the current
+ # behavior is what this test records.
+ bash "$INSTALL" bash "$PROJ"
+ run bash "$INSTALL" python "$PROJ"
+ [ "$status" -ne 0 ]
+ [[ "$output" == *"collision"* ]]
}
# ---- The escape hatch ----