{
  "steward": "unit-test-steward",
  "project": "Azure-AI-RAG-CSharp-Semantic-Kernel-Functions",
  "runDate": "2026-03-21",
  "runId": "2026-03-21T00-00-00",
  "findings": [
    {
      "id": "TEST-COVER-001",
      "title": "No C# test project exists — zero test coverage across the entire solution",
      "severity": "critical",
      "category": "COVER",
      "file": "ChatAPI.sln",
      "description": "The solution contains a single C# project (ChatAPI.csproj) with no test project, no test framework references, and no test files. 100% of production C# code is completely untested.",
      "recommendation": "Create a ChatAPI.Tests xUnit project. Add it to the solution. Reference ChatAPI and install xunit, xunit.runner.visualstudio, Moq (or NSubstitute), and Microsoft.AspNetCore.Mvc.Testing for controller integration tests.",
      "status": "open"
    },
    {
      "id": "TEST-COVER-002",
      "title": "Controllers (ChatController, SessionController) have zero test coverage",
      "severity": "notable",
      "category": "COVER",
      "file": "src/ChatAPI/Controllers/ChatController.cs",
      "description": "ChatController.Post has no null guard on the request parameter and no tests verify the response shape, error paths, or service exception propagation. SessionController.GetSession has no tests verifying the session_id field format.",
      "recommendation": "Use Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory or direct ControllerBase unit tests with mocked ChatService. Cover: null request body, valid request returns serialized response, service exception propagates, session_id is a 32-char hex string.",
      "status": "open"
    },
    {
      "id": "TEST-COVER-003",
      "title": "ChatService has zero test coverage including untested branching logic",
      "severity": "notable",
      "category": "COVER",
      "file": "src/ChatAPI/Services/ChatService.cs",
      "line": 34,
      "description": "ChatService.GetResponseAsync contains a branch on chatHistory.Count == 1 to initialize history from Cosmos. This conditional and all downstream behavior (chat completion call, response serialization) are completely untested.",
      "recommendation": "Add ChatServiceTests covering: history initialization triggered on first call (count==1), initialization skipped on subsequent calls, response serialized as { resp } JSON object, and exception propagation from the chat completion service.",
      "status": "open"
    },
    {
      "id": "TEST-ISOL-001",
      "title": "Data classes depend on concrete Azure SDK types with no interface seam for unit testing",
      "severity": "notable",
      "category": "ISOL",
      "file": "src/ChatAPI/Data/ProductData.cs",
      "description": "ProductData, ChatHistoryData, and AISearchData accept CosmosClient and SearchClient directly. These concrete Azure SDK classes have no publicly usable mock-friendly interfaces, preventing unit isolation of ChatService and plugins without live Azure infrastructure.",
      "recommendation": "Introduce narrow interfaces IProductData, IChatHistoryData, and IAISearchData exposing only the methods called by consumers. Register concrete implementations in Program.cs. This creates a mockable seam for unit tests without requiring a live Azure environment.",
      "status": "open"
    },
    {
      "id": "TEST-COVER-004",
      "title": "Semantic Kernel plugins (AISearchDataPlugin, ProductDataPlugin) have zero test coverage",
      "severity": "minor",
      "category": "COVER",
      "file": "src/ChatAPI/Plugins/AISearchDataPlugin.cs",
      "description": "Both Kernel plugins are invoked by the AI model at runtime. Their exception-catch-and-rethrow behavior, embedding pipeline, and JSON serialization are entirely untested.",
      "recommendation": "After introducing interface abstractions for the data layer (see TEST-ISOL-001), add plugin tests for: successful retrieval and serialization, exception propagation, and empty result set handling.",
      "status": "open"
    },
    {
      "id": "TEST-QUAL-001",
      "title": "ChatService has 6 constructor dependencies — exceeds the over-mocking threshold for unit tests",
      "severity": "minor",
      "category": "QUAL",
      "file": "src/ChatAPI/Services/ChatService.cs",
      "line": 15,
      "description": "ChatService accepts Kernel, ITextEmbeddingGenerationService, ProductData, ChatHistory, ChatHistoryData, and AISearchData. Unit tests would require mocking 5+ dependencies, which exceeds the 3-dependency threshold and signals mixed responsibilities.",
      "recommendation": "Consider splitting ChatService into a focused orchestration class and a history management service, reducing the constructor parameter count to 3-4 per class. This improves cohesion and makes unit tests simpler to write.",
      "status": "open"
    },
    {
      "id": "TEST-COVER-005",
      "title": "GenerateProductInfo.PopulateCosmosAsync silently swallows all exceptions — untested",
      "severity": "info",
      "category": "COVER",
      "file": "src/ChatAPI/Data/sample_data/products/GenerateProductInfo.cs",
      "line": 84,
      "description": "The data seeding method catches all exceptions and only logs them, allowing the application to start silently with an empty database. A test would immediately reveal this behavior and expose the risk of undetected startup data loss.",
      "recommendation": "Add a test verifying the exception is logged. Consider propagating critical seeding failures instead of silently swallowing them so startup probes can detect the failure.",
      "status": "open"
    }
  ],
  "summary": {
    "critical": 1,
    "notable": 3,
    "minor": 2,
    "info": 1,
    "total": 7
  }
}
