{
  "steward": "react-ux-components-steward",
  "project": "Azure-AI-RAG-CSharp-Semantic-Kernel-Functions",
  "runDate": "2026-03-22",
  "runId": "2026-03-22T00-00-00",
  "findings": [
    {
      "id": "RCOMP-A11Y-001",
      "title": "<img> missing alt attribute",
      "severity": "critical",
      "category": "A11Y",
      "file": "src/Main.js",
      "line": 30,
      "description": "The header <img> element has no alt attribute. Screen readers will announce the filename or URL instead of a description. Fails WCAG 2.1 SC 1.1.1 (Non-text Content).",
      "recommendation": "Add alt=\"Azure cloud infrastructure illustration\" (or alt=\"\" if purely decorative).",
      "status": "open"
    },
    {
      "id": "RCOMP-A11Y-002",
      "title": "Chat message list has no aria-live region or role=\"log\"",
      "severity": "notable",
      "category": "A11Y",
      "file": "src/SupportAgent/ChatLayout.js",
      "description": "New messages appended by the assistant are not announced to screen reader users. The scrollable message list has no role=\"log\" or aria-live=\"polite\" attribute.",
      "recommendation": "Wrap the scrollable message container with <div role=\"log\" aria-live=\"polite\" aria-label=\"Chat messages\">.",
      "status": "open"
    },
    {
      "id": "RCOMP-A11Y-003",
      "title": "Placeholder href=\"#\" links with no navigable destination",
      "severity": "notable",
      "category": "A11Y",
      "file": "src/AzureServiceCards.js",
      "description": "All three 'View all services' Link components use href=\"#\". Screen readers announce them as navigable links but activating them does nothing. Violates WCAG 2.4.4 (Link Purpose).",
      "recommendation": "Replace href=\"#\" with real destination URLs, or render as non-interactive Typography if they are future placeholders.",
      "status": "open"
    },
    {
      "id": "RCOMP-THEME-001",
      "title": "No MUI ThemeProvider — all colors hardcoded as literals",
      "severity": "notable",
      "category": "THEME",
      "file": "src/index.js",
      "description": "No createTheme or ThemeProvider is configured. All brand colors (#107C10, #0078D4, #E7FAEC, #E7F4FA, #EBEBEB) are hardcoded hex strings in sx props and inline state values across multiple files. Any brand or accessibility contrast update requires manual find-and-replace.",
      "recommendation": "Introduce createTheme with palette.primary (#0078D4) and palette.success (#107C10), wrap the app in ThemeProvider, and replace all hardcoded hex strings in sx props with theme palette references.",
      "status": "open"
    },
    {
      "id": "RCOMP-DESIGN-001",
      "title": "Class component with unused state and naming collision",
      "severity": "notable",
      "category": "DESIGN",
      "file": "src/Main.js",
      "line": 8,
      "description": "Main.js exports a class named App (colliding with the App export in App.js) and declares this.state = { question: '', searchResults: [] } that is never read or updated. The rest of the codebase uses function components exclusively.",
      "recommendation": "Convert Main.js to a functional component named Main. Remove the unused question and searchResults state.",
      "status": "open"
    },
    {
      "id": "RCOMP-DESIGN-002",
      "title": "Dead import: Dialog/DialogContent imported but never rendered",
      "severity": "notable",
      "category": "DESIGN",
      "file": "src/SupportAgent/Agent.js",
      "line": 4,
      "description": "Dialog and DialogContent are imported from @mui/material but are never used in the component's render output. This suggests incomplete or abandoned functionality and adds unnecessary bundle weight.",
      "recommendation": "Remove the unused Dialog and DialogContent imports from Agent.js.",
      "status": "open"
    },
    {
      "id": "RCOMP-DESIGN-003",
      "title": "sx height value '355' is a string with no CSS unit",
      "severity": "notable",
      "category": "DESIGN",
      "file": "src/SupportAgent/Agent.js",
      "line": 63,
      "description": "The Box wrapping ChatLayout uses sx={{ height: '355' }}. The string '355' has no CSS unit; browsers ignore it for block elements, so the height constraint is silently not applied.",
      "recommendation": "Change to sx={{ height: '355px' }}.",
      "status": "open"
    },
    {
      "id": "RCOMP-DUP-001",
      "title": "Three near-identical card JSX blocks with no extracted sub-component",
      "severity": "minor",
      "category": "DUP",
      "file": "src/AzureServiceCards.js",
      "description": "AzureServiceCards.js contains three copy-pasted Grid item > Paper > Typography > Link blocks that differ only in text content. All sx props are duplicated verbatim three times.",
      "recommendation": "Extract a ServiceCard functional component accepting title and linkLabel props. Replace the three JSX blocks with a data array mapped to ServiceCard instances.",
      "status": "open"
    },
    {
      "id": "RCOMP-DESIGN-004",
      "title": "ChatLayout props not destructured; opaque function signature",
      "severity": "minor",
      "category": "DESIGN",
      "file": "src/SupportAgent/ChatLayout.js",
      "line": 6,
      "description": "The function is declared as function ChatLayout(messages) where messages is the entire props object, then accessed as messages.messages. The idiomatic pattern is function ChatLayout({ messages }), which makes the prop contract explicit.",
      "recommendation": "Change function ChatLayout(messages) to function ChatLayout({ messages }).",
      "status": "open"
    },
    {
      "id": "RCOMP-DESIGN-005",
      "title": "Duplicate key and mutable i++ mutation inside JSX map",
      "severity": "minor",
      "category": "DESIGN",
      "file": "src/SupportAgent/ChatLayout.js",
      "line": 9,
      "description": "The map callback uses key={i} on the outer div.bubbleContainer and key={i++} on the inner Box, mutating i during render. Only the outermost repeated element needs a key; mutation inside JSX is a React anti-pattern.",
      "recommendation": "Use the map-provided index or a stable message ID as key only on the outermost div.bubbleContainer. Remove key from the inner Box and eliminate the i++ mutation.",
      "status": "open"
    },
    {
      "id": "RCOMP-STYLE-001",
      "title": "App.css contains only unused CRA boilerplate styles",
      "severity": "minor",
      "category": "STYLE",
      "file": "src/App.css",
      "description": "App.css contains .App-logo, .App-header, .App-link, and the App-logo-spin animation from the CRA scaffold. None of these classes are referenced in any component. This is dead CSS.",
      "recommendation": "Delete the unused boilerplate rules from App.css, or delete the file if no styles are needed.",
      "status": "open"
    },
    {
      "id": "RCOMP-STYLE-002",
      "title": "Float-based bubble alignment inside MUI flexbox Stack",
      "severity": "minor",
      "category": "STYLE",
      "file": "src/SupportAgent/ChatLayout.js",
      "line": 14,
      "description": "Chat bubbles are aligned left/right using sx={{ float: obj.direction }} inside a MUI Stack (flexbox container). CSS float inside flexbox is unreliable and non-idiomatic. Flexbox items ignore float.",
      "recommendation": "Replace float with alignSelf: obj.direction === 'right' ? 'flex-end' : 'flex-start' on the bubble container, with the Stack set to flexDirection: 'column'.",
      "status": "open"
    },
    {
      "id": "RCOMP-INFO-001",
      "title": "MUI v5 used consistently — no competing UI libraries present",
      "severity": "info",
      "category": "INFO",
      "description": "All interactive and structural components use MUI v5 exclusively. There is no mixing with Ant Design, Bootstrap, or other component libraries.",
      "status": "open"
    },
    {
      "id": "RCOMP-INFO-002",
      "title": "Component decomposition is appropriate for the project scale",
      "severity": "info",
      "category": "INFO",
      "description": "The application is correctly decomposed into focused components: AzureFreeAccount (promotional banner), AzureServiceCards (marketing section), Agent (chat logic and API calls), ChatLayout (message rendering). Separation of concerns between data-fetching (Agent) and rendering (ChatLayout) is good.",
      "status": "open"
    }
  ],
  "summary": {
    "critical": 1,
    "notable": 6,
    "minor": 5,
    "info": 2,
    "total": 14
  }
}
