- Upload accepts multiple files at once (hold Ctrl/Cmd to select)
- All files extracted and combined into one document for AI parsing
- Each file clearly labelled with filename separator in combined text
- Progress shows "Extracting text from file1.xlsx..." per file
- Source filename stores comma-separated list of all uploaded files
- Works with both Normal and Deep extraction modes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Problem: Complex client Excel files (30+ columns, merged cells, Q&A columns,
tier data) produced zero assets because the extraction was a dumb pipe dump
that lost all column context.
Fix:
- Smart Excel extraction: detects header rows, labels each value with its
column name, skips empty sheets, handles merged cells. Claude now sees
"Top 10 deliverables: Toolbox presentation deck | Tier A: Yes | 1"
instead of "Toolbox | Base | Toolbox presentation deck | ü' | Yes | 1"
- Two extraction modes on Upload tab:
- Normal: fast single-pass extraction (~$0.05)
- Deep Extraction: two-pass AI analysis (~$0.15-0.30)
Pass 1: Claude analyzes the spreadsheet structure
Pass 2: Claude extracts assets using the structural understanding
- Upload endpoint accepts ?mode=normal|deep query parameter
- Background parse shows "Deep extraction: analyzing structure (Pass 1 of 2)"
- Tested against both Wella files - header-aware extraction produces
clear labelled output
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Model type labels now show "(AI rates built-in)" for AI variants
- New Project page: warning when AI model type is selected
- Team Shape tab: amber warning banner when project uses AI model type
explaining that hours already include AI efficiency
- AI_MODEL_TYPES constant exported for reuse
- Prevents users from applying efficiency profiles on top of AI model rates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Tier mapping now on Upload tab (set BEFORE matching, not after)
- Added presets: S/M/L, Small/Medium/Large
- Full preset list: None, A/B/C, 1/2/3, S/M/L, Small/Med/Large, Gold/Silver/Bronze
- "None" button to clear tier mapping
- Removed "Expand to Tiers" button from Match Review (redundant)
- Helper text explains to set tiers before matching
- Matching uses pre-set tiers to pick correct GMAL complexity variant
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Doc parser now extracts tier labels (Tier A, A, Gold, etc.) per asset
- Matching uses tier to find the correct GMAL complexity variant:
- Claude matches to the GMAL family (asset type)
- Post-match lookup: (asset_name + target_complexity_level) finds exact variant
- e.g. "Banner - Tier A" with A=Complex → finds Complex variant by asset_name query
- Tier hint passed to Claude prompt for better matching
- No blind expansion - only the tier-appropriate GMAL is matched
- Expand to Tiers button still available for when client doesn't specify tiers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Tier mapping on projects: configurable label→complexity mapping
- Presets: A/B/C, 1/2/3, Gold/Silver/Bronze
- Stored as JSON on project.tier_mapping
- ClientAsset.client_tier field for tracking which tier an asset belongs to
- GMAL family endpoint: GET /gmal/assets/{id}/family returns all complexity variants
- Looks up by asset_name (NOT by GMAL number increment)
- Verified: families share asset_name across non-sequential GMAL IDs
- Expand to Tiers: POST /projects/{id}/expand-tiers
- Splits each matched asset into N tier variants (one per tier)
- Finds correct GMAL variant by asset_name + complexity_level query
- Creates new ClientAsset + Match per tier with correct GMAL
- Removes original un-tiered asset after expansion
- Frontend: tier preset buttons + expand button on Match Review tab
- Tier tags shown with label → complexity mapping
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Brief Analysis now accepts pasted text OR uploaded file
- Textarea for typing/pasting brief directly (no upload required)
- Re-analyze button returns to input screen
- Team Shape Excel sheets now use formulas:
- FTE = Hours/1800 (formula)
- Adjusted Hours = Original * (1-eff%) (formula)
- Hours Saved = Original - Adjusted (formula)
- Headcount = IF/CEILING formula
- Base team shape also uses FTE + headcount formulas
- All sheets are now formula-driven, Finance can edit hours and see recalculation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Iterative Prompting:
- Chat box on Match Review tab for natural language refinement
- "re-run under 70%" / "ignore zero volume" / "set all volumes to 1"
- Claude interprets instruction into structured actions
- Actions: rematch_below_threshold, rematch_specific, delete_assets, set_volume
- Re-matches affected assets automatically after refinement
- Chat log shows instruction history
RFP/Brief Analysis:
- New "Brief Analysis" tab between Upload and Match Review
- Extracts: summary, objectives, KPIs, channels, audiences, deliverable categories,
constraints, timeline, budget, complexity assessment
- Generates prioritized discovery questions (Red/Amber/Green)
- Questions include category, rationale, and priority level
- Stored as JSON in project.brief_analysis field
- Uploaded files now saved to data dir for re-analysis
- Re-analyze button to refresh analysis
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Ratecard Summary: Total Hours column now uses =SUM() formulas
- Grand total row uses =SUM() formulas per column
- New "Assumptions & Rates" sheet with editable inputs:
- Global: Hours per FTE, Margin %, Overhead %
- Per-role: Day Rate (£), Annual Salary (£)
- Yellow highlighted input cells for Finance to edit
- Foundation for full formula-linked financial model
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Team Shape tab: profile selector (Conservative/Moderate/Aggressive)
- BTG tool toggles (Pencil, OMG, Creative X, Cortex, Semblance, Share of Model)
- Per-discipline rates shown inline with combined profile+tool percentages
- Efficiency % column in table showing rate per role
- Flat rate fallback still available (10/25/50/75/90%)
- Match feedback endpoint: POST /matches/{id}/feedback (confirm/reject)
- Feedback learning: confirmed matches stored, checked before AI calls
- Known matches applied instantly (no API call, $0 cost)
- Remaining unknowns sent to Claude as before
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ratecard Summary caveats row now combines AI match caveats with the
original GMAL asset caveats (labelled "GMAL Standard Caveats:") below.
Asset Detail sheet splits these into two separate columns.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inserts an "Assumptions / Caveats" row (row 2) in the Ratecard Summary
sheet so users can see each asset's AI-matched caveats without switching
to the Asset Detail tab. Uses the same amber colour scheme as the PDF report.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Assets with quantity 0 are meaningless downstream (produce 0 ratecard hours)
and clutter the review stage — filter them out at parse time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Azure AD has /gsb/ registered, msalConfig had /gsb without slash.
AADSTS50011 error due to mismatch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Access tokens for User.Read scope have audience=graph.microsoft.com,
but the backend validates audience=CLIENT_ID. ID tokens always have
audience=CLIENT_ID so they validate correctly.
Also add upn claim fallback for email extraction from ID token.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
onRedirectNavigate was removed from EndSessionRequest in msal-browser v3+.
clearCache() clears local tokens without redirecting to Microsoft logout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auth.py: replace synchronous httpx.get (blocked event loop) with
async httpx.AsyncClient; add key-rotation refresh on unknown kid
- App.tsx: use onRedirectNavigate: false so Sign out clears only the
local MSAL session without redirecting to Microsoft logout endpoint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move AI parsing and matching into BackgroundTasks so both endpoints
return immediately instead of blocking until Claude finishes (~60s+)
- Frontend now polls project status after upload/match POST returns,
keeping the spinner/progress UI working as before
- Replace <a href> export links with programmatic Axios downloads to fix
missing /gsb base path and missing auth token (401 in production)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- docker-compose: DATA_DIR env var controls data volume mount
(defaults to ./data for local, /var/www/html/gmal-scope-builder/data on server)
- deploy.sh: resolve DATA_DIR from .env, default to persistent web dir
- deploy.sh: rm only frontend files from WEB_DIR, preserve data/ subdir
- .env.example: document DATA_DIR variable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- Efficiency preview: toggle 10/25/50/75/90% to see adjusted FTE live
- Programme roles NOT reduced (they don't scale with AI)
- Excel export: select multiple efficiency levels, each gets its own tab
showing original vs adjusted hours/FTE/headcount with hours saved
- Export buttons on both Ratecard and Team Shape tabs
- team_shape service accepts efficiency_pct parameter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New ai_descriptions service: generates rich brief-friendly descriptions
per GMAL asset via Claude, grouped by category (135/243 generated)
- Descriptions include client synonyms, inclusions/exclusions, use cases,
channel/format info, complexity differentiators
- GMAL Browser shows AI descriptions with green/amber status indicators
- GMAL Editor: editable AI descriptions, per-asset regenerate, batch generate all
- Matching catalog now includes AI descriptions for better semantic matching
- Fixed ORM session expiry bug: snapshot asset data before batch commits
- Fixed enum issue: removed unused UPLOADING/EXTRACTING statuses
- Added app-level logging (basicConfig) so service logs show in docker
- YOLO now batches 20 selections in parallel
- Matching returns 1 best match by default, extras only within 5% of top
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Team shape service: total_hours / 1800 = FTE per role
- Programme roles (6) flagged separately from delivery roles
- New API endpoint GET /projects/{id}/team-shape
- Team Shape tab in frontend with summary stats and role breakdown
- Sheet 3 "Team Shape" in Excel export with discipline grouping,
delivery vs programme split, FTE, rounded headcount, and summary
- Full GMAL catalog matching (replaced pre-filter with compact catalog)
- Upload progress stages with live polling
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Upload now shows live stage progress (uploading -> extracting -> AI parsing -> done)
- Fix match group collapse: proper React state instead of DOM manipulation
- Replace pre-filter with full GMAL catalog sent to Claude (~3k tokens, <$0.01)
- FTS and keyword matching missed too many semantic matches
- Claude now sees all 243 assets and uses semantic understanding
- Improved system prompt with terminology bridges for better scoring
- Per-project AI cost tracking persisted to DB
- Parallel matching with cancel support
- Auto-select matches >= 80%, YOLO button for rest
- Debug panel for AI call inspection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dockerized web app (FastAPI + React + PostgreSQL) for scoping client ratecards
against the GMAL master asset database. Features:
- GMAL data ingestion from Excel (390 assets, 120 roles, 5 model types)
- AI-powered document parsing and asset extraction (Claude Opus 4.6)
- AI matching engine with parallel batching, confidence scoring, caveats
- Ratecard builder with hours x volume calculation
- Excel and PDF export
- GMAL browser and inline editor
- AI cost tracking per project (persisted to DB)
- Debug panel for AI call inspection
- Dark theme UI with gold (#FFC407) accent
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>