From bf3751f66777b4eea70d204d8534bd1ff1151dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Thu, 26 Mar 2026 13:07:36 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20invert=20shoring=20ratio=20logic=20?= =?UTF-8?q?=E2=80=94=20higher=20offshore=20=3D=20better?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shoring indicator logic was backwards. In the business context, higher offshore = more cost-efficient = GOOD. Inverted logic: - Green: offshore >= threshold (target met, e.g. >= 55%) - Yellow: offshore close to threshold (threshold-10 to threshold) - Red: offshore below threshold (too little offshore, too expensive) Updated: - ShoringIndicator: getSeverity() inverted, badge text updated - ProjectModal: "Max Offshore" renamed to "Min Offshore" with new tooltip - AI Tool: status text reflects "target met" vs "below target" - Tool description: "higher offshore is better, threshold is minimum" Co-Authored-By: claude-flow --- apps/web/src/components/projects/ProjectModal.tsx | 4 ++-- apps/web/src/components/projects/ShoringIndicator.tsx | 9 +++++---- packages/api/src/router/assistant-tools.ts | 10 +++++++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/apps/web/src/components/projects/ProjectModal.tsx b/apps/web/src/components/projects/ProjectModal.tsx index 49c0a41..1f4cca2 100644 --- a/apps/web/src/components/projects/ProjectModal.tsx +++ b/apps/web/src/components/projects/ProjectModal.tsx @@ -499,8 +499,8 @@ export function ProjectModal({ project, onClose }: ProjectModalProps) {
= threshold) return "red"; - if (offshoreRatio >= threshold - 10) return "yellow"; - return "green"; + // Higher offshore = better (cost-efficient). Threshold is the MINIMUM target. + if (offshoreRatio >= threshold) return "green"; // Target met + if (offshoreRatio >= threshold - 10) return "yellow"; // Close to target + return "red"; // Too little offshore } const SEVERITY_BADGE: Record = { @@ -127,7 +128,7 @@ export function ShoringIndicator({ projectId }: { projectId: string }) { {data.offshoreRatio}% offshore - {severity === "red" ? ` — Above ${data.threshold}% limit` : ""} + {severity === "green" ? " — Target met" : severity === "red" ? ` — Below ${data.threshold}% target` : ""}
diff --git a/packages/api/src/router/assistant-tools.ts b/packages/api/src/router/assistant-tools.ts index dd7c233..e46e7b6 100644 --- a/packages/api/src/router/assistant-tools.ts +++ b/packages/api/src/router/assistant-tools.ts @@ -1389,7 +1389,7 @@ export const TOOL_DEFINITIONS: ToolDef[] = [ type: "function", function: { name: "get_shoring_ratio", - description: "Get the onshore/offshore staffing ratio for a project. Shows the percentage of work hours allocated to each country, whether the project exceeds its nearshore threshold, and a full country breakdown.", + description: "Get the onshore/offshore staffing ratio for a project. Higher offshore is better (cost-efficient). The threshold is the MINIMUM offshore target. Shows country breakdown and whether the target is met.", parameters: { type: "object", properties: { @@ -5576,9 +5576,13 @@ const executors = { .map(([code, info]) => `${code} ${info.pct}% (${info.resourceCount} people)`) .join(", "); - const warning = result.isAboveThreshold ? ` -- Above ${threshold}% offshore threshold!` : ""; + const status = result.offshoreRatio >= threshold + ? `Target met (>=${threshold}% offshore)` + : result.offshoreRatio >= threshold - 10 + ? `Close to target (${threshold}% offshore needed)` + : `Below target — only ${result.offshoreRatio}% offshore, need ${threshold}%`; - return `Project "${project.name}" (${project.shortCode}): ${result.onshoreRatio}% onshore (${onshoreCode}), ${result.offshoreRatio}% offshore. Breakdown: ${countryParts}.${warning}${result.unknownCount > 0 ? ` (${result.unknownCount} resource(s) without country)` : ""}`; + return `Project "${project.name}" (${project.shortCode}): ${result.onshoreRatio}% onshore (${onshoreCode}), ${result.offshoreRatio}% offshore. ${status}. Breakdown: ${countryParts}.${result.unknownCount > 0 ? ` (${result.unknownCount} resource(s) without country)` : ""}`; }, };