diff --git a/.github/workflows/persona-mention-reusable.yml b/.github/workflows/persona-mention-reusable.yml index 177a8d76b..eceb54adc 100644 --- a/.github/workflows/persona-mention-reusable.yml +++ b/.github/workflows/persona-mention-reusable.yml @@ -386,7 +386,13 @@ jobs: # triggered. Same two recursion axes and conservative §4 default floor as the # comment path's pre-filter — a PR event is no laxer: # 1. bot actor — a PR opened by an agent identity never routes - # 2. marker — a PR body carrying '\n## Summary\nautomated PR' + [ "$status" -eq 0 ] +} + +@test "pm_is_agent_authored_body ignores leading blank lines and indentation" { + run pm_is_agent_authored_body $'\n\n \n\nbody' + [ "$status" -eq 0 ] + run pm_is_agent_authored_body $' \t\nbody' + [ "$status" -eq 0 ] + run pm_is_agent_authored_body $'\r\n\r\nbody' + [ "$status" -eq 0 ] +} + +@test "pm_is_agent_authored_body does not match a marker quoted mid-body in prose" { + run pm_is_agent_authored_body $'## Summary\n\nThe `` marker is unchanged.' + [ "$status" -eq 1 ] +} + +@test "pm_is_agent_authored_body does not match a marker inside a later fenced code block" { + run pm_is_agent_authored_body $'## Summary\n\n```\n\n```' + [ "$status" -eq 1 ] +} + +@test "pm_is_agent_authored_body does not match an empty or blank body" { + run pm_is_agent_authored_body '' + [ "$status" -eq 1 ] + run pm_is_agent_authored_body $'\n \n' + [ "$status" -eq 1 ] +} + @test "pm_is_bot_actor recognises the agent identities" { run pm_is_bot_actor donpetry-bot [ "$status" -eq 0 ] @@ -693,6 +728,11 @@ runtime: # Same two recursion axes and trust floor as pm_should_route, but WITHOUT the # @-mention requirement: a PR is derived, not addressed. A PR event must not # become an ungated write surface, so the guards apply on this path too (AC #4). +# +# The workflow's pull_request pre-filter uses !startsWith(body, '` marker is unchanged.' + [ "$status" -eq 0 ] +} + +@test "pm_pr_should_route blocks a PR whose body leads with the marker after blank lines (axis 2)" { + run pm_pr_should_route don-petry don-petry OWNER $'\n\n\nautomated PR' + [ "$status" -eq 1 ] +} + @test "pm_pr_should_route blocks a PR from an author below the default floor" { run pm_pr_should_route drive-by drive-by CONTRIBUTOR "PR body" [ "$status" -eq 1 ] } +# The workflow's route-pull-request job uses a cheap if: condition that must match +# the authoritative pm_pr_should_route function. The condition uses startsWith for +# the marker axis (not contains), matching pm_is_agent_authored_body's semantics: +# a marker quoted mid-body is not considered agent-authored. These verifications +# ensure a regression from startsWith back to contains would be caught by CI. +@test "pull_request workflow pre-filter uses prefix matching (startsWith, not contains)" { + local workflow="$SCRIPT_DIR/.github/workflows/persona-mention-reusable.yml" + # Inspect each job's own `if:` so a match elsewhere in the file cannot mask a + # lost guard. + local pr_if comment_if + pr_if="$(yq '.jobs.route-pull-request.if' "$workflow")" + comment_if="$(yq '.jobs.route.if' "$workflow")" + [[ "$pr_if" == *"!startsWith(github.event.pull_request.body, '