Skip to content

Refactor IssueHandler from supervisor to issue_verification_agent #473

Open
martinky82 wants to merge 37 commits into
packit:mainfrom
martinky82:main
Open

Refactor IssueHandler from supervisor to issue_verification_agent #473
martinky82 wants to merge 37 commits into
packit:mainfrom
martinky82:main

Conversation

@martinky82
Copy link
Copy Markdown
Contributor

TODO:

  • Write new tests or update the old ones to cover new functionality.
  • Update doc-strings where appropriate.
  • Update or write new documentation in packit/packit.dev.
  • ‹fill in›

Fixes

Related to

Merge before/after

RELEASE NOTES BEGIN

Packit now supports automatic ordering of ☕ after all checks pass.

RELEASE NOTES END

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the Issue Verification Agent, migrating the post-fix lifecycle management from the supervisor to a dedicated BeeAI workflow. Key additions include modules for baseline test reproduction, XUnit comparison, and a testing analyst agent, along with several new tools for interacting with Jira, GitLab, the Errata Tool, and Testing Farm. Feedback highlights a critical bug in the Jira attachment tool call involving incorrect data structures and encoding. Performance improvements were also requested to wrap blocking synchronous calls in threads within asynchronous methods, and a simplification was suggested for unreachable code in the GitLab MR search logic.

Comment thread ymir/agents/utilities/baseline_tests.py
Comment thread ymir/tools/privileged/errata.py
Comment thread ymir/tools/unprivileged/analyze_ewa_testrun.py Outdated
Comment thread ymir/agents/issue_verification_agent.py
Copy link
Copy Markdown
Member

@TomasTomecek TomasTomecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow, this is massive, thank you for working on this

are you also planning to drop the former supervisor code?

btw this definitely needs rebase against upstream/main

@martinky82
Copy link
Copy Markdown
Contributor Author

martinky82 commented May 12, 2026

After the errata agent is moved out of supervisor, the supervisor will be dropped altogether of course. I reckon it's on the safe side to keep the code in there for the moment.

Yeah, some stuff landed since I started working on it so rebase it needs.

Move the IssueHandler workflow from ymir/supervisor/ into a standalone
BeeAI Framework agent at ymir/agents/issue_verification_agent.py,
following the pattern established by preliminary_testing_agent.

This includes:
- New agent: issue_verification_agent with Workflow-based state machine
- New sub-agent: testing_analyst for AI-driven test result analysis
- New MCP tools: errata (GetErratum, GetErratumBuildNvr),
  testing_farm (GetTestingFarmRequest, ReproduceTestingFarmRequest),
  gitlab (SearchGitlabProjectMrs), jira (UpdateJiraComment,
  AddJiraAttachments, GetJiraAttachment)
- New unprivileged tools: read_logfile, read_readme, search_resultsdb,
  analyze_ewa_testrun, read_attachment
- Supporting modules: baseline_tests, compare_xunit, qe_data
- Shared types added to ymir/common/models.py
- New skill definition for issue_verification

The supervisor's ErratumHandler remains unchanged for a follow-up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@martinky82
Copy link
Copy Markdown
Contributor Author

I rebased the PR and now I have the pre-commit installed as well, so it should be in better shape than the first attempt.

The agent only checked customfield_10418 for the errata link, but some
issues (e.g. those handled by infraserv teams directly) store the errata
link in customfield_10626 instead. Fall back to that field when the
primary one is null.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@TomasTomecek TomasTomecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please address the bug with the issue_key, the other 2 comments are mostly cosmetic

Comment thread ymir/agents/issue_verification_agent.py
return JSONToolOutput(result=results)

except Exception as e:
from beeai_framework.tools import ToolError
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shouldn't be here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you, please, elaborate?

Comment thread ymir/agents/issue_verification_agent.py Outdated
@TomasKorbar TomasKorbar self-requested a review May 14, 2026 09:19
martinky82 and others added 3 commits May 14, 2026 13:20
Inlines the function and its regex constants from
ymir/supervisor/ewa_utils.py, removing the cross-module
dependency on the supervisor package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread agents_as_skills/issue_verification/SKILL.md Outdated
Comment thread ymir/agents/utilities/baseline_tests.py
Comment thread ymir/agents/utilities/compare_xunit.py
Comment thread ymir/agents/issue_verification_agent.py Outdated
Comment thread ymir/agents/issue_verification_agent.py Outdated
Comment thread ymir/tools/unprivileged/read_attachment.py Outdated
Comment thread ymir/tools/unprivileged/read_logfile.py Outdated
Comment thread ymir/tools/unprivileged/read_readme.py
Comment thread ymir/tools/unprivileged/search_resultsdb.py Outdated
Comment thread ymir/tools/unprivileged/search_resultsdb.py Outdated
@TomasKorbar
Copy link
Copy Markdown
Collaborator

Additional note, please implement makefile target for this so it can be triggered as the other agents. For example like we do with triage make run-triage-agent-standalone DRY_RUN=true

martinky82 and others added 15 commits May 20, 2026 00:57
The get_jira_pull_requests and get_jira_dev_status tools were
returning bare lists, but MCP requires structuredContent to be
dictionaries. This caused validation errors when these tools
returned results (including empty lists).

Changes:
- Wrap return values in dictionaries with descriptive keys
  (pull_requests, commits)
- Update return type annotations to match new structure
- Update preliminary_testing_agent to extract list from dictionary

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Move the IssueHandler workflow from ymir/supervisor/ into a standalone
BeeAI Framework agent at ymir/agents/issue_verification_agent.py,
following the pattern established by preliminary_testing_agent.

This includes:
- New agent: issue_verification_agent with Workflow-based state machine
- New sub-agent: testing_analyst for AI-driven test result analysis
- New MCP tools: errata (GetErratum, GetErratumBuildNvr),
  testing_farm (GetTestingFarmRequest, ReproduceTestingFarmRequest),
  gitlab (SearchGitlabProjectMrs), jira (UpdateJiraComment,
  AddJiraAttachments, GetJiraAttachment)
- New unprivileged tools: read_logfile, read_readme, search_resultsdb,
  analyze_ewa_testrun, read_attachment
- Supporting modules: baseline_tests, compare_xunit, qe_data
- Shared types added to ymir/common/models.py
- New skill definition for issue_verification

The supervisor's ErratumHandler remains unchanged for a follow-up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The agent only checked customfield_10418 for the errata link, but some
issues (e.g. those handled by infraserv teams directly) store the errata
link in customfield_10626 instead. Fall back to that field when the
primary one is null.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Inlines the function and its regex constants from
ymir/supervisor/ewa_utils.py, removing the cross-module
dependency on the supervisor package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The get_jira_pull_requests and get_jira_dev_status tools were
returning bare lists, but MCP requires structuredContent to be
dictionaries. This caused validation errors when these tools
returned results (including empty lists).

Changes:
- Wrap return values in dictionaries with descriptive keys
  (pull_requests, commits)
- Update return type annotations to match new structure
- Update preliminary_testing_agent to extract list from dictionary

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Convert the stub SKILL.md into a comprehensive skill definition
matching the pattern used by preliminary_testing and triage skills.
Includes all workflow steps, tool listings, constants, attention
template, and output schema with examples.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move baseline_tests.py and compare_xunit.py to ymir/agents/utilities/
  subpackage to separate utility code from agent modules
- Extract MERGE_CHECK_DELAY and ERRATA_WAIT_DELAY constants in
  issue_verification_agent.py
- Convert testing_analyst from deprecated ToolCallingAgent to
  ReasoningAgent with proper config (get_chat_model,
  is_reasoning_enabled, get_tool_call_checker_config)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the testing analyst sub-agent from a separate module directly
into issue_verification_agent.py, consistent with how other workflows
embed their sub-agents. Rename schemas and templates with
TestingAnalyst/TESTING_ANALYST_ prefixes to avoid collisions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
martinky82 and others added 14 commits May 20, 2026 11:05
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use the get_maintainer_rules MCP tool to fetch package-specific
testing guidelines from AGENTS.md instead of the hardcoded
jotnar-qe-data repository. Teams can now specify test location
info in their rules repository.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap synchronous network calls in asyncio.to_thread in errata.py
  (GetErratumTool, GetErratumBuildNvrTool) and analyze_ewa_testrun.py
  to avoid blocking the event loop
- Remove redundant inline aiohttp import in jira.py, use the
  existing top-level import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ean up tools

Move JIRA attachment reading to the privileged jira module by replacing
ReadAttachmentTool with the existing GetJiraAttachmentTool. Also raise
ToolError instead of ValueError in testing_farm.py and remove unnecessary
type: ignore comments from unprivileged tools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Security should be enforced at the infrastructure level via egress
control, not by hardcoded URL patterns in tools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove unnecessary type: ignore comments, update description to reference
maintainer rules instead of removed TEST_LOCATION_INFO, and replace broad
Exception catch with specific aiohttp.ClientError and ValueError raised
as ToolError.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ervice

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tomas Tomecek <tomas@tomecek.net>
Use list.extend instead of loop append (PERF401) and fix two lines
exceeding 110 character limit (E501).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@TomasTomecek TomasTomecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used opus to review this PR and overall it's very well done there is just one internal API breakage:

Broken caller of get_jira_dev_status in zstream_search.py

The return type of GetJiraDevStatusTool and GetJiraPullRequestsTool changed from a bare list to a dict wrapper ({"commits": [...]} / {"pull_requests": [...]}). preliminary_testing_agent.py was updated to handle
this, but zstream_search.py was missed.

In ymir/tools/privileged/zstream_search.py around line 235-244:

dev_status = await run_tool(GetJiraDevStatusTool(), issue_key=issue_key)
commits = json.loads(dev_status) if isinstance(dev_status, str) else dev_status
# ...
commit_urls = [_get_patch_url(c["url"]) for c in commits if c.get("url")]

After this change, commits will be {"commits": [...]} instead of a list, so iterating it will iterate over dict keys ("commits") rather than commit objects, causing a KeyError.

The test mocks in ymir/agents/tests/unit/test_zstream_search.py also still return bare lists, so the tests pass but don't catch this.


Otherwise LGTM, thank you for working on this!! Looking fwd to trying this out.

martinky82 and others added 3 commits May 20, 2026 16:35
GetJiraDevStatusTool now returns {"commits": [...]} instead of a bare
list. Update zstream_search.py to extract the commits list and fix
test mocks to match the new format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@martinky82
Copy link
Copy Markdown
Contributor Author

I used opus to review this PR and overall it's very well done there is just one internal API breakage:

Broken caller of get_jira_dev_status in zstream_search.py

Good catch, thanks! Fixed in the last commit.

@martinky82
Copy link
Copy Markdown
Contributor Author

Additional note, please implement makefile target for this so it can be triggered as the other agents. For example like we do with triage make run-triage-agent-standalone DRY_RUN=true

Makefile target is implemented, thanks for the hint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants