# Project export: Verdict AI

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: An explainable AI decision support system that reviews evidence, explains its reasoning, highlights uncertainty, and helps humans make better decisions with GPT-5.6
- Devpost: https://devpost.com/software/verdict-ai-5wj1ft
- GitHub: https://github.com/aadityakulkarni12-cell/Verdict-AI
- Demo: https://verdict-ai-seven.vercel.app/
- Video: https://www.youtube.com/embed/_A59Dwg_X_c?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Aaditya Hemant Kulkarni (8 commits)

## Devpost submission (written by the team)

### Inspiration

As AI systems become more capable, I believe they'll play a much larger role in helping people make important decisions. Whether it's software deployments, connected vehicles, manufacturing, healthcare, or finance, the amount of data available is growing much faster than a person can manually analyze. That led me to a simple question: How can AI help people make better decisions without becoming a black box? Verdict AI was built to explore that future. Instead of replacing human judgment, it reviews structured evidence, explains its reasoning, highlights uncertainty, and recommends the next best action while keeping a human in control of the final decision.

### What it does

Verdict AI is an explainable AI decision support system. It collects evidence from multiple sources, validates it, sends structured information to GPT-5.6 for reasoning, calculates confidence, and returns a transparent recommendation together with its assumptions and missing evidence. The same reasoning pipeline can be applied across multiple domains. The current demonstration includes: Software deployment investigations Connected vehicle investigations Manufacturing anomaly investigations The goal is not anomaly detection itself, but transparent AI-assisted decision making.

### How we built it

Verdict-AI consists of a React + TypeScript frontend and a FastAPI backend connected through the OpenAI Responses API. The backend normalizes evidence, performs deterministic validation, invokes GPT-5.6 to generate structured reasoning, validates the response, calculates confidence, and produces recommendations. If AI is unavailable, the system automatically falls back to a deterministic decision engine to ensure reliability. Codex played a significant role throughout development by helping accelerate implementation, debugging, refactoring, documentation, and repository organization.

### Challenges we ran into

The biggest challenge wasn't implementing GPT-5.6, it was turning an idea into a product. I didn't want to build another AI demo that simply generated answers. I wanted Verdict AI to feel like a real decision-support system with a clear user experience, explainable reasoning, confidence scoring, and human oversight. Finding the right balance between automation and transparency took the most iteration. I wanted every recommendation to remain connected to the evidence that produced it, allowing users to understand not only the conclusion, but also its assumptions, uncertainty, and limitations.

### Accomplishments we're proud of

I'm proud that Verdict AI demonstrates a complete end-to-end workflow rather than just an AI prompt. The project combines a production-style frontend, a FastAPI backend, GPT-5.6 reasoning through the OpenAI Responses API, deterministic fallback behavior, explainable recommendations, confidence scoring, and a polished user experience into a single application. Most importantly, it reinforces the idea that AI should help people make better decisions, not replace them.

### What we learned

Building Verdict-AI reinforced that the most valuable AI products aren't necessarily those that automate everything. People are more likely to trust AI when it explains its reasoning, communicates uncertainty, and keeps humans involved in important decisions. I also gained a much deeper understanding of designing AI systems that combine deterministic software engineering with large language models in a reliable and transparent way

### What's next

Verdict AI is currently a proof of concept, but I see it evolving into a production-ready decision support platform. The next step is to pilot this approach within real enterprise workflows, where AI can assist teams in reviewing evidence, explaining its reasoning, and recommending the next best action while keeping humans responsible for the final decision. I also want to expand the platform beyond the current software, automotive, and manufacturing scenarios by integrating live data sources, richer evidence pipelines, role-based collaboration, audit trails, and feedback loops that continuously improve recommendations over time. Ultimately, my goal is to build AI systems that people can trust, not because they always have the right answer, but because they clearly explain how they reached it and make it easy for humans to make informed decisions.

## README (from the GitHub repository)

# Verdict-AI

Verdict-AI helps people review structured evidence, understand uncertainty, and decide what to do next. It combines model-based reasoning with deterministic safeguards and keeps the final decision in human hands.

## Live Resources

| Resource | Link |
| --- | --- |
| **Live Application** | [verdict-ai-seven.vercel.app](https://verdict-ai-seven.vercel.app) |
| **Demo Video** | [Watch on YouTube](https://youtu.be/_A59Dwg_X_c) |
| **GitHub Repository** | [aadityakulkarni12-cell/Verdict-AI](https://github.com/aadityakulkarni12-cell/Verdict-AI) |

## Why Verdict-AI exists

Evidence-based decisions are rarely difficult because facts are completely absent. They are difficult because the available facts can conflict, carry different levels of importance, leave critical gaps, or support more than one reasonable interpretation. A recommendation without visible reasoning does little to help someone judge those tradeoffs.

Verdict-AI treats the process as an investigation. It normalizes an evidence package, evaluates individual findings, highlights contradictions and uncertainty, and recommends a concrete next action. The result includes the reasoning behind the recommendation so a person can inspect it rather than simply accept a model output.

GPT-5.6 is used for the part of the process that requires synthesis: comparing multiple findings, distinguishing uncertainty from contradiction, and explaining how the evidence supports a judgment. Its output is constrained to a typed contract and sits inside a broader pipeline with deterministic evaluation and fallback behavior.

## Design principles

- **Live GPT-5.6 reasoning:** each investigation sends structured evidence through the backend decision pipeline. When GPT-5.6 produces the judgment, the interface identifies the source as **AI Reasoning Engine (GPT-5.6)**.
- **Deterministic fallback:** if the API key is not configured, the provider is unavailable, or the model response fails validation, the investigation completes with a labeled, rule-based fallback instead of failing silently.
- **Human in the loop:** Verdict-AI explains evidence, confidence, uncertainty, and a recommended next action. A person remains responsible for the final decision.

## Built with OpenAI

### GPT-5.6 and the Responses API

GPT-5.6 is the reasoning engine behind Verdict-AI's AI Judge. The backend sends normalized evidence, an evaluation plan, and deterministic findings to the OpenAI Responses API. Pydantic Structured Outputs constrain the result to the application's judgment contract, including the verdict, rationale, confidence, uncertainty notes, and cited evidence. The API key and model call remain backend-only.

### Codex

Codex was used throughout development to accelerate implementation, debugging, testing, documentation, and repository refinement. Its suggestions and changes were reviewed as part of the normal engineering process; product direction and final decisions remained human-owned.

## Judge Quick Start

The fastest path is the [live application](https://verdict-ai-seven.vercel.app). To run it locally, clone the repository and open two PowerShell terminals:

```powershell
git clone https://github.com/aadityakulkarni12-cell/Verdict-AI.git
cd Verdict-AI
```

**1. Start the backend**

```powershell
cd backend
Copy-Item .env.example .env
python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install -r requirements-dev.txt
uvicorn app.main:app --reload
```

The backend starts at `http://localhost:8000`. Leaving `OPENAI_API_KEY` empty runs the deterministic fallback. For live GPT-5.6 reasoning, add your key to `backend/.env`:

```dotenv
OPENAI_API_KEY=your_openai_api_key
OPENAI_MODEL=gpt-5.6
VERDICT_AI_JUDGE_ENABLED=true
```

Restart the backend after editing `.env`.

**2. Start the frontend in a second terminal**

```powershell
cd frontend
Copy-Item .env.example .env.local
npm ci
npm run dev
```

Open `http://localhost:5173`, select a scenario, and click **Investigate**. The result clearly labels whether GPT-5.6 or the deterministic fallback produced the judgment.

## Prerequisites

- Python 3.11 or newer
- Node.js 20 or newer
- npm (included with Node.js)
- Git
- An OpenAI Platform account and API key for live GPT-5.6 reasoning; the project still runs in deterministic mode without a key

### Get an OpenAI API key

1. Sign in to the [OpenAI Platform](https://platform.openai.com/).
2. Open the [API keys page](https://platform.openai.com/api-keys) and create a secret key.
3. Copy `backend/.env.example` to `backend/.env` and set `OPENAI_API_KEY` there.

Keep the key private. Never commit `backend/.env` or place the key in a `VITE_*` frontend variable, because Vite variables are included in browser assets. API usage may require billing to be configured on the OpenAI Platform account.

## How the decision flow works

1. The user selects or supplies a structured evidence package.
2. The deterministic pipeline normalizes the evidence, creates an evaluation plan, and produces findings and confidence diagnostics.
3. GPT-5.6 reviews that context and returns a validated structured judgment through the Responses API.
4. If live AI is unavailable or invalid, the deterministic Judge returns a labeled fallback judgment.
5. Verdict-AI presents the reasoning, uncertainty, recommendation, and next action for human review.

The decision pipeline is documented in [`DECISION_ENGINE.md`](DECISION_ENGINE.md), AI behavior in [`AI_JUDGE.md`](AI_JUDGE.md), and system boundaries in [`ARCHITECTURE.md`](ARCHITECTURE.md).

## Project structure

```text
Verdict-AI/
|-- frontend/   # React + TypeScript + Vite experience
|-- backend/    # FastAPI decision pipeline and OpenAI integration
|-- AI_JUDGE.md
|-- ARCHITECTURE.md
|-- DECISION_ENGINE.md
`-- README.md
```

## Useful local URLs

- Frontend: `http://localhost:5173`
- API: `http://localhost:8000`
- Health check: `http://localhost:8000/health`
- Interactive API docs: `http://localhost:8000/docs`

## Deploy to Vercel

Verdict-AI deploys from the same GitHub repository as two Vercel projects: one rooted at `backend/` and one at `frontend/`.

### 1. Deploy the backend

Import the repository in Vercel and configure:

- **Root Directory:** `backend`
- **Framework/build settings:** use Vercel's detected defaults
- **Environment variables:**

| Name | Value | Required |
| --- | --- | --- |
| `OPENAI_API_KEY` | Your OpenAI project key | No; omit for deterministic mode |
| `OPENAI_MODEL` | `gpt-5.6` | No; this is the configured default |
| `VERDICT_AI_JUDGE_ENABLED` | `true` | Yes |
| `VERDICT_ENVIRONMENT` | `production` | Recommended |
| `VERDICT_CORS_ORIGINS` | Frontend URL or planned domain | Yes |

[`backend/index.py`](backend/index.py) exposes the FastAPI application to Vercel's Python runtime. After deployment, verify the service using its assigned URL:

```powershell
Invoke-RestMethod "https://YOUR-BACKEND.vercel.app/health"
```

Expected response:

```json
{"status":"ok","service":"verdict-ai-api","version":"0.1.0"}
```

### 2. Deploy the frontend

Import the same repository as a second Vercel project and configure:

- **Root Directory:** `frontend`
- **Framework Preset:** Vite
- **Environment variable:**

```text
VITE_API_BASE_URL=https://YOUR-BACKEND.vercel.app
```

[`frontend/vercel.json`](frontend/vercel.json) defines the production output and preserves React routes during direct navigation.

### 3. Finalize CORS and validate

Set `VERDICT_CORS_ORIGINS` in the backend project to the exact frontend URL without a trailing slash, then redeploy the backend:

```text
VERDICT_CORS_ORIGINS=https://YOUR-FRONTEND.vercel.app
```

Use comma-separated values for multiple trusted domains. Do not use `*` in production. Confirm the backend health check, open the frontend, and directly visit `/evidence`, `/decisions`, and `/settings` to verify client-side routing.

Once both Vercel projects are connected to GitHub, pushes create deployments automatically. The GitHub Actions workflow runs bac

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 64 recognized source files, 146 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Vercel (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (75 of 75)

```
.github/workflows/ci.yml
.gitignore
AI_JUDGE.md
ARCHITECTURE.md
backend/.env.example
backend/app/__init__.py
backend/app/config/__init__.py
backend/app/config/settings.py
backend/app/decisions/__init__.py
backend/app/decisions/ai_judge.py
backend/app/decisions/confidence.py
backend/app/decisions/judge.py
backend/app/decisions/models.py
backend/app/decisions/recommendation.py
backend/app/evidence/__init__.py
backend/app/evidence/models.py
backend/app/evidence/normalizer.py
backend/app/main.py
backend/app/models/__init__.py
backend/app/models/common.py
backend/app/orchestrator/__init__.py
backend/app/orchestrator/engine.py
backend/app/orchestrator/evaluators.py
backend/app/orchestrator/interfaces.py
backend/app/orchestrator/planner.py
backend/app/routers/__init__.py
backend/app/routers/decisions.py
backend/app/routers/evaluation.py
backend/app/routers/health.py
backend/app/sample_data/__init__.py
backend/app/sample_data/decisions.py
backend/app/services/__init__.py
backend/app/services/decision_service.py
backend/index.py
backend/pytest.ini
backend/requirements-dev.txt
backend/requirements.txt
backend/tests/conftest.py
backend/tests/test_ai_judge.py
backend/tests/test_api.py
backend/tests/test_decision_engine.py
DECISION_ENGINE.md
frontend/.env.example
frontend/index.html
frontend/package.json
frontend/postcss.config.js
frontend/src/App.tsx
frontend/src/components/investigation/DecisionOverview.tsx
frontend/src/components/investigation/HowAIDecides.tsx
frontend/src/components/investigation/InvestigationSequence.tsx
frontend/src/components/investigation/InvestigationTimeline.tsx
frontend/src/components/investigation/ScenarioPicker.tsx
frontend/src/components/layout/AppLayout.tsx
frontend/src/components/layout/Header.tsx
frontend/src/components/layout/Sidebar.tsx
frontend/src/components/PageHeading.tsx
frontend/src/components/StatusBadge.tsx
frontend/src/lib/api.ts
frontend/src/main.tsx
frontend/src/pages/DecisionsPage.tsx
frontend/src/pages/EvidenceInputPage.tsx
frontend/src/pages/SettingsPage.tsx
frontend/src/sample_data/decisions.ts
frontend/src/sample_data/scenarios.ts
frontend/src/styles/index.css
frontend/src/types/decision.ts
frontend/src/types/scenario.ts
frontend/src/vite-env.d.ts
frontend/tailwind.config.js
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vercel.json
frontend/vite.config.ts
README.md
```

### Dependencies

- backend/requirements.txt: fastapi@==0.115.12, openai@==2.45.0, pydantic-settings@==2.9.1, uvicorn[standard]@==0.34.2
- frontend/package.json: @types/react@18.3.18, @types/react-dom@18.3.5, @vitejs/plugin-react@4.3.4, autoprefixer@10.4.20, lucide-react@0.468.0, postcss@8.5.19, react@18.3.1, react-dom@18.3.1, react-router-dom@7.18.1, tailwindcss@3.4.17, typescript@5.7.2, vite@6.4.3

### Recent commits (newest first)

- docs: improve Verdict-AI project README
- Update README.md
- Update README.md
- Connect frontend to live AI judge
- Add progressive AI investigation experience
- Reframe frontend as AI investigation workflow
- Fix Vercel backend dependency detection
- Prepare Verdict-AI for Vercel deployment

## Key source files (fetched from GitHub, selected and truncated for size)

### AI_JUDGE.md

```markdown
# GPT-5.6 AI Judge

Verdict-AI can use GPT-5.6 as the Judge while preserving the existing normalization, planning, evaluator, confidence, and recommendation stages. The integration uses the OpenAI Responses API with Pydantic Structured Outputs and never sends credentials or prompts to the frontend.

Official references:

- [GPT-5.6 Sol model](https://developers.openai.com/api/docs/models/gpt-5.6-sol)
- [Structured model outputs](https://developers.openai.com/api/docs/guides/structured-outputs)
- [Official Python SDK](https://github.com/openai/openai-python)

## Configuration

Create `backend/.env` from `backend/.env.example` and set:

```dotenv
VERDICT_AI_JUDGE_ENABLED=true
OPENAI_API_KEY=your-backend-only-key
OPENAI_MODEL=gpt-5.6
VERDICT_OPENAI_TIMEOUT_SECONDS=20
VERDICT_OPENAI_MAX_RETRIES=1
```

`OPENAI_API_KEY` and `OPENAI_MODEL` use the standard OpenAI environment names. `VERDICT_OPENAI_API_KEY` and `VERDICT_OPENAI_MODEL` are also accepted for deployments that namespace every application setting.

The API key is represented as Pydantic `SecretStr`, is passed directly to the backend SDK client, and is never included in a decision model. An empty or absent key means the AI provider is unconfigured and triggers deterministic fallback.

## Structured contract

The model must satisfy exactly this logical schema:

```json
{
  "verdict": "proceed | review | stop",
  "confidence": 0,
  "reasoning": ["concise decision reason"],
  "recommendation": "one concrete next action",
  "assumptions": ["explicit assumption"],
  "missing_evidence": ["evidence that would improve the decision"]
}
```

Confidence is constrained to the inclusive range 0-100. Extra fields are forbidden. Reasoning must contain at least one entry. The provider uses `client.responses.parse(..., text_format=AIJudgeOutput)`, then validates `output_parsed` again at the Verdict-AI boundary.

## Data sent to the Judge

Only the following backend models are serialized into the user payload:

- normalized evidence;
- the planner's evaluator IDs and rationale;
- structured evaluator findings.

The system instruction tells the model to treat every string in the case payload as untrusted data. Evaluator input cannot become a new system instruction.

## Pipeline integration

`ResilientAIJudge` implements the pipeline's `Judge` protocol. `OpenAIResponsesJudgeProvider` implements a smaller provider protocol and owns the OpenAI-specific API call. This split means another model provider can replace the OpenAI adapter without changing the orchestrator.

Validated AI output is adapted into the existing `Judgment` model:

- `verdict` becomes the judgment disposition;
- `reasoning` becomes the judgment rationale;
- AI confidence is converted from 0-100 to the public decision score of 0-1;
- the AI recommendation passes through the existing Recommendation Engine, which adds pipeline priority;
- assumptions and missing evidence remain explicit judgment fields;
- model and source identify how the judgment wa
[truncated — 1006 more characters]
```

### ARCHITECTURE.md

```markdown
# Verdict-AI Architecture

## Scope of this iteration

This repository is an original foundation for a decision engine. It defines boundaries, data contracts, an optional OpenAI-backed Judge, deterministic fallback behavior, and a dashboard shell. It intentionally does not implement production policy rules, persistence, authentication, or customer integrations.

## Repository boundary

The project uses a small monorepo with independent `backend` and `frontend` applications. Keeping them together makes local setup and coordinated contract changes simple at this stage. Keeping their dependencies and build tools separate allows either application to be deployed or replaced independently later.

## Backend decisions

### FastAPI application factory surface

`app/main.py` is deliberately small: it creates the application, applies cross-origin configuration, and mounts routers. Business behavior does not accumulate at the entry point, which keeps startup predictable and tests easy to target.

### Thin routers

The `routers` package owns HTTP concerns: paths, response types, status codes, and error translation. Routers delegate evaluation and retrieval to a service instead of owning workflow logic. That keeps domain behavior reusable outside HTTP, for example from a future queue worker.

### Application service

`DecisionService` is the boundary between transport and decision workflow. It currently manages an in-memory store and calls the deterministic orchestrator. A database repository can replace the store later without changing endpoint contracts.

### Domain-oriented packages

- `evidence` owns evidence input contracts.
- `decisions` owns decision output and reasoning contracts.
- `orchestrator` coordinates evaluation stages and will eventually sequence validation, model calls, policies, and explanations.
- `models` contains API models shared across domains, currently the health response.
- `sample_data` contains visibly fictional seed records so examples cannot be confused with production data.

These boundaries make dependencies flow toward explicit domain contracts. Deterministic engine stages are isolated behind protocols and constructor injection, so one implementation can be replaced without changing its consumers. See [`DECISION_ENGINE.md`](DECISION_ENGINE.md) for the full pipeline design.

### Typed contracts and validation

Pydantic models constrain lengths, confidence ranges, statuses, and required evidence. Validation happens before orchestration, giving future engine stages clean input and clients consistent errors.

### Centralized configuration

`pydantic-settings` loads `VERDICT_`-prefixed environment variables and provides typed defaults. Configuration remains outside code while local startup works without a secret-bearing `.env` file. `.env.example` documents the supported surface.

### In-memory mock storage

An in-memory dictionary is sufficient for demonstrating `POST /evaluate` followed by `GET /decision/{id}`. It is intentiona
[truncated — 2544 more characters]
```

### backend/requirements.txt

```
fastapi==0.115.12
openai==2.45.0
pydantic-settings==2.9.1
uvicorn[standard]==0.34.2

```

### frontend/package.json

```
{
  "name": "verdict-ai-frontend",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "@vitejs/plugin-react": "4.3.4",
    "lucide-react": "0.468.0",
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "react-router-dom": "7.18.1"
  },
  "devDependencies": {
    "@types/react": "18.3.18",
    "@types/react-dom": "18.3.5",
    "autoprefixer": "10.4.20",
    "postcss": "8.5.19",
    "tailwindcss": "3.4.17",
    "typescript": "5.7.2",
    "vite": "6.4.3"
  }
}

```

### backend/index.py

```python
"""Vercel entrypoint for the existing FastAPI application."""

from app.main import app

__all__ = ["app"]

```

### frontend/src/main.tsx

```typescript
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'

import App from './App'
import './styles/index.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
)


```

### backend/app/main.py

```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.config.settings import get_settings
from app.routers import api_router

settings = get_settings()

app = FastAPI(
    title=settings.app_name,
    version="0.1.0",
    description="Original scaffold for an explainable decision engine.",
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins,
    allow_credentials=False,
    allow_methods=["GET", "POST", "OPTIONS"],
    allow_headers=["Content-Type", "Accept"],
)
app.include_router(api_router, prefix=settings.api_prefix)

```

### frontend/src/App.tsx

```typescript
import { Navigate, Route, Routes } from 'react-router-dom'

import { AppLayout } from './components/layout/AppLayout'
import { DecisionsPage } from './pages/DecisionsPage'
import { EvidenceInputPage } from './pages/EvidenceInputPage'
import { SettingsPage } from './pages/SettingsPage'

export default function App() {
  return (
    <Routes>
      <Route element={<AppLayout />}>
        <Route index element={<Navigate replace to="/evidence" />} />
        <Route path="/evidence" element={<EvidenceInputPage />} />
        <Route path="/decisions" element={<DecisionsPage />} />
        <Route path="/settings" element={<SettingsPage />} />
      </Route>
    </Routes>
  )
}


```

### frontend/postcss.config.js

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}


```

### frontend/vite.config.ts

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 5173,
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },
})


```

[55 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]