Task: gitlab.open-issue
Goal: Open my latest created issue that has 'theme editor' in its title to check if it is closed
Task configuration:
keyword: theme editor
order_by: created_at

Validation code:
import re
import urllib.parse as parse
from typing import Any, Dict, List

import requests
import json
import os

def _get_headers():
    return {
        "Content-Type": "application/json",
        "Accept": "application/json",
        **json.loads(os.getenv("GITLAB_EXTRA_HTTP_HEADERS", "{}")),
    }

def validate(messages: List[Dict[str, str]], config: Dict[str, Any]) -> int:

    if not messages:
        raise ValueError("Messages cannot be empty")

    content = messages[-1].get("content", "")

    if not "keyword" in config:
        raise ValueError("Target must contain 'keyword'")

    # Search for the issue via API
    # "my issues" -> "issues assigned to me" or "issues created by me"
    order_by = config.get("order_by", "updated_at")
    base_url = os.getenv("GITLAB_BASE_URL", "").rstrip("/")

    url = (
        base_url
        + "/api/v4/issues"
        + "?scope=created_by_me"
        + "&search="
        + config["keyword"]
        + "&in=title"
        + "&order_by="
        + order_by
        + "&sort=desc"
        + "&per_page=1"
    )

    response = requests.get(url=url, headers=_get_headers())
    if response.status_code != 200:
        return 0
    result = response.json()

    # Also try scope=assigned_to_me if created_by_me returns nothing
    if not result:
        url = (
            base_url
            + "/api/v4/issues"
            + "?scope=assigned_to_me"
            + "&search="
            + config["keyword"]
            + "&in=title"
            + "&order_by="
            + order_by
            + "&sort=desc"
            + "&per_page=1"
        )
        response = requests.get(url=url, headers=_get_headers())
        if response.status_code != 200:
            return 0
        result = response.json()

    if not result:
        return 0

    target_issue = result[0]
    expected_reference = target_issue["references"]["full"]

    # Try URL-based validation — search all URLs, parse path (hostname-agnostic)
    all_urls = re.findall(r"https?://\S+", content)
    for found_url in all_urls:
        parsed = parse.urlparse(parse.unquote(found_url))
        path = parsed.path.lstrip("/")
        # Expected pattern: {namespace}/{project}/-/issues/{iid}
        issue_parts = path.split("/-/issues/")
        if len(issue_parts) == 2:
            ns_project = issue_parts[0]
            iid = issue_parts[1].rstrip("/")
            parts = ns_project.split("/")
            if len(parts) >= 2:
                current_url_reference = f"{parts[0]}/{parts[1]}#{iid}"
                if current_url_reference == expected_reference:
                    return 1

    # Fallback: check if the agent's message mentions the issue title or state
    issue_title = target_issue["title"].lower()
    issue_state = target_issue["state"].lower()
    content_lower = content.lower()

    # The task asks to check if the issue is closed
    # Validate that the agent found the right issue and reported its state
    if issue_title in content_lower:
        # Agent mentioned the issue title
        if issue_state in content_lower:
            return 1
        # Also accept "open" as synonym for "opened"
        if issue_state == "opened" and "open" in content_lower:
            return 1
        # Accept if they mentioned the issue URL reference
        if expected_reference in content:
            return 1

    # Check if the issue web_url appears in the message (hostname-agnostic)
    expected_web_url = target_issue.get("web_url", "")
    if expected_web_url and expected_web_url in content:
        return 1
    # Also check by path only (different hostname)
    if expected_web_url:
        expected_path = parse.urlparse(expected_web_url).path
        for found_url in all_urls:
            if parse.urlparse(found_url).path == expected_path:
                return 1

    return 0