diff --git a/tests/run-prune.bats b/tests/run-prune.bats new file mode 100644 index 0000000..af2c5ca --- /dev/null +++ b/tests/run-prune.bats @@ -0,0 +1,68 @@ +#!/usr/bin/env bats +# tests/run-prune.bats — prune orphaned sources (no LLM, no network; DRY_RUN). +setup() { + load 'helpers' + export PRUNE="${SKILL_SCRIPTS}/run-prune.sh" + export GENOMES_ROOT="${BATS_TEST_TMPDIR}" + export INGEST_BASE="main" + export KG_LIB_DIR="${LIB_DIR}" + export FORGEJO_URL="http://forgejo.local" FORGEJO_USER="u" FORGEJO_TOKEN="t" + export DRY_RUN=1 + g_src="$(make_fixture_genome)"; export g_name="fixture-genome" + mv "$g_src" "${GENOMES_ROOT}/${g_name}"; export g="${GENOMES_ROOT}/${g_name}" + ( cd "$g" && rm -f raw/articles/test.md && git add -A && git commit -q -m clear && git push -q ) +} + +@test "run-prune: removes only the orphaned source + its index entry, opens a dry PR" { + command -v jq >/dev/null 2>&1 || skip "jq not installed" + cd "$g" + # kept: raw exists. orphan: raw missing. + echo content > raw/articles/kept.md + h="$(sha256sum raw/articles/kept.md | cut -d' ' -f1)" + printf -- '---\nsource_path: raw/articles/kept.md\nsource_sha256: %s\n---\nbody\n' "$h" > wiki/sources/kept.md + printf -- '---\nsource_path: raw/articles/gone.md\nsource_sha256: abc\n---\nbody\n' > wiki/sources/orphan.md + python3 "$SKILL_SCRIPTS/index-append.py" --section Sources --entry '- [[sources/kept]] — kept. `maturity: draft`' + python3 "$SKILL_SCRIPTS/index-append.py" --section Sources --entry '- [[sources/orphan]] — orphan. `maturity: draft`' + git add -A && git commit -q -m setup && git push -q + + run bash "$PRUNE" "$g_name" + [ "$status" -eq 0 ] + [[ "$output" == *'"status":"ok"'* ]] + [[ "$output" == *'"count":1'* ]] + + # only the orphan page is gone + [ ! -f wiki/sources/orphan.md ] + [ -f wiki/sources/kept.md ] + # index reflects the removal + ! grep -q 'sources/orphan' wiki/index.md + grep -q 'sources/kept' wiki/index.md + # committed on a chore/ branch (NOT feat/ai-ingest-*) + git rev-parse --verify "chore/prune-orphans-$(date +%F)" +} + +@test "run-prune: no orphans -> count 0 and no PR/branch" { + command -v jq >/dev/null 2>&1 || skip "jq not installed" + cd "$g" + echo content > raw/articles/kept.md + h="$(sha256sum raw/articles/kept.md | cut -d' ' -f1)" + printf -- '---\nsource_path: raw/articles/kept.md\nsource_sha256: %s\n---\nbody\n' "$h" > wiki/sources/kept.md + git add -A && git commit -q -m setup && git push -q + + run bash "$PRUNE" "$g_name" + [ "$status" -eq 0 ] + [[ "$output" == *'"count":0'* ]] + run git rev-parse --verify "chore/prune-orphans-$(date +%F)" + [ "$status" -ne 0 ] +} + +@test "run-prune: refuses when an orphan path would escape wiki/ (defense in depth)" { + command -v jq >/dev/null 2>&1 || skip "jq not installed" + cd "$g" + # legacy page without source_path is ignored; a page with a missing raw is the orphan. + printf -- '---\nsource_path: raw/articles/gone.md\nsource_sha256: abc\n---\nbody\n' > wiki/sources/orphan.md + git add -A && git commit -q -m setup && git push -q + run bash "$PRUNE" "$g_name" + [ "$status" -eq 0 ] + [[ "$output" == *'"count":1'* ]] + [ ! -f wiki/sources/orphan.md ] +}