Implementation Plan: Report a Problem & Ticket Integration
Branch: 094-report-a-problem (on prebuild/fix/audit-chat-active-preserve) | Date: 2026-03-17 | Spec: spec.md
Input: Feature specification from /specs/094-report-a-problem/spec.md
Summary
Add a "Report a Problem" button in the AppHeader and a "Submit & Report Issue" combo button in the FeedbackButton dialog that create Jira or GitHub tickets via the existing A2A agents. Ticket creation streams progress logs to the user in real-time (same UX pattern as AI Enhance in SkillsBuilderEditor). Feature is opt-in via separate JIRA_TICKET_* and GITHUB_TICKET_* environment variables exposed through Helm chart values.
Technical Context
Language/Version: TypeScript (Next.js 16, React 19)
Primary Dependencies: Zustand, Radix UI Dialog, A2ASDKClient (@a2a-js/sdk), Framer Motion
Storage: N/A (stateless -- tickets created via A2A agents, no local persistence)
Testing: Jest + React Testing Library
Target Platform: Web browser (SPA)
Project Type: Web application (UI component of CAIPE)
Performance Goals: Streaming logs visible within 2s of submission
Constraints: Must not add ticket UI elements when providers are unconfigured; must reuse existing A2A infrastructure
Scale/Scope: ~6 new/modified source files, 1 config update, 1 Helm chart update
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
| Gate | Status | Notes |
|---|---|---|
| I. Specs as Source of Truth | PASS | Spec exists at docs/docs/specs/094-report-a-problem/spec.md |
| II. Agent-First Architecture | PASS | Tickets created via existing Jira/GitHub A2A agents through supervisor |
| III. MCP Server Pattern | PASS | Reuses existing Jira/GitHub MCP servers; no new MCP servers |
| V. A2A Protocol Compliance | PASS | Uses A2ASDKClient.sendMessageStream() for streaming ticket creation |
| VII. Test-First Quality Gates | PASS | Tests planned for all new components and config changes |
| IX. Security by Default | PASS | No secrets in source; env vars for config; auth required for ticket creation |
| X. Simplicity / YAGNI | PASS | Reuses existing A2ASDKClient, existing agent infrastructure; no new abstractions |
No violations. Complexity Tracking section not needed.
Project Structure
Documentation (this feature)
specs/094-report-a-problem/
├── spec.md # Feature specification (complete)
├── plan.md # This file
├── research.md # Phase 0 output
├── data-model.md # Phase 1 output
└── checklists/
└── requirements.md # Spec quality checklist
Source Code (repository root)
ui/src/
├── lib/
│ ├── config.ts # ADD: ticketConfig fields to Config interface
│ └── ticket-client.ts # NEW: thin wrapper around A2ASDKClient for ticket prompts
├── components/
│ ├── layout/
│ │ └── AppHeader.tsx # MODIFY: add "Report a Problem" button (conditional)
│ ├── chat/
│ │ └── FeedbackButton.tsx # MODIFY: add "Submit & Report Issue" button
│ └── ticket/
│ └── ReportProblemDialog.tsx # NEW: modal with input, streaming progress, result
├── components/__tests__/
│ └── ticket/
│ └── ReportProblemDialog.test.tsx # NEW: tests for report dialog
├── components/chat/__tests__/
│ └── FeedbackButton.test.tsx # MODIFY: add tests for combo button
└── components/layout/__tests__/
└── AppHeader.test.tsx # MODIFY: add tests for report button visibility
charts/ai-platform-engineering/charts/caipe-ui/
└── values.yaml # ADD: JIRA_TICKET_* and GITHUB_TICKET_* env vars
Structure Decision: Frontend-only feature. A new ReportProblemDialog component encapsulates the modal UX (input, streaming progress, result). A thin ticket-client.ts module constructs the A2A prompt for ticket creation. Config changes add ticket provider fields to the existing Config interface. No backend API routes needed -- tickets are created client-side via the existing A2ASDKClient streaming to the supervisor agent.
Phase 0: Research
No NEEDS CLARIFICATION items remain. All design decisions were resolved in the spec clarification session.
Key Findings
Decision 1: Ticket creation via A2A agents (not direct API calls)
- Rationale: The existing Jira and GitHub agents already know how to create tickets via their MCP servers. Reusing the supervisor -> agent pipeline means zero new backend code and consistent behavior with task-builder workflows.
- The
A2ASDKClientused in SkillsBuilderEditor's AI Enhance feature provides the exact streaming pattern needed. - Alternative rejected: Direct Jira/GitHub API calls from a Next.js API route -- would require duplicating auth, API logic, and error handling already solved by the agents.
Decision 2: Prompt-based ticket creation
- The A2A prompt sent to the supervisor will instruct it to route to the Jira or GitHub agent with a structured request.
- Prompt template:
"Create a {Jira issue in project OPENSD | GitHub issue in org/repo} with the following details: Summary: {user description}. Reporter: {user email}. Context URL: {chat/page URL}." - The agent handles field mapping, authentication, and API calls.
Decision 3: Single ReportProblemDialog component reused everywhere
- The same dialog component is used by: (a) AppHeader button, (b) FeedbackButton combo, (c) FeedbackButton "Report a Problem" link.
- Each caller provides context props (chat URL, feedback details) to customize the ticket body.
Decision 4: Config pattern follows existing conventions
- New fields added to the
Configinterface:jiraTicketEnabled,jiraTicketProject,githubTicketEnabled,githubTicketRepo. - Read from env vars
JIRA_TICKET_ENABLED,JIRA_TICKET_PROJECT,GITHUB_TICKET_ENABLED,GITHUB_TICKET_REPO. - A derived
ticketEnabledboolean (true if either provider is enabled) controls UI visibility.
Decision 5: Jira takes precedence when both are enabled
- In v1, no provider selection UI. If both are configured, the prompt targets Jira.
- Future: could add a dropdown to the dialog.
Phase 1: Design
Data Model
See data-model.md for entity definitions.
Contracts
No new external APIs. The feature uses the existing A2A protocol via A2ASDKClient.sendMessageStream(). The "contract" is the natural language prompt sent to the supervisor agent, which routes to the appropriate ticket-creation agent.
Component Design
ReportProblemDialog (new component)
Props:
open: boolean-- controlled dialog stateonOpenChange: (open: boolean) => void-- dialog state callbackchatUrl?: string-- current chat URL if on a chat pagefeedbackContext?: { reason: string; additionalFeedback?: string }-- optional feedback details for combo flow
Internal state:
description: string-- user input textstatus: "idle" | "submitting" | "success" | "error"-- workflow stateticketResult: { id: string; url: string; provider: string } | null-- result on successdebugLog: string[]-- streaming A2A event logshowDebug: boolean-- toggle for details panel
Behavior:
- Idle: text input + submit button with provider label
- Submitting: animated progress bar + "Show Details" toggle (streaming log)
- Success: ticket ID/link + "Done" button
- Error: error message + "Retry" / "Copy Description" buttons
ticket-client.ts (new module)
Exports createTicketViaAgent(params) which:
- Reads ticket config from
getConfig() - Constructs the A2A prompt with ticket details
- Creates an
A2ASDKClientinstance and callssendMessageStream() - Returns an async generator of
ParsedA2AEventfor the dialog to consume - Extracts the ticket ID/URL from the
final_resultartifact
Config additions to config.ts
Add to Config interface:
jiraTicketEnabled: boolean;
jiraTicketProject: string | null;
githubTicketEnabled: string | null;
githubTicketRepo: string | null;
Add derived getter:
ticketEnabled: boolean; // true if either jira or github ticket is enabled
ticketProvider: 'jira' | 'github' | null; // which provider to use (jira takes precedence)
Test Plan
ReportProblemDialog.test.tsx: renders input/submit in idle, shows streaming view on submit, displays result on success, handles errors, hides when no provider configured.FeedbackButton.test.tsx(additions): "Submit & Report Issue" button visible when ticket enabled, hidden when disabled, triggers both feedback submit and ticket creation.AppHeader.test.tsx(additions): "Report a Problem" button visible when ticket enabled, hidden when disabled, opens dialog on click.config.tstests: verifyjiraTicketEnabled,githubTicketEnabled,ticketEnabledderive correctly from env vars.