gmal-scope-builder/CLAUDE.md
Vadym Samoilenko b2812593ae Add Azure SSO + production deployment config
- MSAL.js (PKCE) browser-side auth against Azure Entra ID
- Bearer token interceptor on all API calls
- Backend JWT validation middleware (python-jose + JWKS)
- All API routes protected; /api/health stays public
- vite base set to /gsb/, BrowserRouter basename=/gsb
- docker-compose: remove frontend service, lock backend to 127.0.0.1:8002, remove dev volumes
- backend: 2 workers, no --reload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 18:51:18 +00:00

5.3 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Overview

GMAL Scope Builder is a Dockerized AI-powered scoping tool that matches client deliverables (from uploaded Word/Excel documents) against a standardized GMAL asset database, then builds team ratecards and FTE models. The AI layer uses Claude Opus 4.6 for both document parsing and asset matching.

Development Commands

Docker (primary workflow)

docker compose build                          # Build all images
docker compose up -d                          # Start all services (bg)
docker compose logs backend --tail 50         # Backend logs
docker compose logs frontend --tail 20        # Frontend logs
docker compose down                           # Stop all services

Services run on

One-time setup

cp .env.example .env                          # Add ANTHROPIC_API_KEY
# Place GMAL Excel file in data/ directory
curl -X POST http://localhost:8001/api/gmal/ingest   # Populate GMAL catalog

Frontend (without Docker)

cd frontend && npm install
npm run dev       # Vite dev server with HMR
npm run build     # TypeScript compile + production bundle

Backend (without Docker)

cd backend && pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000

Database operations

# Backup
docker compose exec db pg_dump -U scope_user -d scope_builder > backups/dump.sql

# Restore
docker compose exec -T db psql -U scope_user -d scope_builder < backups/dump.sql

Architecture

Stack

  • Frontend: React 18 + TypeScript + Vite + React Router + Axios
  • Backend: FastAPI + SQLAlchemy (async) + asyncpg + Uvicorn
  • Database: PostgreSQL 16
  • AI: Claude Opus 4.6 via Anthropic SDK (tool_use for structured output)
  • Document parsing: openpyxl, python-docx

Backend structure (backend/app/)

  • main.py: FastAPI app, CORS config, router registration, AI usage/debug endpoints
  • models/: SQLAlchemy ORM — gmal.py (catalog: GmalAsset, Role, GmalHours, ServiceLine) and project.py (workflow: Project, ClientAsset, Match, RatecardLine)
  • services/: Core business logic — see flow below
  • api/: Route handlers for gmal, ingest, projects, matching, ratecard
  • schemas/: Pydantic request/response models
  • utils/claude_client.py: Wraps Anthropic SDK with per-project + global token/cost tracking and a 50-call debug log

Frontend structure (frontend/src/)

  • App.tsx: Router, navigation bar, live AI cost tracker, expandable debug panel
  • pages/: Dashboard, NewProject, ProjectView (main workflow), GmalBrowser, GmalEditor, Help
  • api/client.ts: Axios instance pointing to backend
  • types/index.ts: Shared TS interfaces + MODEL_TYPE_LABELS / CONFIDENCE_COLORS constants

Core data flow

  1. Ingestion — Excel file → excel_parser.pyGmalAsset + Role + GmalHours (per model type) in PostgreSQL

  2. Project creation — User selects one of 5 model types (Current, AI-Enhanced, Offshore+, Local, Factory); this key drives which GmalHours rows are used throughout

  3. Document parsing — Uploaded .docx/.xlsxdoc_parser.py extracts raw text → Claude with extract_assets tool returns structured ClientAsset list (name, description, volume, complexity hint)

  4. AI matching — Each ClientAssetai_matching.py → Claude with submit_matches tool → ranked GMAL matches with confidence (exact/close/multiple/none), score 01, reasoning, caveats. Processed in batches of 10 with cancellation support.

  5. Ratecard building — User selects a match per asset → ratecard_builder.py looks up GmalHours[gmal_asset, model_type], multiplies by ClientAsset.volumeRatecardLine rows (one per role per asset)

  6. Team shapeteam_shape.py aggregates hours per role → FTE = total / 1800; efficiency slider (090%) is applied to delivery roles only (programme roles are not reduced)

  7. Exportexport_excel.py produces multi-tab workbook (ratecard, asset detail, team shape, efficiency); export_pdf.py produces caveats report

Project status lifecycle

draftparsingmatchingreviewbuildingfinalized

AI cost tracking

Every Claude call records input/output tokens and USD cost ($3/M input, $15/M output) via claude_client.py. Costs are stored on the Project model and surfaced globally via GET /ai/usage. The frontend polls this and shows a live cost tracker + expandable debug panel.

Key design decisions

  • All Claude calls use tool_use for structured output — no fragile JSON parsing from free-text responses
  • model_type is set at project creation and cannot change — it filters all GmalHours lookups
  • Programme roles are exempt from efficiency reduction in team shape calculations (they don't scale with AI productivity)
  • Matching is async/batched — supports cancellation mid-job; poll /api/projects/{id}/status for progress
  • The GMAL catalog (390 assets) is ingested from a single Excel file in data/; re-run /api/gmal/ingest to reload after updating the file