fix: #3631526 Tag every AI call and stop when the site's guardrails stop it

Issue: #3631526 "Initialize the AI Media module"

Chunk 1 of the UX and integration plan (20 October 2026): tags, parent ID and guardrail stop detection (plan sections 2.1 and 2.2, detection only).

Depends on !6 (merged) (3631526-settings, starting at 0e290fbd). Until !6 (merged) merges, this diff includes it.

What changed

  • New ai_media.request service (AiMediaRequest). Every provider call, generators and "Ask AI" alike, goes through it:
    • Tags: ai_media, ai_media_generator:<id>, ai_media_media_type:<bundle>; "Ask AI" adds ai_media_metadata and ai_media_metadata:<name|alt|title>.
    • One request parent ID per Generate press, set on every provider used in it (frame, video, name, alt).
    • Debug data under ai_media: generator, media type, opener (field or editor), host entity type and bundle. Never the description.
    • entity_context request metadata from the Media Library opener, for AI Context.
  • Guardrail stop detection. In the AI module a stop does not throw: the answer is a chat message holding the stop message. AI Media now checks the stop results on the input after every call (global and attached sets, against the lowest threshold, like AI Automators) and also treats a chat answer where an image or video was expected as a stop. It throws GuardrailStopException, so:
    • the editor reads "This site's AI rules stopped this request. Change the description and try again." plus the site's own guardrail message;
    • users with Administer AI also see the guardrail set, linked;
    • no file is written: name and alt are now worked out before the file is saved, so a stopped "Ask AI" request also leaves nothing;
    • a stopped SVG is not retried, and a stopped "Ask AI" no longer falls back to the description.
  • drupal/ai minimum raised to ^1.5 (composer.json, info.yml ai:ai (>=1.5.0)), for request metadata.
  • No events, guardrails or rules of AI Media's own. The tags and the parent ID are documented in docs/info/providers.md.
  • Tests: Kernel tests (tests/src/Kernel/AiMediaRequestTest.php) with a test guardrail plugin that checks any input (tests/modules/ai_media_test); PHPUnit now runs in CI. The fixtures recipe adds a global set with the AI module's RegEx guardrail, and 08-01-01-guardrails.feature checks the SVG and document stops.

How it was tested

  • Fresh plain Drupal 11.4 site built with the Vardot Workspace builder (aimplan1), drupal/ai 1.5.1, ai_test (Echo), ai_context 1.0.0-rc1 with ai_agents, ai_image_alt_text, Gin. One global guardrail set with the AI module's regexp_guardrail stopping on a test word.
  • Kernel (6 tests, 36 assertions): a global stop stops image, SVG and document generation and "Ask AI"; stops under the threshold pass; one press shares one parent ID across the image call and the alt call, the next press gets a new one; tags, debug data and entity_context are as documented.
  • Through the generators directly: SVG and document stopped with the site's message; image passes the built-in RegEx guardrail (it checks chat only), as expected. As an administrator the message names and links the set.
  • Varbase E2E free lane, Firefox, against aimplan1: 37 scenarios, 692 steps passed, including the two new guardrail scenarios. No file or media item with the stop word was created.
  • phpcs (Drupal, DrupalPractice), phpstan level 1, cspell, eslint (step definitions and core config on js/), stylelint: all clean.

Not tested

  • Real providers (no paid calls in this MR).
  • A guardrail that checks image or video inputs on a live site (covered by the Kernel test plugin only).
  • Post-generate stops with a real guardrail (same code path as pre-generate, covered by reading the AI module's subscriber).
  • Mobile widths (out of scope).

AI-Generated: Yes. Written with Claude Code (Claude Opus 5.5) under the Drupal AI policy; tested by the author before submission.

Checkpoints:

  • File an issue
  • Addition/Change/Update/Fix
  • Testing to ensure no regression
  • Automated unit testing coverage
  • Automated functional testing coverage
  • UX/UI designer responsibilities
  • Readability
  • Accessibility
  • Performance
  • Security
  • Developer Documentation
  • User Guide Documentation
  • Reviewed by human
  • Code review by maintainers
  • Full testing and approval
  • Credit contributors
  • Review with the product owner
  • Release notes snippet
  • Release
Edited by Rajab Natshah

Merge request reports

Loading
Loading