Commit graph

52 commits

Author SHA1 Message Date
DJP
dc861fbc23 Excel ratecard summary: add Tier row and split caveat rows
The ratecard summary tab now includes:
- Tier row (showing client_tier A/B/C per asset column) below the header
- Match Summary row (per-match caveat text) — split from combined caveats
- GMAL Standard Caveats row — split from combined caveats

Match summary and GMAL standard caveats were previously merged into a
single row, which made it hard to tell what came from the AI match vs
the standard GMAL clause. Splitting them surfaces both clearly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:12:29 -04:00
DJP
2d44103603 Fix hours × volume bug: store per-1-asset hours, link directly to GMAL
Ratecard lines now store total_hours as per-1-asset hours (= base_hours,
linked to the GMAL row), with volume tracked separately. Aggregators
(team_shape, ratecard summary, Excel matrix, in-app ratecard tab) multiply
by volume themselves when computing total effort. Display behavior is
preserved; storage semantics are clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:11:04 -04:00
DJP
57bffb8347 Fix ratecard build crash: handle multiple selected matches per asset
MultipleResultsFound when building ratecard because some assets had
duplicate selected matches (from re-running matching or YOLO).
Changed scalar_one_or_none() to scalars().first() to take the first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:20:38 -04:00
DJP
06bb1b9bfd Fix deep extraction crash: unescaped curly braces in f-string
Root cause: "name 'name' is not defined" error on line 300
The f-string example {name:"KV 360", tier:"Tier B"} was interpreted
as Python set literal, not as JSON text. Changed to parentheses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:23:25 -04:00
DJP
c49f83a5a2 Role-based access control: Viewer / Editor / Admin
Backend:
- AppUser model with email, name, role (viewer/editor/admin), azure_oid
- Users API: GET /users/me (current user + role), GET /users (admin: list all),
  PUT /users/{id}/role (admin: change role)
- Auto-create user on first login: first user = admin, rest = editor
- get_or_create_user helper for role lookup
- require_role helper for permission checks

Frontend:
- UserRoleContext provides role to all components
- useUserRole() hook: isAdmin, isEditor, isViewer
- Nav items filtered by role: GMAL Editor + Users only for admin
- Dashboard: Ingest button admin-only, New Project editor-only
- User Management page: list all users, change roles via dropdown
- Role badges: admin (red), editor (gold), viewer (grey)

Roles:
- Viewer: view projects, download exports
- Editor: create/edit projects, upload, match, build ratecards
- Admin: all + GMAL Editor, data ingest, user management

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 12:29:04 -04:00
DJP
68d342575e Fix tier extraction: separate entry per tier + user context box
Tier fix (reverses previous "extract once" mistake):
- SEPARATE entry for EACH tier where volume > 0
- "KV 360" Tier A=No/0, Tier B=Yes/1, Tier C=Yes/1 → TWO entries
- Tier field matches column header exactly ("Tier B", "Tier C")
- Tiers with volume=0 or status=No are skipped
- Applied to both normal and deep extraction prompts

User context box (new Step 3 on Upload tab):
- Textarea where users give hints before extraction runs
- Examples: "Focus on Toolbox sheet", "Tier columns are D/F/H"
- Context prepended to Claude prompt in both normal and deep modes
- Passed through upload endpoint → background parse → AI calls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 09:24:07 -04:00
DJP
6273179741 Fix duplicate asset extraction: one entry per unique asset
Problem: Claude extracted the same asset 3 times (once per tier A/B/C),
creating duplicate entries like "Toolbox presentation deck" x3.

Fix: Both normal and deep extraction prompts now say:
- Extract each UNIQUE asset ONCE only
- Do NOT create duplicates for same asset at different tiers
- Use the "tier" field to record the tier label
- Skip assets with volume 0 across all tiers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:15:03 -04:00
DJP
09441a20b8 Fix deep extraction max_tokens: 16k→32k, shorter descriptions
Root cause: stop_reason=max_tokens - Claude ran out of output tokens
before finishing the tool call JSON for 50+ assets.

Fix:
- Bump max_tokens from 16000 to 32000 for both normal and deep extraction
- Tell Claude to keep descriptions SHORT (1 sentence max)
- Reduce input data to 35k chars (from 40k) to leave more room for output
- Better stop_reason logging on normal extraction too

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:51:08 -04:00
DJP
617c1e3ca3 Debug deep extraction Pass 2: better logging, truncate analysis, force tool use
- Log structure analysis length and data length before Pass 2
- Log stop_reason from Claude response
- If no assets returned, log the text response for debugging
- Truncate structure analysis to 4k chars if too long (leaves room for data)
- Reduce data to 40k chars (was 45k, combined with analysis was too large)
- Add instruction: "You MUST call extract_assets with at least one asset"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:43:38 -04:00
DJP
a79529470e Fix header detection: distinguish header text from data values
Problem: Header detection picked data rows (with Yes/No/numbers) as headers
because they had more filled cells than the actual header row (which had
merged cells with gaps). Result: data values became column labels, deep
extraction failed.

Fix:
- Header values must be text-like (not numbers, Yes/No, 0/1, ü, x, -)
- Only consecutive header rows count - stop scanning at first data row
- Multi-row headers combined (row 1 + row 2 both contribute)
- Tested against Wella Job Routes 2: correctly identifies row 2 as header
  with "Buckets | Categories | Top 10 deliverables | Tier A | Tier B | Tier C"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:15:00 -04:00
DJP
d85ef96a06 Add Asset Summary table on Ratecard tab for visual validation
- New "Asset Summary" table at top of Ratecard tab showing:
  #, Client Asset name, Tier, Matched GMAL, Volume, Total Hours
- Grand total row with volume sum and hours sum
- Appears above the existing "Hours by Role" detail table
- Section labels ("Asset Summary" / "Hours by Role") for clarity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 10:56:06 -04:00
DJP
9eaa85dc37 3-step upload flow: select files → set tiers → extract
- Step 1: Select files (shown with gold bullet points after selection)
- Step 2: Tier mapping is REQUIRED - must click "None" or a preset
  before extraction is enabled. Red asterisk indicates required.
- Step 3: Choose Normal/Deep extraction mode, then click "Extract Assets"
- Upload no longer auto-triggers extraction on file select
- Uploaded filenames shown persistently on the Upload tab
- Tier confirmation state tracked (tierConfirmed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 10:52:51 -04:00
DJP
e5b20c1b36 Comprehensive Help page: tier mapping, brief analysis, team shape, tools, refine chat
- Client Tier Mapping: how it works, common mappings, when to set it
- Brief Analysis: what it extracts, discovery questions (Red/Amber/Green), how it feeds into matching
- Team Shape: FTE formula, efficiency profiles (Conservative/Moderate/Aggressive), BTG tool stacking, AI model warning, Excel export tabs
- Refine Chat: example instructions and how it works
- GMAL Browser & Editor: what each does, AI description generation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 10:31:55 -04:00
DJP
7a7f9d762a Update Help page: document prep guide + extraction modes
- New section: "Preparing Documents for Upload"
  - Excel: delete hidden/blank/internal sheets, clean up random data,
    check merged cells
  - Word: remove cover pages, accept tracked changes
  - General: smaller is better, upload multiple files, set tiers first,
    try Normal first then Deep
- Updated Upload step: explains Normal vs Deep extraction with use cases
- Tips on when to use Deep Extraction

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 10:27:54 -04:00
DJP
8a2b45ae31 Deep extraction: live progress between passes + elapsed timer
- Split deep extraction into two separate functions (pass1 + pass2)
  so the background task can update DB between them
- Progress now shows:
  "Pass 1/2: Analyzing structure... (this takes 20-40 seconds)"
  "Pass 1 complete (23s). Pass 2/2: Extracting assets..."
  "Deep extraction complete (52s total). Found 45 assets."
- Live elapsed timer (seconds) shown in the upload spinner
- Timer ticks every second so user knows it's not hung

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 10:03:04 -04:00
DJP
f01774e6f3 Multi-file upload support
- 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>
2026-04-10 09:52:14 -04:00
DJP
714ab98388 Normal + Deep Extraction modes for complex client files
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>
2026-04-10 09:46:04 -04:00
DJP
ad51477432 AI model type warnings to prevent double-counting efficiency
- 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>
2026-04-09 17:20:36 -04:00
DJP
04eed9fdd6 Custom tier editor, brief analysis feeds matching, exportable questions
1. Custom tier editor:
   - Editable label + complexity dropdown per tier row
   - Add/remove tier rows
   - Presets populate editable fields (can be customised after)

2. Brief analysis feeds into matching:
   - Summary, channels, deliverable categories, objectives passed as context
   - Claude gets brief context when matching each asset for better accuracy
   - RFP analysis now improves matching quality, not just informational

3. Discovery questions:
   - "Copy to Clipboard" button for sharing with client
   - Brief Analysis sheet added to Excel export
   - Questions exported with priority, category, rationale

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 16:02:11 -04:00
DJP
8245ae52e2 Move tier mapping to Upload tab, add S/M/L presets, remove expand button
- 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>
2026-04-09 15:28:20 -04:00
DJP
3cb1973f57 Fix tier matching: use client tier to pick correct complexity variant
- 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>
2026-04-09 15:17:20 -04:00
DJP
668ea44ea2 Client tier mapping + GMAL complexity variant expansion
- 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>
2026-04-09 15:02:45 -04:00
DJP
b067326557 Remove Cortex from tool presets 2026-04-09 14:39:19 -04:00
DJP
1d920d62cc Fix: Brief analysis text input, Excel formulas on all sheets
- 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>
2026-04-09 14:37:56 -04:00
DJP
bc778ce7af P2: Iterative prompting + RFP brief analysis engine
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>
2026-04-09 14:15:31 -04:00
DJP
1dcf7c084a P1: Excel SUM formulas + Assumptions & Rates sheet
- 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>
2026-04-09 14:06:46 -04:00
DJP
ecaa5012d9 P1: Frontend profile/tool selector + match feedback loop
- 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>
2026-04-09 14:04:49 -04:00
DJP
0aacb2bb4c Merge branch 'main' of bitbucket.org:zlalani/gmal-scope-builder 2026-04-09 13:48:46 -04:00
DJP
82046c784c P1: Role-specific efficiency profiles + BTG tool efficiencies
Backend:
- New models: MatchFeedback, EfficiencyProfile, EfficiencyRate, ToolEfficiency, ToolEfficiencyRate
- 3 preset profiles seeded: Conservative, Moderate, Aggressive with per-discipline rates
- 6 BTG tools seeded: Pencil, OMG, Creative X, Cortex, Semblance, Share of Model
- Efficiency API: CRUD for profiles and tools at /api/efficiency/
- team_shape.py: accepts profile_rates + tool_rates (per-discipline, additive, capped at 90%)
- team-shape endpoint: accepts profile_id and tool_ids query params
- Programme roles always exempt regardless of method

Example: Moderate profile + Creative X + Pencil → Account Mgmt 10%, Creative 70%, Production 65%

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 13:48:30 -04:00
Vadym Samoilenko
4ed072105f Add GMAL standard caveats to ratecard Excel export
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>
2026-03-31 19:31:10 +01:00
Vadym Samoilenko
de150f3b57 Add caveats row to Ratecard Summary sheet in Excel export
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>
2026-03-31 18:00:29 +01:00
Vadym Samoilenko
8b01213be6 Skip extracted assets with zero or negative volume
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>
2026-03-30 20:18:06 +01:00
Vadym Samoilenko
83bb8f8fa2 Fix redirect URI trailing slash to match Azure AD registration
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>
2026-03-30 11:21:46 +01:00
Vadym Samoilenko
b7db37828b Fix 401: send ID token instead of Graph access token
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>
2026-03-30 11:16:44 +01:00
Vadym Samoilenko
4b4e48be01 Fix logout for MSAL v5: use clearCache() for app-only sign out
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>
2026-03-30 11:14:06 +01:00
Vadym Samoilenko
dbbef4972b Fix blocking JWKS fetch causing 504s + app-only logout
- 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>
2026-03-30 11:11:46 +01:00
Vadym Samoilenko
9596f4231e Fix 504 timeouts on upload/match and broken exports
- 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>
2026-03-30 10:57:34 +01:00
DJP
b5a21764d8 Merge server changes (SSO, /gsb base path) + add proxy timeout 2026-03-28 17:06:39 -04:00
DJP
7bb3679afb Increase Vite proxy timeout to 5min for long AI calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 17:04:37 -04:00
Vadym Samoilenko
c18927f7ab Add vite/client types for import.meta.env support
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 20:23:08 +00:00
Vadym Samoilenko
c37e6888e2 Add DEV_AUTH_BYPASS env var to skip SSO in local dev
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 20:19:22 +00:00
Vadym Samoilenko
c47bf46faa Make data/ path configurable; preserve on frontend redeploy
- 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>
2026-03-28 19:03:38 +00:00
Vadym Samoilenko
53a18d0d62 Add deploy.sh + fix TS build errors
- Idempotent deploy script: git pull, docker build, frontend build via
  Node:20 Docker container, static file copy, Apache config block, reload
- Pre-flight checks for .env required vars
- Fix MSAL cache config (remove storeAuthStateInCookie)
- Fix GmalEditor.tsx undefined→null coercion for ai_efficiency_pct
- Update .env.example with Azure vars

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 19:01:14 +00:00
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
DJP
9b0660c5b4 Add README with deployment guide + fresh DB dump
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 10:42:19 -04:00
DJP
1c3f6fe78f Add AI/Automation efficiency adjustment for team shape
- 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>
2026-03-28 10:36:44 -04:00
DJP
a1bbd330c6 AI-enhanced GMAL descriptions + matching fixes
- 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>
2026-03-28 10:12:04 -04:00
DJP
0a5b552ad2 Add Team Shape calculator (Phase 2) with FTE per role
- 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>
2026-03-27 19:32:34 -04:00
DJP
26d3435be0 Improve matching, upload UX, collapse fix, full catalog approach
- 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>
2026-03-27 19:22:08 -04:00
DJP
23f3eaf3c8 Merge remote and resolve .gitignore conflict 2026-03-27 17:36:10 -04:00