Exactly one AI disclosure checkbox must be selected. If the "AI tools were used" option is checked, at least 5 words of additional description must be present in that section.
(pr_body)
| 358 | |
| 359 | |
| 360 | def check_ai_disclosure(pr_body): |
| 361 | """Exactly one AI disclosure checkbox must be selected. |
| 362 | |
| 363 | If the "AI tools were used" option is checked, at least 5 words of |
| 364 | additional description must be present in that section. |
| 365 | """ |
| 366 | ai_match = re.search( |
| 367 | r"#### AI Assistance Disclosure[^\n]*\n(.*?)(?=\r?\n####|\Z)", |
| 368 | pr_body, |
| 369 | re.DOTALL, |
| 370 | ) |
| 371 | if not ai_match: |
| 372 | return Message(*MISSING_AI_DISCLOSURE) |
| 373 | |
| 374 | section = strip_html_comments(ai_match.group(1)) |
| 375 | no_ai_checked = bool( |
| 376 | re.search(r"-\s*\[x\].*?No AI tools were used", section, re.IGNORECASE) |
| 377 | ) |
| 378 | ai_used_checked = bool( |
| 379 | re.search(r"-\s*\[x\].*?If AI tools were used", section, re.IGNORECASE) |
| 380 | ) |
| 381 | |
| 382 | # Must check exactly one option. |
| 383 | if no_ai_checked == ai_used_checked: |
| 384 | return Message(*MISSING_AI_DISCLOSURE) |
| 385 | |
| 386 | if ai_used_checked: |
| 387 | # Collect non-checkbox lines for word count. |
| 388 | extra_lines = [ |
| 389 | line.strip() |
| 390 | for line in section.splitlines() |
| 391 | if line.strip() and not line.strip().startswith("- [") |
| 392 | ] |
| 393 | # Ensure PR author includes at least 5 words about their AI use. |
| 394 | if len(" ".join(extra_lines).split()) < MIN_WORDS: |
| 395 | return Message(*MISSING_AI_DESCRIPTION) |
| 396 | |
| 397 | return None |
| 398 | |
| 399 | |
| 400 | def check_checklist(pr_body): |