# Project export: Incident Commander 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: Turn production alerts into evidence-backed, human-approved resolution packages with cited diagnosis, bounded patches, deterministic verification, and auditable postmortems.
- Devpost: https://devpost.com/software/incident-commander-ai
- GitHub: https://github.com/AtchayamG/ai-incident-commander
- Video: https://www.youtube.com/embed/CCqM-leu_8Y?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Atchayam G (13 commits)

## Devpost submission (written by the team)

### Inspiration

Small engineering teams rarely have a dedicated incident commander on every shift. When production starts failing, one senior engineer becomes the integration layer across alerts, logs, deployments, code, tests, stakeholder updates, and the postmortem. Incident Commander AI keeps that chain evidence-backed, bounded, and human-controlled.

### What it does

Incident Commander AI provides one incident room that: normalizes a production-style alert and redacts secret-shaped data; correlates telemetry, deploy history, repository evidence, and runbooks; ranks cited hypotheses and maps evidence to code; proposes a bounded remediation plan, then stops for human approval; creates a candidate patch inside an isolated workspace; reconstructs and verifies the patch with targeted tests, full tests, lint, typecheck, regression coverage, and deterministic risk review; requires a second, artifact-bound approval before recording a draft-PR package; and drafts stakeholder communications and an evidence-linked postmortem.

### How we built it

The operator experience uses Next.js 15 and strict TypeScript. The API and workflow use FastAPI, Pydantic v2, SQLAlchemy, Alembic, PostgreSQL, and Redis. A bounded OpenAI Responses adapter uses strict Pydantic structured output for investigation synthesis. A credentialed smoke receipt proves a GPT-5.6 request returned gpt-5.6-sol, parsed into the schema, used store=false, and safely returned insufficient evidence for sparse synthetic input. The product and repository were developed side-by-side with Codex during Build Week. The codebase includes a fail-closed Codex CLI gateway with workspace-write confinement, network denial, a secret-free environment, and explicit engine provenance. The reliable recorded golden path uses deterministic fixture providers and never silently switches to a live provider when credentials are present. Challenges The hardest problem was separating intelligence from authority. Model output is only a typed proposal; deterministic code validates citations, budgets, approval bindings, verification artifacts, and risk before the workflow advances. We also made provenance visible so simulated evidence cannot be mistaken for a live OpenAI, Codex, or GitHub action. Accomplishments The complete two-approval path reaches RESOLUTION_DRAFTED. 185 backend tests, 20 web tests, 6 shared-contract tests, and 22 Chromium scenarios pass. Eight deterministic safety evaluations cover the golden path, insufficient evidence, flaky tests, risky migrations, redaction, prompt injection, noisy telemetry, and rollback cancellation. Five consecutive fresh-database CLI demos pass. Both production Docker images build; the PostgreSQL/Redis/API/web/worker stack reports healthy. Gitleaks and dependency security checks pass.

### What we learned

Reliable agent products need an evidence model and an authorization model, not just a prompt. The most useful design decision was making agents capable of proposing and editing within a sandbox while the state machine alone decides what is grounded, approved, verified, and safe to expose.

### What's next

Next steps are production evidence providers, deployment proof, optional Slack delivery, and a real draft-only GitHub integration for teams that explicitly enable those credentials and policies. Truthful demo disclosure The recorded golden demo uses deterministic fixture telemetry, a fixture code-agent, and a simulated offline draft PR for repeatability. A separate credentialed GPT-5.6 Responses smoke test proves strict structured output. No live GitHub write, production deployment, or credentialed Codex repository diff is claimed.

## README (from the GitHub repository)

# Incident Commander AI

AI incident commander for small engineering teams: evidence-grounded diagnosis, human-approved remediation, verified patches. Blueprint: `docs/AI_INCIDENT_COMMANDER_MASTER_BLUEPRINT_v1.md`.

Built side-by-side with Codex for OpenAI Build Week. The optional live investigation adapter targets GPT-5.6 through the Responses API when explicitly configured; the reproducible judging demo remains credential-free and clearly labelled simulated.

**Status: M0-M9 complete and submitted to OpenAI Build Week.** The deterministic demo completes the two-approval workflow through an explicitly simulated draft-PR package, communications, and an evidence-linked postmortem. No external credentials are required.

## Public submission artifacts

- Demo video: https://youtu.be/-8zRF8RCuc8
- Devpost project: https://devpost.com/software/incident-commander-ai
- Source repository: https://github.com/AtchayamG/ai-incident-commander
- Final submission receipt: [docs/submission/final-submission-receipt.md](docs/submission/final-submission-receipt.md)

## Layout

| Path | What |
|---|---|
| `services/api` | Python 3.12 FastAPI backend (Pydantic v2, strict mypy, ruff, pytest) |
| `apps/web` | Next.js 15 App Router frontend (strict TypeScript, Vitest) |
| `packages/contracts` | Shared TypeScript contract types mirroring the backend Pydantic models |
| `docs/adr` | Architecture decisions, including the local-demo runtime boundary |
| `docs/architecture` | System context, state machine, security model, demo architecture |
| `LICENSE` | MIT license for public review and reuse |

## Quick start

Docker (one command):

```bash
make docker-up        # or: docker compose up -d --build
# web: http://localhost:3000   api: http://localhost:8000/docs
```

Native:

```bash
make setup            # pnpm install + backend venv (Python 3.12) + dev deps
make dev-api          # FastAPI on :8000
make dev-web          # Next.js on :3000 (second terminal)
```

`make bootstrap` is an alias for the fresh-clone setup contract. `make dev` runs the Docker development stack in the foreground.

Windows or any host without GNU Make can use the underlying commands directly:

```powershell
pnpm install --frozen-lockfile
uv sync --project services/api --extra dev
uv run --project services/api python -m uvicorn app.main:app --app-dir services/api --reload --port 8000
# second terminal
pnpm --filter @incident-commander/web dev
```

## Quality gates

```bash
make lint             # ruff + next lint + tsc
make typecheck        # mypy --strict + tsc --noEmit
make test             # backend, shared-contract, and web tests
make eval             # eight deterministic safety scenarios
make secret-scan      # Gitleaks over current tree and Git history
make demo-assert      # five complete deterministic demo runs
make openai-smoke     # optional credentialed GPT-5.6 structured-output proof
```

CI (`.github/workflows/ci.yml`) enforces backend/frontend gates, the web build, five deterministic demos, secret and dependency scans, and release-image builds on every push/PR to `main`.

## Golden demo (no credentials)

```bash
make demo-reset       # verify protected reset and RECEIVED seed state
make demo-run         # one full run through RESOLUTION_DRAFTED
make demo-assert      # five consecutive asserted runs
```

On Windows hosts without GNU Make, run the underlying command directly:

```powershell
uv run --directory services/api python -m app.demo.runner --runs 5
```

Every run uses an ephemeral SQLite database, fixture investigation, and the fixture code-agent. It exercises both public approval endpoints and asserts `RESOLUTION_DRAFTED`, simulated provider provenance, communications, and the evidence-linked postmortem. It never contacts OpenAI or GitHub.

See `docs/architecture/demo-architecture.md` for the full walkthrough.

## Architecture at a glance

```mermaid
flowchart LR
  J["Judge / incident commander"] --> W["Next.js review UI"]
  W --> A["FastAPI typed workflow API"]
  A --> S["SQLAlchemy + PostgreSQL default stack"]
  A -. "ephemeral test/demo runner" .-> Q["Deterministic SQLite store"]
  A --> F["Fixture telemetry, investigation, code-agent, and PR providers"]
  A -. "optional; fail closed" .-> O["OpenAI Responses API / Codex CLI / GitHub"]
  A --> G["Two recorded human approval gates"]
  G --> V["Sandbox policy + six-check verifier"]
```

The verified submission path is local and simulated where labelled. The default Compose stack uses PostgreSQL and Redis; the repeatability runner uses ephemeral SQLite. See [ADR 009](docs/adr/009-local-demo-runtime-boundary.md) for the remaining hosted-production boundary.

## Verified baseline

- Backend: Ruff and strict mypy pass across 56 application source files; 185 tests pass.
- Frontend: lint, strict typecheck, 20 web tests, 6 shared-contract tests, and production build pass.
- Browser: 22 Chromium scenarios pass, including four-viewport overflow checks, internal-link validation, and a real local-API flow through both approvals.
- Evaluations: all 8 deterministic safety scenarios and 13 grader/mutation tests pass.
- Optional live integrations fail closed and never replace deterministic demo mode. A bounded credentialed GPT-5.6 structured-output receipt is documented separately and is never implied by fixture artifacts.

See [task status](docs/project/taskstatus.md), [evidence checklist](docs/submission/evidence-checklist.md), [GPT-5.6 receipt](docs/submission/openai-live-smoke.md), and [demo script](docs/submission/demo-script.md) for current proof and remaining limitations.

## Principles

- Evidence passes a redaction boundary before persistence — raw payloads never do.
- Workflow state changes only through the deterministic state machine; model output is a typed proposal.
- External effects (patches, PRs) require recorded human approval.
- Simulated data is always labelled simulated.


## Detected evidence (automated analysis)

Indexed codebase: 197 recognized source files, 1249 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Redis (technology) — detected in the code
- TypeScript (language) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code
- PostgreSQL (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (120 of 316)

```
.dockerignore
.env.example
.github/workflows/ci.yml
.github/workflows/live-openai-smoke.yml
.gitignore
.gitleaks.toml
AGENTS.md
apps/web/.eslintrc.json
apps/web/app/global.css
apps/web/app/incidents/[id]/page.tsx
apps/web/app/layout.tsx
apps/web/app/page.tsx
apps/web/Dockerfile
apps/web/e2e/accessibility.spec.ts
apps/web/e2e/golden-evidence.spec.ts
apps/web/e2e/incident-creation.spec.ts
apps/web/e2e/m4-approval.spec.ts
apps/web/e2e/m6-golden-verification.spec.ts
apps/web/e2e/m6-review.spec.ts
apps/web/e2e/m7-golden-resolution.spec.ts
apps/web/e2e/m7-resolution.spec.ts
apps/web/e2e/m8-product-polish.spec.ts
apps/web/e2e/m9-ui-refinement.spec.ts
apps/web/lib/api.test.ts
apps/web/lib/api.ts
apps/web/next-env.d.ts
apps/web/next.config.js
apps/web/package.json
apps/web/playwright.config.ts
apps/web/tsconfig.json
apps/web/vitest.config.ts
docker-compose.yml
docs/adr/001-monorepo.md
docs/adr/002-backend-framework.md
docs/adr/003-frontend-framework.md
docs/adr/004-docker-contract.md
docs/adr/005-demo-mode.md
docs/adr/006-security-defaults.md
docs/adr/007-simulated-providers.md
docs/adr/008-investigation-agent-outputs.md
docs/adr/009-local-demo-runtime-boundary.md
docs/adr/frontend-m1-architecture.md
docs/AI_INCIDENT_COMMANDER_MASTER_BLUEPRINT_v1.md
docs/architecture/demo-architecture.md
docs/architecture/security-model.md
docs/architecture/system-context.md
docs/architecture/workflow-state-machine.md
docs/BLUEPRINT_EXECUTION_INDEX.md
docs/deep-research-report.md
docs/fixtures/checkout-api.md
docs/project/agent-runs/AGY_M1_E2E.log
docs/project/agent-runs/AGY_M1.log
docs/project/agent-runs/AGY_M2.log
docs/project/agent-runs/AGY_M3.log
docs/project/agent-runs/CLAUDE_M0_AUTH_FAILURE.log
docs/project/agent-runs/CLAUDE_M0_FABLE_LABEL_FAILURE.log
docs/project/agent-runs/CLAUDE_M1_FABLE_LIMIT.log
docs/project/agent-runs/CLAUDE_M1_OPUS_LIMIT.log
docs/project/agent-runs/CLAUDE_M2_CONNECTION_FAILURE.log
docs/project/agent-runs/CLAUDE_M3_FABLE_LIMIT.log
docs/project/agent-runs/CLAUDE_M3_OPUS.log
docs/project/agent-runs/CLAUDE_M4_FABLE_LIMIT.log
docs/project/agent-runs/HERMES_M0_AUTH_FAILURE.log
docs/project/agent-runs/M0_CLAUDE_HANDOFF.md
docs/project/agent-runs/m0-claude.txt
docs/project/agent-runs/M1_AGY_BACKEND_PARTIAL_HANDOFF.md
docs/project/agent-runs/M1_AGY_HANDOFF.md
docs/project/agent-runs/M1_BACKEND_FINAL_HANDOFF.md
docs/project/agent-runs/M1_E2E_AGY_HANDOFF.md
docs/project/agent-runs/m1-backend-claude.txt
docs/project/agent-runs/m1-backend-repair-agy.txt
docs/project/agent-runs/m1-e2e-agy.txt
docs/project/agent-runs/m1-frontend-agy.txt
docs/project/agent-runs/M2_EVIDENCE_FINAL_HANDOFF.md
docs/project/agent-runs/M2_FRONTEND_AGY_HANDOFF.md
docs/project/agent-runs/m2-evidence-claude.txt
docs/project/agent-runs/m2-frontend-agy.txt
docs/project/agent-runs/M3_CLAUDE_OPUS_HANDOFF.md
docs/project/agent-runs/M3_FRONTEND_AGY_HANDOFF.md
docs/project/agent-runs/m3-frontend-agy.txt
docs/project/agent-runs/m3-investigation-claude.txt
docs/project/agent-runs/M4_APPROVAL_UI_FINAL_HANDOFF.md
docs/project/agent-runs/M4_REMEDIATION_FINAL_HANDOFF.md
docs/project/agent-runs/m4-approval-ui-agy.log
docs/project/agent-runs/m4-remediation-claude.txt
docs/project/agent-runs/M5_CODEX_SANDBOX_FINAL_HANDOFF.md
docs/project/agent-runs/m5-codex-sandbox-fable-refill.log
docs/project/agent-runs/m5-codex-sandbox-opus-continuation.txt
docs/project/agent-runs/m5-codex-sandbox-opus.log
docs/project/agent-runs/M6_REVIEW_UI_FINAL_HANDOFF.md
docs/project/agent-runs/M6_VERIFICATION_FABLE_PARTIAL_HANDOFF.md
docs/project/agent-runs/M6_VERIFICATION_OPUS_FINAL_HANDOFF.md
docs/project/agent-runs/m6-review-ui-agy.log
docs/project/agent-runs/m6-verification-claude.log
docs/project/agent-runs/m6-verification-claude.txt
docs/project/agent-runs/m6-verification-opus-continuation.txt
docs/project/agent-runs/m6-verification-opus.log
docs/project/agent-runs/M7_RESOLUTION_BACKEND_FINAL_HANDOFF.md
docs/project/agent-runs/M7_RESOLUTION_UI_FINAL_HANDOFF.md
docs/project/agent-runs/m7-resolution-backend-agy-final-repair.log
docs/project/agent-runs/m7-resolution-backend-agy-final-repair.txt
docs/project/agent-runs/m7-resolution-backend-agy-repair.log
docs/project/agent-runs/m7-resolution-backend-agy-repair.txt
docs/project/agent-runs/m7-resolution-backend-agy.log
docs/project/agent-runs/m7-resolution-backend-fable.log
docs/project/agent-runs/m7-resolution-backend-opus.log
docs/project/agent-runs/m7-resolution-backend-opus.txt
docs/project/agent-runs/m7-resolution-ui-agy-repair.log
docs/project/agent-runs/m7-resolution-ui-agy-repair.txt
docs/project/agent-runs/m7-resolution-ui-agy.log
docs/project/agent-runs/m7-resolution-ui-agy.txt
docs/project/agent-runs/M8_PRODUCT_POLISH_FINAL_HANDOFF.md
docs/project/agent-runs/m8-product-polish-agy.log
docs/project/agent-runs/m8-product-polish-agy.txt
docs/project/agent-runs/M9_DEMO_ASSETS_AGY_FINAL_HANDOFF.md
docs/project/agent-runs/M9_EVALS_AGY_HANDOFF.md
docs/project/agent-runs/M9_OPENAI_INTEGRATION_FINAL_HANDOFF.md
docs/project/agent-runs/M9_UI_REFINEMENT_AGY_HANDOFF.md
docs/project/agent-runs/m9-completion-audit-agy.log
docs/project/agent-runs/m9-completion-audit-agy.txt
[196 more files omitted for size]
```

### Dependencies

- apps/web/package.json: @axe-core/playwright@^4.12.1, @incident-commander/contracts@workspace:*, @playwright/test@^1.61.1, @types/node@^20.16.0, @types/react@^18.3.0, @types/react-dom@^18.3.0, eslint@^8.57.0, eslint-config-next@15.5.18, next@15.5.18, react@^18.3.1, react-dom@^18.3.1, typescript@^5.5.0, vitest@^3.2.6
- packages/contracts/package.json: typescript@^5.5.0, vitest@^3.2.6
- services/api/pyproject.toml: alembic@>=1.13.0, fastapi@>=0.115.0,<1.0, httpx@>=0.27.0, mypy@>=1.11.0, openai@>=1.73.0,<3.0, psycopg[binary]@>=3.2.0,<4.0, pydantic@>=2.8.0,<3.0, pytest@>=8.0.0, redis@>=5.0.0,<7.0, ruff@>=0.6.0, sqlalchemy@>=2.0.0, uvicorn[standard]@>=0.30.0,<1.0

### Recent commits (newest first)

- docs: record final hackathon submission
- fix: align browser CI Python environment
- fix: unblock GitHub CI
- docs: prepare final Devpost answers
- docs: publish submission artifact links
- docs: verify public captioned demo
- docs: record uploaded demo URL
- docs: refresh live Devpost submission state
- feat: finalize M9 submission package
- docs: produce narrated submission demo video
- feat(api): complete incident command contracts
- feat: complete M0 service foundation
- feat: align M9 deterministic evaluation suite
- feat(m9): complete local submission proof
- chore(m9): enforce full-history secret scan
- feat(m9): add fail-closed OpenAI investigation gateway
- test(m9): add five-run golden demo assertion
- docs(m9): integrate truthful demo assets
- docs(m8): close verified product polish milestone
- feat(m8): integrate truthful product polish

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

### AGENTS.md

```markdown
# Repository Instructions

Source of truth: `docs/AI_INCIDENT_COMMANDER_MASTER_BLUEPRINT_v1.md`.

- Complete P0 milestones M0-M9 in order; P1 must not delay P0.
- Use strict typed contracts and deterministic fixture providers.
- Never expose secrets or claim simulated evidence is live.
- Require approval before workspace writes and external actions.
- Run untrusted repository commands only through the sandbox allowlist.
- Never merge, deploy, push protected branches, or perform production actions.
- Use `make lint`, `make typecheck`, `make test`, and `make demo-assert` as gates once available.
- Keep `docs/project/taskstatus.md`, `docs/project/handover.md`, `docs/project/BUILD_STATUS.json`, and `docs/project/CODEX_RESULT.md` accurate.

## External-agent routing (persistent project policy)

- Use the `orchestrate-external-coding-agents` skill for delegated project work in every session.
- Route complex architecture/backend/reasoning work to Claude `Fable 5` first while usage remains.
- When Fable usage is exhausted, route Claude work to `Opus 4.8`.
- Route UI/UX and suitable frontend/integration tasks to agy.
- Use Hermes for bounded implementation, tests, documentation, repair, or fallback when authenticated.
- Keep one clean worktree per writable worker, avoid overlapping file ownership, and reproduce all worker verification before integration.

## Repository structure

- Keep the project root clean and purpose-driven.
- Store documentation and durable project state under `docs/` with clear subfolders (`docs/project/`, `docs/adr/`, `docs/architecture/`, `docs/submission/`, `docs/testing/`).
- Root Markdown is limited to tooling/convention entrypoints: `AGENTS.md` and `README.md`.
- Do not create duplicate documentation trees or miscellaneous files at the root.

```

### docs/BLUEPRINT_EXECUTION_INDEX.md

```markdown
# Blueprint Execution Index

| Area | Blueprint sections | Milestones |
|---|---|---|
| Product, users, scope | 1–7 | M0–M9 |
| Stack and architecture | 8–10 | M0 |
| Workflow and agents | 11–15 | M2–M5 |
| Data and APIs | 16–17 | M0–M3 |
| Frontend UX | 18 | M1–M8 |
| Sandbox and integrations | 19–20 | M4–M7 |
| Security and observability | 21–22 | M0–M8 |
| Evaluation and testing | 23–25 | M0–M8 |
| Deployment and repository | 26–27 | M0, M9 |
| Governance and milestones | 28–31 | M0–M9 |
| Golden fixture and demo | 32–33 | M2–M9 |
| Submission and environment | 34–38 | M0, M9 |
| ADRs and failure prevention | 39–40 | M0–M8 |
| Definition of done | 41–43 | M9 |

P0 is the controlling scope. Each material claim must cite evidence; workspace mutation and external PR creation require separate approvals; deterministic verification controls PR eligibility.


```

### package.json

```
{
  "name": "incident-commander-ai",
  "version": "0.1.0",
  "private": true,
  "packageManager": "pnpm@10.34.4",
  "pnpm": {
    "overrides": {
      "postcss": "^8.5.10",
      "vite": "^6.4.3"
    }
  },
  "scripts": {
    "dev": "pnpm --filter @incident-commander/web dev",
    "build": "pnpm -r run build",
    "test": "pnpm -r run test",
    "test:e2e": "pnpm --filter @incident-commander/web test:e2e",
    "lint": "pnpm -r run lint",
    "typecheck": "pnpm -r run typecheck"
  }
}

```

### docker-compose.yml

```yaml
services:
  api:
    build:
      context: ./services/api
    ports:
      - "8000:8000"
    environment:
      DEMO_MODE: "true"
      DEMO_ADMIN_KEY: ${DEMO_ADMIN_KEY:-demo-admin-key}
      CORS_ORIGINS: http://localhost:3000
      DATABASE_URL: postgresql+psycopg://incident:incident-local@postgres:5432/incident_commander
      REDIS_URL: redis://redis:6379/0
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "python", "-c", "import json,urllib.request; assert json.load(urllib.request.urlopen('http://localhost:8000/health/dependencies'))['status'] == 'ok'"]
      interval: 10s
      timeout: 3s
      retries: 5

  worker:
    build:
      context: ./services/api
    command: ["python", "-m", "app.worker"]
    environment:
      REDIS_URL: redis://redis:6379/0
    depends_on:
      redis:
        condition: service_healthy

  web:
    build:
      context: .
      dockerfile: apps/web/Dockerfile
      args:
        NEXT_PUBLIC_API_URL: http://localhost:8000
    ports:
      - "3000:3000"
    environment:
      NEXT_PUBLIC_API_URL: http://localhost:8000
    depends_on:
      api:
        condition: service_healthy

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: incident
      POSTGRES_PASSWORD: incident-local
      POSTGRES_DB: incident_commander
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U incident -d incident_commander"]
      interval: 5s
      timeout: 3s
      retries: 10

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  pgdata:

```

### packages/contracts/package.json

```
{
  "name": "@incident-commander/contracts",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "main": "src/index.ts",
  "types": "src/index.ts",
  "scripts": {
    "lint": "tsc --noEmit",
    "typecheck": "tsc --noEmit",
    "test": "vitest run"
  },
  "devDependencies": {
    "typescript": "^5.5.0",
    "vitest": "^3.2.6"
  }
}

```

### services/api/Dockerfile

```
FROM node:22-slim AS node-runtime

FROM python:3.12-slim

WORKDIR /srv

# Verification commands are labels pinned to a zero-dependency Node harness;
# only the Node 22 runtime is needed for native TypeScript type stripping.
COPY --from=node-runtime /usr/local/bin/node /usr/local/bin/node

COPY pyproject.toml ./
COPY alembic.ini ./
COPY alembic ./alembic
COPY app ./app
COPY fixtures ./fixtures

RUN pip install --no-cache-dir .

ENV DEMO_MODE=true
EXPOSE 8000

CMD ["sh", "-c", "alembic upgrade head && exec uvicorn app.main:app --host 0.0.0.0 --port 8000"]

```

### apps/web/package.json

```
{
  "name": "@incident-commander/web",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "typecheck": "tsc --noEmit",
    "test": "vitest run",
    "test:e2e": "playwright test"
  },
  "dependencies": {
    "@incident-commander/contracts": "workspace:*",
    "next": "15.5.18",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@axe-core/playwright": "^4.12.1",
    "@playwright/test": "^1.61.1",
    "@types/node": "^20.16.0",
    "@types/react": "^18.3.0",
    "@types/react-dom": "^18.3.0",
    "eslint": "^8.57.0",
    "eslint-config-next": "15.5.18",
    "typescript": "^5.5.0",
    "vitest": "^3.2.6"
  }
}

```

### apps/web/Dockerfile

```
# Built from the repository root so the workspace contracts package is available:
#   docker build -f apps/web/Dockerfile .
FROM node:22-alpine AS build

RUN corepack enable

ARG NEXT_PUBLIC_API_URL=http://localhost:8000
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL

WORKDIR /repo
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./
COPY packages/contracts/package.json packages/contracts/
COPY apps/web/package.json apps/web/

RUN pnpm install --frozen-lockfile

COPY packages/contracts packages/contracts
COPY apps/web apps/web

RUN pnpm --filter @incident-commander/web build

FROM node:22-alpine

RUN corepack enable
ENV NEXT_PUBLIC_API_URL=http://localhost:8000
WORKDIR /repo
COPY --from=build /repo ./

EXPOSE 3000
WORKDIR /repo/apps/web
CMD ["npx", "next", "start", "-p", "3000"]

```

### services/api/pyproject.toml

```
[project]
name = "incident-commander-api"
version = "0.1.0"
description = "Incident Commander AI backend (FastAPI, Pydantic v2)"
requires-python = ">=3.12"
dependencies = [
    "fastapi>=0.115.0,<1.0",
    "uvicorn[standard]>=0.30.0,<1.0",
    "pydantic>=2.8.0,<3.0",
    "sqlalchemy>=2.0.0",
    "alembic>=1.13.0",
    "openai>=1.73.0,<3.0",
    "psycopg[binary]>=3.2.0,<4.0",
    "redis>=5.0.0,<7.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=8.0.0",
    "httpx>=0.27.0",
    "ruff>=0.6.0",
    "mypy>=1.11.0",
]

[tool.setuptools.packages.find]
include = ["app*"]
exclude = ["alembic*", "tests*"]

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP", "B", "SIM"]

[tool.mypy]
python_version = "3.12"
strict = true
warn_unused_configs = true
files = ["app", "tests"]

[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_decorators = false

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-q"

```

### apps/web/app/layout.tsx

```typescript
import type { Metadata } from "next";
import "./global.css";

export const metadata: Metadata = {
  title: "Incident Commander AI",
  description: "Dashboard for Incident Commander AI",
  icons: { icon: "/icon.svg" },
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}


```

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