Skip to content

feat(x2a): adversarial agents - #4190

Open
yray-pixel wants to merge 2 commits into
redhat-developer:mainfrom
yray-pixel:adversarialAgents
Open

feat(x2a): adversarial agents #4190
yray-pixel wants to merge 2 commits into
redhat-developer:mainfrom
yray-pixel:adversarialAgents

Conversation

@yray-pixel

Copy link
Copy Markdown
Contributor

Adds adversarial agents - a way to configure agents that check the LLM's output during conversion.

  • new Adversarial Agents page where you can create, edit, and delete agents.
  • when creating a project , you can now pick which adversarial agents to run .
  • the Module page now shows adversarial job output alongside the regular conversion results.

Tested on RHDH 1.10.2 as a dynamic plugin . created agents, selected them in the scaffolder, ran a conversion, and verified adversarial job details appear on the module page.

@rhdh-gh-app

rhdh-gh-app Bot commented Aug 6, 2026

Copy link
Copy Markdown

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-scaffolder-backend-module-x2a workspaces/x2a/plugins/scaffolder-backend-module-x2a patch v1.0.0
@red-hat-developer-hub/backstage-plugin-x2a-backend workspaces/x2a/plugins/x2a-backend patch v2.0.0
@red-hat-developer-hub/backstage-plugin-x2a-common workspaces/x2a/plugins/x2a-common patch v2.0.0
@red-hat-developer-hub/backstage-plugin-x2a-mcp-extras workspaces/x2a/plugins/x2a-mcp-extras patch v1.0.0
@red-hat-developer-hub/backstage-plugin-x2a-node workspaces/x2a/plugins/x2a-node patch v1.0.0
@red-hat-developer-hub/backstage-plugin-x2a workspaces/x2a/plugins/x2a patch v2.0.0

@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

feat(x2a): add adversarial agents CRUD, project selection, and review job output

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add adversarial agent CRUD APIs, DB storage, and OpenAPI client/server types.
• Allow selecting adversarial agents during scaffolder project creation.
• Run adversarial review jobs and show reports/logs on the Module page.
Diagram

graph TD
  UI[["X2A Frontend" انصاف]] --> API(["X2A Backend Router"]) --> DB[("X2A Database")]
  API --> KUBE(["KubeService"]) --> CM["Agents ConfigMap"] --> JOB["K8s Job Pod"] --> SCRIPT["x2a-job-script.sh"]
  subgraph Legend
    direction LR
    _ui[["UI Page"]] ~~~ _svc(["Service/Router"]) ~~~ _db[("Database")] ~~~ _file["Runtime artifact"]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Normalize project↔agent relation (join table)
  • ➕ Avoids storing JSON snapshots in a single projects column
  • ➕ Enables querying/reporting across projects/agents via SQL
  • ➕ Simplifies validating referential integrity at DB level
  • ➖ More schema/DAO complexity (new table + migrations + queries)
  • ➖ Requires deciding how/when to snapshot agent versions for reproducibility
2. Store agent IDs only (resolve at runtime)
  • ➕ No JSON serialization/parsing in DB columns
  • ➕ Always runs latest agent definition without extra update steps
  • ➖ Runs are not reproducible if agent prompts change over time
  • ➖ Deletes/edits can break historical meaning of past projects/jobs
3. Embed agents into Job spec only (no project persistence)
  • ➕ Keeps project records minimal; job is fully self-contained
  • ➕ Avoids project update flows and snapshot maintenance
  • ➖ Harder to show configured agents at project/module level later
  • ➖ Users can’t easily re-run with the same configuration without reselecting

Recommendation: The chosen approach (persisting per-project snapshots of selected agents and passing those snapshots into jobs via a job-owned ConfigMap) is a good balance for reproducibility and operational isolation. If long-term analytics/querying becomes important, consider evolving to a normalized join table while retaining immutable snapshots per job/project for auditability.

Files changed (86) +4949 / -76

Enhancement (66) +3938 / -63
createAndInitProject.tsPass adversarialAgentIds through scaffolder project creation +3/-0

Pass adversarialAgentIds through scaffolder project creation

• Extends CreateAndInitProjectParams and the backend project-create request body to optionally include adversarialAgentIds.

workspaces/x2a/plugins/scaffolder-backend-module-x2a/src/actions/createAndInitProject.ts

createProjectAction.tsAdd adversarialAgentIds input to scaffolder action schema +9/-0

Add adversarialAgentIds input to scaffolder action schema

• Updates zod schemas and manual creation flow to accept an array of adversarial agent UUIDs and pass them to project creation.

workspaces/x2a/plugins/scaffolder-backend-module-x2a/src/actions/createProjectAction.ts

conversion-project-template.yamlAdd AdversarialAgentsPicker field to conversion template +8/-0

Add AdversarialAgentsPicker field to conversion template

• Introduces an adversarialAgentIds parameter (ui:field AdversarialAgentsPicker) and wires it into the createProject step input.

workspaces/x2a/plugins/scaffolder-backend-module-x2a/templates/conversion-project-template.yaml

2025012401_create_jobs_table.tsExpand jobs.phase constraint for adversarial phases +8/-1

Expand jobs.phase constraint for adversarial phases

• Extends the jobs.phase CHECK constraint to include adversarial-analyze and adversarial-migrate.

workspaces/x2a/plugins/x2a-backend/migrations/2025012401_create_jobs_table.ts

GitRepositoryResolver.tsAdd resolver for target-only repository auth +24/-0

Add resolver for target-only repository auth

• Adds resolveTargetOnly to support adversarial phases that only need the target repository and require a target token.

workspaces/x2a/plugins/x2a-backend/src/router/GitRepositoryResolver.ts

adversarialAgents.tsAdd backend CRUD routes for adversarial agents +176/-0

Add backend CRUD routes for adversarial agents

• Introduces GET/list (with optional phase filter), GET by id, POST, PUT, and DELETE endpoints with input validation and admin-write permission enforcement.

workspaces/x2a/plugins/x2a-backend/src/router/adversarialAgents.ts

index.tsRegister adversarial agent routes in main router +2/-0

Register adversarial agent routes in main router

• Wires the new adversarial agents router into the backend API router creation.

workspaces/x2a/plugins/x2a-backend/src/router/index.ts

jobs.tsAllow log streaming for all module-scoped phases +8/-5

Allow log streaming for all module-scoped phases

• Broadens phase query validation to include any module phase (including adversarial phases) when fetching module job logs.

workspaces/x2a/plugins/x2a-backend/src/router/jobs.ts

projects.tsAttach adversarial agents on project creation and add adversarial-run trigger +131/-0

Attach adversarial agents on project creation and add adversarial-run trigger

• Adds optional adversarialAgentIds to project creation (validating IDs and storing snapshots), and introduces POST /projects/:projectId/adversarial-run to launch adversarial-analyze/migrate jobs with conflict detection.

workspaces/x2a/plugins/x2a-backend/src/router/projects.ts

openapi.yamlAdd OpenAPI definitions for adversarial agents and adversarial-run +311/-1

Add OpenAPI definitions for adversarial agents and adversarial-run

• Extends the API schema with adversarial-agents CRUD endpoints, project adversarial-run trigger, new artifacts and phase enums, and project/module schema fields for adversarial jobs and agent snapshots.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi.yaml

Api.server.tsRegenerate server API bindings for new endpoints +72/-2

Regenerate server API bindings for new endpoints

• Updates generated server bindings to include adversarial agents and adversarial-run operations per OpenAPI spec.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/apis/Api.server.ts

AdversarialAgent.model.tsAdd generated AdversarialAgent model (server) +63/-0

Add generated AdversarialAgent model (server)

• Introduces generated model types for the adversarial agent entity in the backend OpenAPI server bindings.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/AdversarialAgent.model.ts

AdversarialAgentSnapshot.model.tsAdd generated AdversarialAgentSnapshot model (server) +46/-0

Add generated AdversarialAgentSnapshot model (server)

• Introduces generated snapshot model used when persisting selected agent snapshots onto projects.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/AdversarialAgentSnapshot.model.ts

AdversarialAgentsGet200Response.model.tsAdd generated adversarial agent list response model (server) +31/-0

Add generated adversarial agent list response model (server)

• Adds generated response wrapper for list agents (agents + total).

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/AdversarialAgentsGet200Response.model.ts

AdversarialAgentsPostRequest.model.tsAdd generated create-agent request model (server) +46/-0

Add generated create-agent request model (server)

• Adds generated request shape for creating an adversarial agent.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/AdversarialAgentsPostRequest.model.ts

ArtifactType.model.tsUpdate artifact enum for adversarial report (server) +2/-1

Update artifact enum for adversarial report (server)

• Extends generated artifact type enum to include adversarial_report.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/ArtifactType.model.ts

MigrationPhase.model.tsUpdate phase enum for adversarial phases (server) +7/-1

Update phase enum for adversarial phases (server)

• Extends generated phase enum to include adversarial-analyze and adversarial-migrate.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/MigrationPhase.model.ts

Module.model.tsExpose adversarial job fields on Module model (server) +2/-0

Expose adversarial job fields on Module model (server)

• Updates generated Module model to include adversarialAnalyze/adversarialMigrate job references.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/Module.model.ts

Project.model.tsExpose adversarial agent snapshots on Project model (server) +5/-0

Expose adversarial agent snapshots on Project model (server)

• Updates generated Project model to include adversarialAgents snapshots.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/Project.model.ts

ProjectsPostRequest.model.tsAllow adversarialAgentIds on project create request (server) +4/-0

Allow adversarialAgentIds on project create request (server)

• Extends generated project-create request model to include adversarialAgentIds.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/ProjectsPostRequest.model.ts

ProjectsProjectIdAdversarialRunPost202Response.model.tsAdd generated 202 response model for adversarial-run (server) +33/-0

Add generated 202 response model for adversarial-run (server)

• Adds generated response model returning jobId and k8sJobName for accepted adversarial runs.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/ProjectsProjectIdAdversarialRunPost202Response.model.ts

ProjectsProjectIdAdversarialRunPostRequest.model.tsAdd generated request model for adversarial-run (server) +42/-0

Add generated request model for adversarial-run (server)

• Adds generated request model for triggering adversarial review (phase, moduleId, targetRepoAuth).

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/ProjectsProjectIdAdversarialRunPostRequest.model.ts

index.tsExport new OpenAPI models (server) +6/-0

Export new OpenAPI models (server)

• Updates the generated models barrel to export adversarial agent related models.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/models/index.ts

router.tsRegenerate OpenAPI router wiring (server) +440/-3

Regenerate OpenAPI router wiring (server)

• Updates generated router registration to include adversarial agent CRUD and project adversarial-run endpoints.

workspaces/x2a/plugins/x2a-backend/src/schema/openapi/generated/router.ts

JobResourceBuilder.tsMount adversarial agent ConfigMap and set imagePullPolicy +74/-2

Mount adversarial agent ConfigMap and set imagePullPolicy

• Adds imagePullPolicy support to job specs and introduces a job-owned ConfigMap builder that writes agents.json and mounts it into the job pod for adversarial phases.

workspaces/x2a/plugins/x2a-backend/src/services/JobResourceBuilder.ts

KubeService.tsCreate and mount adversarial agents ConfigMap for adversarial phases +51/-1

Create and mount adversarial agents ConfigMap for adversarial phases

• Detects adversarial phases, generates a per-job ConfigMap name, passes it into the job spec, and creates the ConfigMap owned by the Job for GC cleanup.

workspaces/x2a/plugins/x2a-backend/src/services/KubeService.ts

adversarialAgentOperations.tsImplement adversarial agent DB operations and project snapshot attachment +231/-0

Implement adversarial agent DB operations and project snapshot attachment

• Adds CRUD operations for adversarial_agents, validates agent IDs when attaching to projects, stores snapshots as JSON in projects.adversarial_agents, and supports listing agents with a phase filter.

workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/adversarialAgentOperations.ts

index.tsExpose adversarial agent operations via X2ADatabaseService API +106/-21

Expose adversarial agent operations via X2ADatabaseService API

• Wires AdversarialAgentOperations into the service, adds public methods for agent CRUD and project snapshot attach/fetch, and enriches Module reads with last adversarial jobs.

workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/index.ts

mappers.tsMap project adversarial agent snapshots from DB rows +17/-0

Map project adversarial agent snapshots from DB rows

• Extends project row mapping to parse adversarial_agents JSON into typed snapshots (best-effort).

workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/mappers.ts

x2a-job-script.shAdd adversarial-analyze/migrate job execution path +59/-5

Add adversarial-analyze/migrate job execution path

• Skips source repo clone for adversarial phases, reads agents.json from the mounted ConfigMap, runs x2a adversarial-run, and publishes markdown/JSON reports as artifacts.

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh

Api.client.tsRegenerate frontend client for new adversarial endpoints +214/-2

Regenerate frontend client for new adversarial endpoints

• Updates generated API client to include adversarial agents CRUD and project adversarial-run operations.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/apis/Api.client.ts

AdversarialAgent.model.tsAdd generated AdversarialAgent model (client) +63/-0

Add generated AdversarialAgent model (client)

• Introduces generated client-side model for adversarial agents.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/AdversarialAgent.model.ts

AdversarialAgentSnapshot.model.tsAdd generated AdversarialAgentSnapshot model (client) +46/-0

Add generated AdversarialAgentSnapshot model (client)

• Introduces generated snapshot model used by Project schemas.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/AdversarialAgentSnapshot.model.ts

AdversarialAgentsGet200Response.model.tsAdd generated adversarial agent list response model (client) +31/-0

Add generated adversarial agent list response model (client)

• Adds generated response wrapper type for listing agents.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/AdversarialAgentsGet200Response.model.ts

AdversarialAgentsPostRequest.model.tsAdd generated create-agent request model (client) +46/-0

Add generated create-agent request model (client)

• Adds generated request type for creating agents from the frontend.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/AdversarialAgentsPostRequest.model.ts

ArtifactType.model.tsUpdate artifact enum for adversarial report (client) +2/-1

Update artifact enum for adversarial report (client)

• Extends generated artifact type to include adversarial_report.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/ArtifactType.model.ts

MigrationPhase.model.tsUpdate phase enum for adversarial phases (client) +7/-1

Update phase enum for adversarial phases (client)

• Extends generated migration phase enum for adversarial-analyze/migrate.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/MigrationPhase.model.ts

Module.model.tsExpose adversarial job fields on Module model (client) +2/-0

Expose adversarial job fields on Module model (client)

• Updates generated Module model to include adversarialAnalyze/adversarialMigrate jobs returned from backend.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/Module.model.ts

Project.model.tsExpose adversarial agent snapshots on Project model (client) +5/-0

Expose adversarial agent snapshots on Project model (client)

• Updates generated Project model to include adversarialAgents snapshots.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/Project.model.ts

ProjectsPostRequest.model.tsAllow adversarialAgentIds on project create request (client) +4/-0

Allow adversarialAgentIds on project create request (client)

• Extends generated project-create request model to include adversarialAgentIds.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/ProjectsPostRequest.model.ts

ProjectsProjectIdAdversarialRunPost202Response.model.tsAdd generated 202 response model for adversarial-run (client) +33/-0

Add generated 202 response model for adversarial-run (client)

• Adds generated response type for accepted adversarial runs.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/ProjectsProjectIdAdversarialRunPost202Response.model.ts

ProjectsProjectIdAdversarialRunPostRequest.model.tsAdd generated request model for adversarial-run (client) +42/-0

Add generated request model for adversarial-run (client)

• Adds generated request type used by the Module page to trigger adversarial review.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/ProjectsProjectIdAdversarialRunPostRequest.model.ts

index.tsExport new OpenAPI models (client) +6/-0

Export new OpenAPI models (client)

• Updates the generated models barrel to export adversarial-related types.

workspaces/x2a/plugins/x2a-common/client/src/schema/openapi/generated/models/index.ts

AdversarialAgent.tsAdd AdversarialAgentEntity domain model +126/-0

Add AdversarialAgentEntity domain model

• Introduces a validated domain entity with snapshot conversion for storing and transporting adversarial agent data safely.

workspaces/x2a/plugins/x2a-common/src/domain/AdversarialAgent.ts

ArtifactKind.tsAdd adversarial_report artifact kind +2/-0

Add adversarial_report artifact kind

• Extends ArtifactKind with ADVERSARIAL_REPORT so reports can be linked and rendered consistently.

workspaces/x2a/plugins/x2a-common/src/domain/ArtifactKind.ts

Phase.tsAdd adversarial phases and agent-phase validation helpers +26/-5

Add adversarial phases and agent-phase validation helpers

• Adds adversarial-analyze/migrate phases, exposes adversarialPhases, and introduces adversarialAgentPhaseValues (analyze|migrate) used for agent configuration validation.

workspaces/x2a/plugins/x2a-common/src/domain/Phase.ts

index.tsExport AdversarialAgentEntity from domain index +1/-0

Export AdversarialAgentEntity from domain index

• Adds AdversarialAgentEntity to the domain public exports.

workspaces/x2a/plugins/x2a-common/src/domain/index.ts

x2aArtifactTypeLiterals.tsAdd adversarial_report to artifact type literals +1/-0

Add adversarial_report to artifact type literals

• Extends the canonical artifact type literals to include adversarial_report.

workspaces/x2a/plugins/x2a-common/src/x2aArtifactTypeLiterals.ts

createListModulesAction.tsAllow adversarial phases in MCP list-modules schema +8/-1

Allow adversarial phases in MCP list-modules schema

• Extends the returned job phase enum to include adversarial-analyze and adversarial-migrate.

workspaces/x2a/plugins/x2a-mcp-extras/src/actions/createListModulesAction.ts

X2ADatabaseService.tsExtend node-side database service typings for adversarial agents +42/-1

Extend node-side database service typings for adversarial agents

• Updates the x2a-node service surface to include adversarial agent-related operations used by the backend plugin.

workspaces/x2a/plugins/x2a-node/src/services/X2ADatabaseService.ts

types.tsUpdate node service types for adversarial agent snapshots +3/-0

Update node service types for adversarial agent snapshots

• Adjusts shared types to accommodate new adversarial agent entities/snapshots across packages.

workspaces/x2a/plugins/x2a-node/src/services/types.ts

alpha.tsxRegister AdversarialAgentsPicker form field in new frontend system +20/-1

Register AdversarialAgentsPicker form field in new frontend system

• Adds a scaffolder form-field blueprint that lazily loads the AdversarialAgentsPicker field extension.

workspaces/x2a/plugins/x2a/src/alpha.tsx

AdversarialAgentsPage.tsxAdd admin-only Adversarial Agents management page shell +69/-0

Add admin-only Adversarial Agents management page shell

• Adds a dedicated page with permission gating (admin write) and renders the management table when allowed.

workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AdversarialAgentsPage.tsx

AdversarialAgentsTable.tsxImplement adversarial agents table with create/edit/delete flows +234/-0

Implement adversarial agents table with create/edit/delete flows

• Fetches agents via the generated client, displays them in a table, and wires create/edit dialog plus delete confirmation.

workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AdversarialAgentsTable.tsx

AgentDialog.tsxAdd create/edit agent dialog with local validation +241/-0

Add create/edit agent dialog with local validation

• Implements a modal for editing name/prompt/phases/critical and calls POST/PUT endpoints with basic client-side constraints.

workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AgentDialog.tsx

DeleteAgentDialog.tsxAdd delete confirmation dialog for agents +79/-0

Add delete confirmation dialog for agents

• Adds a simple confirmation modal with loading state used by the agents table delete action.

workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/DeleteAgentDialog.tsx

AdversarialAgentsSelector.tsxAdd multi-select UI for choosing adversarial agents +131/-0

Add multi-select UI for choosing adversarial agents

• Implements an autocomplete-based selector that loads agents from the backend and returns selected agent IDs.

workspaces/x2a/plugins/x2a/src/components/CreateProjectPage/AdversarialAgentsSelector.tsx

Dashboard.tsxUpdate dashboard to surface adversarial agents entry point +9/-1

Update dashboard to surface adversarial agents entry point

• Adjusts dashboard UI to accommodate adversarial agents navigation/messaging (details in diff).

workspaces/x2a/plugins/x2a/src/components/Dashboard/Dashboard.tsx

AdversarialJobDetails.tsxRender adversarial job status, report link, telemetry, and logs +259/-0

Render adversarial job status, report link, telemetry, and logs

• Adds a dedicated details component for adversarial phases, including artifact link to adversarial_report, log streaming, and telemetry rendering.

workspaces/x2a/plugins/x2a/src/components/ModulePage/AdversarialJobDetails.tsx

ModulePage.tsxAdd UI action to trigger adversarial review runs +59/-6

Add UI action to trigger adversarial review runs

• Adds client calls to POST /projects/:projectId/adversarial-run (target repo auth only) and passes the handler into the phases card.

workspaces/x2a/plugins/x2a/src/components/ModulePage/ModulePage.tsx

PhasesCard.tsxShow adversarial job details alongside normal phase details +23/-0

Show adversarial job details alongside normal phase details

• Adds adversarial job panels (adversarial-analyze/migrate) under the Analyze and Migrate tabs and wires an optional run-adversarial handler.

workspaces/x2a/plugins/x2a/src/components/ModulePage/PhasesCard.tsx

PhaseDetails.tsxUpdate phase details rendering for new phase/artifact types +27/-1

Update phase details rendering for new phase/artifact types

• Extends phase detail rendering to account for adversarial phases/artifacts (details in diff).

workspaces/x2a/plugins/x2a/src/components/PhaseDetails.tsx

Router.tsxAdd route for Adversarial Agents page +6/-0

Add route for Adversarial Agents page

• Registers the /adversarial-agents route and mounts the AdversarialAgentsPage component.

workspaces/x2a/plugins/x2a/src/components/Router.tsx

plugin.tsProvide AdversarialAgentsPicker scaffolder field extension +9/-0

Provide AdversarialAgentsPicker scaffolder field extension

• Registers the AdversarialAgentsPicker field extension so templates can reference it via ui:field.

workspaces/x2a/plugins/x2a/src/plugin.ts

routes.tsAdd adversarial agents route ref +6/-0

Add adversarial agents route ref

• Defines adversarialAgentsRouteRef under the plugin root for frontend routing.

workspaces/x2a/plugins/x2a/src/routes.ts

AdversarialAgentsPickerFieldExtension.tsxImplement AdversarialAgentsPicker scaffolder field component +39/-0

Implement AdversarialAgentsPicker scaffolder field component

• Wraps AdversarialAgentsSelector as a scaffolder field extension and displays raw schema errors when present.

workspaces/x2a/plugins/x2a/src/scaffolder/AdversarialAgentsPickerFieldExtension/AdversarialAgentsPickerFieldExtension.tsx

Bug fix (2) +11 / -7
CurrentPhaseCell.tsxHandle phases without step mapping (e.g., adversarial phases) +3/-2

Handle phases without step mapping (e.g., adversarial phases)

• Makes the phase-to-step mapping partial and avoids rendering step counters when unknown phases are provided.

workspaces/x2a/plugins/x2a/src/components/CurrentPhaseCell.tsx

getNextPhase.tsPrevent adversarial phases from breaking next-phase computation +8/-5

Prevent adversarial phases from breaking next-phase computation

• Restricts rerun-on-error logic to regular module phases and uses partial mappings to avoid invalid phase keys.

workspaces/x2a/plugins/x2a/src/components/tools/getNextPhase.ts

Refactor (6) +39 / -2
projectOperations.tsAllow nullable update fields in project updates +1/-1

Allow nullable update fields in project updates

• Adjusts updateFields typing to allow null assignments, aligning with new nullable columns/updates.

workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/projectOperations.ts

index.tsExport AdversarialAgentsPage component +17/-0

Export AdversarialAgentsPage component

• Adds barrel export for the new Adversarial Agents page.

workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/index.ts

ModuleTable.tsxAdjust module table rendering for extended phase set +2/-1

Adjust module table rendering for extended phase set

• Updates module table behavior to handle expanded phases and/or new module fields (details in diff).

workspaces/x2a/plugins/x2a/src/components/ModuleTable/ModuleTable.tsx

index.tsUpdate plugin exports for new components/routes +1/-0

Update plugin exports for new components/routes

• Adjusts top-level exports to include newly added page/field extension wiring (details in diff).

workspaces/x2a/plugins/x2a/src/index.ts

index.tsAdd barrel export for AdversarialAgentsPickerFieldExtension +17/-0

Add barrel export for AdversarialAgentsPickerFieldExtension

• Exports the picker field extension from its directory index.

workspaces/x2a/plugins/x2a/src/scaffolder/AdversarialAgentsPickerFieldExtension/index.ts

index.tsExport AdversarialAgentsPickerFieldExtension from scaffolder module +1/-0

Export AdversarialAgentsPickerFieldExtension from scaffolder module

• Adds the new picker field extension to scaffolder exports alongside existing fields.

workspaces/x2a/plugins/x2a/src/scaffolder/index.ts

Tests (4) +791 / -4
plugin.test.tsExtend backend plugin test mocks for adversarial agent APIs +22/-0

Extend backend plugin test mocks for adversarial agent APIs

• Updates the x2aDatabase service mock to include adversarial agent CRUD/snapshot methods used by the router.

workspaces/x2a/plugins/x2a-backend/src/plugin.test.ts

adversarialAgents.test.tsAdd integration tests for adversarial agents endpoints +530/-0

Add integration tests for adversarial agents endpoints

• Adds comprehensive tests across supported DBs covering happy paths, filtering, validation errors, and permission-denied behavior for all CRUD endpoints.

workspaces/x2a/plugins/x2a-backend/src/router/adversarialAgents.test.ts

AdversarialAgent.test.tsAdd unit tests for AdversarialAgentEntity validation and helpers +186/-0

Add unit tests for AdversarialAgentEntity validation and helpers

• Covers constructor validation, fromRow handling, snapshot conversion, and equals/toString semantics.

workspaces/x2a/plugins/x2a-common/src/domain/AdversarialAgent.test.ts

Phase.test.tsUpdate Phase tests for adversarial phases +53/-4

Update Phase tests for adversarial phases

• Extends phase parsing and enumeration tests to cover adversarial phases and new helper methods.

workspaces/x2a/plugins/x2a-common/src/domain/Phase.test.ts

Documentation (5) +83 / -0
de.tsAdd DE translations for adversarial agents UI +2/-0

Add DE translations for adversarial agents UI

• Updates German translation bundle to include adversarial agents page/module strings.

workspaces/x2a/plugins/x2a/src/translations/de.ts

es.tsAdd ES translations for adversarial agents UI +2/-0

Add ES translations for adversarial agents UI

• Updates Spanish translation bundle to include adversarial agents page/module strings.

workspaces/x2a/plugins/x2a/src/translations/es.ts

fr.tsAdd FR translations for adversarial agents UI +2/-0

Add FR translations for adversarial agents UI

• Updates French translation bundle to include adversarial agents page/module strings.

workspaces/x2a/plugins/x2a/src/translations/fr.ts

it.tsAdd IT translations for adversarial agents UI +2/-0

Add IT translations for adversarial agents UI

• Updates Italian translation bundle to include adversarial agents page/module strings.

workspaces/x2a/plugins/x2a/src/translations/it.ts

ref.tsAdd reference strings for adversarial agents and module UI +75/-0

Add reference strings for adversarial agents and module UI

• Adds canonical i18n strings for adversarial agent selection, management UI, adversarial review actions, and new artifact/phase labels.

workspaces/x2a/plugins/x2a/src/translations/ref.ts

Other (3) +87 / -0
chilly-needles-own.mdAdd changeset for adversarial agents rollout +10/-0

Add changeset for adversarial agents rollout

• Adds a patch changeset covering x2a backend, frontend, common, node, scaffolder module, and MCP extras packages.

workspaces/x2a/.changeset/chilly-needles-own.md

app-config.yamlExpose kubernetes imagePullPolicy configuration +2/-0

Expose kubernetes imagePullPolicy configuration

• Adds an x2a.kubernetes.imagePullPolicy setting with an environment variable override for local/dev clusters.

workspaces/x2a/app-config.yaml

202607081000_create_adversarial_agents_table.tsCreate adversarial_agents table and project snapshot column +75/-0

Create adversarial_agents table and project snapshot column

• Adds a new adversarial_agents table, adds projects.adversarial_agents JSON snapshot column, and (PG only) updates jobs.phase constraint; includes full down migration.

workspaces/x2a/plugins/x2a-backend/migrations/202607081000_create_adversarial_agents_table.ts

@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Aug 6, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (3) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Invalid agent phases stored ✓ Resolved 🐞 Bug ≡ Correctness
Description
The adversarial agents API accepts arbitrary phase strings, but AdversarialAgentEntity only allows
phases in {analyze,migrate}; AdversarialAgentOperations inserts the DB row before
constructing/validating the entity, so invalid phases can be persisted and later break
GET/list/attach flows.
Code

workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/adversarialAgentOperations.ts[R45-48]

+    await this.#dbClient('adversarial_agents').insert({
+      id,
+      name: input.name,
+      prompt: input.prompt,
Relevance

●●● Strong

Input validation before insert is a clear correctness fix; aligns with past accepted
schema/validation hardening.

PR-#3144

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The route schema permits any phase strings, but the domain entity rejects anything outside
{analyze,migrate}. Because the DB insert happens before entity construction, a bad phase can be
committed and then throw, leaving a persisted invalid record.

workspaces/x2a/plugins/x2a-backend/src/router/adversarialAgents.ts[86-91]
workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/adversarialAgentOperations.ts[35-68]
workspaces/x2a/plugins/x2a-common/src/domain/AdversarialAgent.ts[52-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Adversarial agent creation/update can persist invalid `phases` values because request validation allows any string and the DB insert happens before `AdversarialAgentEntity` validation. If validation throws after the insert, the request fails but the invalid row remains.

## Issue Context
`AdversarialAgentEntity` enforces that each phase is one of `Phase.adversarialAgentPhaseValues()` (`analyze`, `migrate`). The route schema currently allows `z.array(z.string())`, and `createAdversarialAgent` inserts before constructing the entity.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/src/router/adversarialAgents.ts[86-91]
- workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/adversarialAgentOperations.ts[35-68]
- workspaces/x2a/plugins/x2a-common/src/domain/AdversarialAgent.ts[52-59]

### Implementation notes
- Tighten Zod validation to `phases: z.array(z.enum(['analyze','migrate'])).min(1)`.
- In `createAdversarialAgent` / `updateAdversarialAgent`, validate by constructing `AdversarialAgentEntity` **before** writing, or wrap insert/update + validation in a DB transaction and rollback on error.
- Convert entity validation failures into `InputError` (400) instead of letting a generic `Error` surface as 500.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Non-PG phase constraint stale 🐞 Bug ≡ Correctness
Description
The new migration updates the jobs.phase CHECK constraint only when the DB client is Postgres;
upgrades on SQLite/other DBs keep the old constraint, so inserting adversarial job phases can fail
at runtime.
Code

workspaces/x2a/plugins/x2a-backend/migrations/202607081000_create_adversarial_agents_table.ts[R26-33]

+  if (knex.client.config.client === 'pg') {
+    await knex.schema.raw(
+      `ALTER TABLE jobs DROP CONSTRAINT IF EXISTS jobs_phase_check`,
+    );
+    await knex.schema.raw(
+      `ALTER TABLE jobs ADD CONSTRAINT jobs_phase_check CHECK (phase IN ('init', 'analyze', 'migrate', 'publish', 'adversarial-analyze', 'adversarial-migrate'))`,
+    );
+  }
Relevance

●● Moderate

Likely bug for non-PG DBs, but unclear if non-Postgres upgrades are supported/expected here.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The migration explicitly gates the phase constraint update behind client === 'pg', while the
backend creates jobs with phase: 'adversarial-*' and the jobs schema enforces a finite allowed set
via CHECK/checkIn. Without a non-PG migration path, non-Postgres upgrades can retain the pre-PR
allowed phases and reject inserts.

workspaces/x2a/plugins/x2a-backend/migrations/202607081000_create_adversarial_agents_table.ts[25-33]
workspaces/x2a/plugins/x2a-backend/migrations/2025012401_create_jobs_table.ts[24-46]
workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[524-555]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Existing deployments that are not Postgres won’t get the expanded `jobs.phase` constraint during migration, but the backend now creates jobs with phases like `adversarial-analyze`/`adversarial-migrate`. This can cause job creation to fail with a constraint violation.

## Issue Context
- The old `create_jobs_table` migration was edited to include the new phases, but previously-migrated DBs do not re-run it.
- The new migration only alters the CHECK constraint for Postgres.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/migrations/202607081000_create_adversarial_agents_table.ts[25-33]
- workspaces/x2a/plugins/x2a-backend/migrations/2025012401_create_jobs_table.ts[24-46]
- workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[524-555]

### Implementation notes
- Ensure the `jobs.phase` constraint is updated (or removed/relaxed) for **all supported DB clients**, not just `pg`.
- If SQLite constraint alteration is difficult, consider a migration that rebuilds the table without the restrictive CHECK or uses a DB-agnostic approach.
- Add an integration test for an upgrade scenario where the DB was migrated before this PR and verify adversarial job creation succeeds.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Project create not atomic 🐞 Bug ☼ Reliability
Description
POST /projects creates the project row and then attaches adversarial agents; if any agent ID doesn’t
exist, attachAdversarialAgentsToProject throws after the project is already created, leaving a
partially-created project even though the request fails.
Code

workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[R190-198]

+    // Attach adversarial agents if provided (validates agent IDs exist)
+    if (
+      requestBody.adversarialAgentIds &&
+      requestBody.adversarialAgentIds.length > 0
+    ) {
+      await x2aDatabase.attachAdversarialAgentsToProject({
+        projectId: newProject.id,
+        agentIds: requestBody.adversarialAgentIds,
+      });
Relevance

●● Moderate

Transactional/atomicity change is more invasive; team may accept but not guaranteed for this feature
PR.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The route creates the project before attaching adversarial agents; the attach method explicitly
throws an InputError on missing IDs, so the failure happens after the project is already persisted.

workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[179-199]
workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/adversarialAgentOperations.ts[175-184]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Project creation is not atomic when `adversarialAgentIds` are provided: the project is created first, then agent attachment can throw, causing a failed request with a persisted project.

## Issue Context
`attachAdversarialAgentsToProject` validates IDs and throws `InputError` when any are missing.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[179-199]
- workspaces/x2a/plugins/x2a-backend/src/services/X2ADatabaseService/adversarialAgentOperations.ts[163-205]

### Implementation notes
Pick one:
1) **Pre-validate IDs** before calling `createProject` (e.g., add a `validateAdversarialAgentIdsExist(agentIds)` method that only queries and throws if missing).
2) **Wrap create + attachments in a single transaction** at the DB service layer, rolling back the project insert if attachments fail.
3) If transactions aren’t feasible here, catch attachment failure and explicitly delete the newly created project as compensation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Stale jobs block adversarial-run ✓ Resolved 🐞 Bug ☼ Reliability
Description
The adversarial-run endpoint rejects runs based only on DB job status without reconciling active
jobs against Kubernetes; stale “running/pending” DB rows can cause repeated 409 responses even when
no K8s job is actually active.
Code

workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[R526-534]

+      const existingJobs = await x2aDatabase.listJobsForModule({
+        projectId,
+        moduleId,
+      });
+      const activeAdversarialJob = existingJobs.find(
+        j =>
+          j.phase === adversarialPhase.value &&
+          JobStatus.from(j.status).isActive(),
+      );
Relevance

●● Moderate

Reconciling DB job state with Kubernetes adds complexity; may be deferred unless it’s a known issue.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new endpoint checks JobStatus.isActive() directly on DB rows, whereas the existing module run
handler reconciles active jobs against Kubernetes before enforcing the single-active-job constraint.

workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[524-541]
workspaces/x2a/plugins/x2a-backend/src/router/modules.ts[202-229]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`POST /projects/:projectId/adversarial-run` decides “already running” purely from DB status. If the callback never updated the DB (or the K8s job was deleted), users can be blocked from starting a new adversarial job.

## Issue Context
The existing module run endpoint reconciles active jobs via `reconcileJobStatus(...)` before returning 409.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[524-541]
- workspaces/x2a/plugins/x2a-backend/src/router/modules.ts[202-229]

### Implementation notes
- Filter to jobs matching the adversarial phase and active statuses, then call `reconcileJobStatus` (or a similar K8s check) before deciding to return 409.
- If reconciliation determines the job is not active, update the DB status accordingly and proceed to create a new job.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Migration filename has extra digits 📘 Rule violation ⚙ Maintainability
Description
A new migration file under plugins/x2a-backend/migrations/ does not follow the required
YYYYMMDDHH_description.ts (10-digit timestamp) naming pattern. This can break ordering assumptions
and tooling that depends on the standardized filename format.
Code

workspaces/x2a/plugins/x2a-backend/migrations/202607081000_create_adversarial_agents_table.ts[1]

+/*
Relevance

●●● Strong

Deterministic compliance fix: rename migration to required 10-digit timestamp pattern.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1877 requires migrations in plugins/x2a-backend/migrations/ to have exactly a
10-digit timestamp prefix. The newly added migration filename uses a 12-digit timestamp
(202607081000_...).

Rule 1877: Enforce timestamped migration filename pattern in plugins/x2a-backend/migrations
workspaces/x2a/plugins/x2a-backend/migrations/202607081000_create_adversarial_agents_table.ts[1-1]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The migration filename `202607081000_create_adversarial_agents_table.ts` does not match the required `^[0-9]{10}_[a-z0-9_]+\.ts$` pattern.

## Issue Context
Compliance requires migration filenames to be timestamped with exactly `YYYYMMDDHH` (10 digits) to keep ordering consistent.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/migrations/202607081000_create_adversarial_agents_table.ts[1-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Missing AdversarialAgentsPage tests 📘 Rule violation ▣ Testability
Description
New production TSX components were added without co-located *.test.tsx files in the same
directory, violating the required test naming/co-location convention. This makes the change harder
to validate and maintain over time.
Code

workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AdversarialAgentsPage.tsx[R23-28]

+export const AdversarialAgentsPage = () => {
+  const { t } = useTranslation();
+  const { allowed, loading } = usePermission({
+    permission: x2aAdminWritePermission,
+  });
+
Relevance

●●● Strong

Co-located test convention is typically enforced; adding a basic component test is straightforward.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1692 requires a co-located *.test.ts(x) file for each changed TS/TSX source file.
AdversarialAgentsPage.tsx was added, but there is no corresponding co-located
AdversarialAgentsPage.test.tsx in the same directory in this PR branch.

Rule 1692: Co-locate TypeScript test files with source using *.test.ts(x) suffix
workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AdversarialAgentsPage.tsx[23-28]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
TypeScript/TSX source files added in `.../AdversarialAgentsPage/` do not have co-located test files using the required `*.test.tsx` suffix.

## Issue Context
Compliance requires tests to live next to the source file and use the `.test.ts` / `.test.tsx` suffix.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AdversarialAgentsPage.tsx[1-69]
- workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AdversarialAgentsTable.tsx[1-99999]
- workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/AgentDialog.tsx[1-241]
- workspaces/x2a/plugins/x2a/src/components/AdversarialAgentsPage/DeleteAgentDialog.tsx[1-99999]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Endpoint accepts raw SCM token 📘 Rule violation ⛨ Security
Description
A new REST endpoint accepts a targetRepoAuth.token string from the request body, which is an
OAuth/PAT-like SCM secret being passed around directly rather than being resolved from the
scaffolder secrets mechanism. This increases the risk of token exposure via logs, client code, and
transport.
Code

workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[R481-484]

+      const adversarialRunSchema = z.object({
+        phase: z.enum(['analyze', 'migrate']),
+        moduleId: z.string().uuid(),
+        targetRepoAuth: z.object({ token: z.string() }).optional(),
Relevance

●●● Strong

Security/compliance: avoid accepting raw SCM tokens in request bodies; likely required to pass
review.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1959 disallows SCM OAuth tokens being passed/handled as raw strings outside the
scaffolder secrets mechanism. The new endpoint explicitly defines targetRepoAuth with a token
string in the request body schema, indicating the token is provided directly by the caller.

Rule 1959: Store OAuth tokens for SCM providers only in scaffolder secrets
workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[481-485]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new `/projects/:projectId/adversarial-run` endpoint schema accepts `targetRepoAuth: { token: string }` directly from the request body.

## Issue Context
Compliance requires SCM OAuth tokens to be obtained from scaffolder secrets (or an equivalent dedicated secrets abstraction), not passed as plain strings or sourced from ad-hoc locations.

## Fix Focus Areas
- workspaces/x2a/plugins/x2a-backend/src/router/projects.ts[481-546]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ Compliance rules (platform): 22 rules
✅ Cross-repo context
  Explored: repo: redhat-developer/rhdh-local (sha: a1776caa)
  Explored: repo: redhat-developer/rhdh (sha: 4c5a4e85)
  Explored: repo: redhat-developer/rhdh-operator (sha: 3119afc2)
  Not relevant to this PR: redhat-developer/rhdh-chart

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

@rhdh-qodo-merge rhdh-qodo-merge Bot added documentation Improvements or additions to documentation enhancement New feature or request Tests labels Aug 6, 2026
@sonarqubecloud

sonarqubecloud Bot commented Aug 6, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
5.9% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

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

Labels

documentation Improvements or additions to documentation enhancement New feature or request Tests workspace/x2a

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant