#!/usr/bin/env bats setup() { REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../../../../" && pwd)" load "$REPO_ROOT/tests/test_helper/bats-support/load" load "$REPO_ROOT/tests/test_helper/bats-assert/load" SCRIPT="$(cd "$BATS_TEST_DIRNAME/../scripts" && pwd)/validate-provenance.sh" TMPDIR="$(mktemp -d)" # Helper: create an APM package root at (apm.yml with a top-level # type: line — a real package manifest, not marketplace-only) plus a # single vendor-neutral agent file at /.apm/agents/.agent.md. make_package() { local root="$1" mkdir -p "$root/.apm/agents" cat > "$root/apm.yml" < "$root/.apm/agents/${name}.agent.md" < "$root/.apm/agents/${name}.agent.md" < "$root/sources.md" < "$dir/.apm/agents/my-agent.agent.md" < "$dir/apm.yml" < "$dir/.apm/agents/my-agent.agent.md" < "$dir/plugin.json" cat > "$dir/agents/my-agent.md" < "$dir/apm.yml" < "$dir/sub/.apm/agents/my-agent.agent.md" < "$dir/apm.yml" < "$fake_home/.apm/agents/my-agent.agent.md" < "$dir/apm.yml" < "$dir/sub/.apm/agents/my-agent.agent.md" < "$root/sources.md" <> "$root/sources.md" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_success } # --------------------------------------------------------------------------- # Check 2: source_keys slug missing from sources.md → FAIL # --------------------------------------------------------------------------- @test "FAIL: source_keys slug in agent file not present as H2 in sources.md" { local root="$TMPDIR/package" make_package "$root" make_agent_with_source_keys "$root" "my-agent" "my-source" make_sources_md "$root" "different-source" "(none)" "(none)" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_failure assert_output --partial "FAIL" } # --------------------------------------------------------------------------- # Check 3: Contributing file path doesn't exist → FAIL # --------------------------------------------------------------------------- @test "FAIL: Contributing file listed in sources.md does not exist" { local root="$TMPDIR/package" make_package "$root" make_agent_with_source_keys "$root" make_sources_md "$root" "my-source" ".apm/agents/nonexistent.agent.md" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_failure assert_output --partial "FAIL" } @test "pass: (none) in Contributing files is skipped" { local root="$TMPDIR/package" make_package "$root" make_agent_with_source_keys "$root" make_sources_md "$root" "my-source" "(none — not used directly)" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_success } # --------------------------------------------------------------------------- # Check 5: Research doc field missing or placeholder → FAIL # --------------------------------------------------------------------------- @test "FAIL: Research doc field missing from sources.md entry" { local root="$TMPDIR/package" make_package "$root" make_agent_with_source_keys "$root" cat > "$root/sources.md" < "$root/sources.md" < "$root/.apm/agents/my-agent.agent.md" < "$root/sources.md" < "$root/sources.md" < "$root/sources.md" < "$root/sources.md" < "$root/sources.md" < "$root/.apm/agents/my-agent.txt" run bash "$SCRIPT" "$root/.apm/agents/my-agent.txt" [ "$status" -eq 2 ] assert_output --partial "unrecognized extension" } @test "exit 2: a PATH with no python3 names the missing dependency instead of exiting 127" { local root="$TMPDIR/package" make_package "$root" make_clean_agent "$root" local emptybin="$TMPDIR/emptybin" mkdir -p "$emptybin" local bash_bin bash_bin="$(command -v bash)" run env -i PATH="$emptybin" HOME="$HOME" "$bash_bin" "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" [ "$status" -eq 2 ] # The needle is the DIAGNOSTIC, not the bare word: with no preflight, bash's # own "python3: command not found" would satisfy a bare-word match. assert_output --partial "python3 is required" } @test "reconciliation: a REAL agent file at non-plugin scope still exits 0 silently, never 2" { # scripts/check-scope-walkup-sync.sh fixture 6 in miniature. The exit-2 tier # must not widen to cover "find_plugin_root returned None": the file exists, # is readable and is correctly named — it is simply user/project scope. local dir="$TMPDIR/anc" mkdir -p "$dir" cat > "$dir/apm.yml" < "$fake_home/.apm/agents/my-agent.agent.md" < "$root/sources.md" < "$root/sources.md" < "$root/.apm/agents/my-agent.agent.md" make_sources_md "$root" "my-source" "(none)" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_failure assert_output --partial "not valid UTF-8" refute_output --partial "Traceback" } @test "FAIL: an undecodable contributing file is reported, not a traceback" { local root="$TMPDIR/package" make_package "$root" make_agent_with_source_keys "$root" printf '\xff\xfe---\nname: other\n---\n' > "$root/.apm/agents/other.agent.md" make_sources_md "$root" "my-source" ".apm/agents/other.agent.md" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_failure assert_output --partial "not valid UTF-8" refute_output --partial "Traceback" } @test "exit 2: an undecodable apm.yml names the file instead of dying mid walk-up" { local root="$TMPDIR/package" make_package "$root" make_clean_agent "$root" printf 'name: t\nversion: 0.1.0\ntype: skill\n# \xff\xfe\n' > "$root/apm.yml" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" [ "$status" -eq 2 ] assert_output --partial "not valid UTF-8" refute_output --partial "Traceback" } @test "a BOM-prefixed agent file still has its source_keys read (check 2 runs)" { # A leading BOM defeats parse_frontmatter()'s ^--- anchor, so no frontmatter # parsed means no source_keys parsed means nothing to validate — check 2 # went silently missing on exactly the file it was pointed at. local root="$TMPDIR/package" make_package "$root" printf '\xef\xbb\xbf---\nname: my-agent\ndescription: A valid agent description.\nsource_keys:\n - ghost-source\n---\n\nYou are a test agent.\n' \ > "$root/.apm/agents/my-agent.agent.md" make_sources_md "$root" "my-source" "(none)" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_failure assert_output --partial "source_keys slug 'ghost-source' not found in sources.md" } @test "under LC_ALL=C a sources.md carrying an em dash is read, not a UnicodeDecodeError" { local root="$TMPDIR/package" make_package "$root" make_agent_with_source_keys "$root" cat > "$root/sources.md" < "$root/sources.md" < "$root/sources.md" < "$root/.apm/agents/my-agent.agent.md" make_sources_md "$root" "my-source" ".apm/agents/my-agent.agent.md" run bash "$SCRIPT" "$root/.apm/agents/my-agent.agent.md" assert_failure local count count="$(printf '%s\n' "$output" | grep -c "^FAIL File is not valid UTF-8" || true)" [ "$count" -eq 1 ] }