rename(phase 1): CapaKraken → Nexus across code, UI, docs, CI (#61)
CI / Architecture Guardrails (push) Successful in 2m38s
CI / Assistant Split Regression (push) Successful in 3m33s
CI / Typecheck (push) Successful in 3m51s
CI / Lint (push) Successful in 5m2s
CI / E2E Tests (push) Has been cancelled
CI / Fresh-Linux Docker Deploy (push) Has been cancelled
CI / Release Images (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Architecture Guardrails (push) Successful in 2m38s
CI / Assistant Split Regression (push) Successful in 3m33s
CI / Typecheck (push) Successful in 3m51s
CI / Lint (push) Successful in 5m2s
CI / E2E Tests (push) Has been cancelled
CI / Fresh-Linux Docker Deploy (push) Has been cancelled
CI / Release Images (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
rename(phase 1): CapaKraken → Nexus across code, UI, docs, CI (#61) Co-authored-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com> Co-committed-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com>
This commit was merged in pull request #61.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@capakraken/staffing",
|
||||
"name": "@nexus/staffing",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -12,10 +12,10 @@
|
||||
"test:unit:watch": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@capakraken/shared": "workspace:*"
|
||||
"@nexus/shared": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capakraken/tsconfig": "workspace:*",
|
||||
"@nexus/tsconfig": "workspace:*",
|
||||
"typescript": "^5.6.3",
|
||||
"vitest": "^2.1.8",
|
||||
"@vitest/coverage-v8": "^2.1.9"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AllocationStatus } from "@capakraken/shared";
|
||||
import { AllocationStatus } from "@nexus/shared";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { findCapacityWindows, analyzeUtilization } from "../capacity-analyzer.js";
|
||||
import type { CapacityAnalysisInput } from "../capacity-analyzer.js";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* analyzeUtilization and findCapacityWindows functions correctly handle the
|
||||
* resulting utilization when vacation blocks are modelled as full-day allocations.
|
||||
*/
|
||||
import { AllocationStatus } from "@capakraken/shared";
|
||||
import { AllocationStatus } from "@nexus/shared";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { analyzeUtilization, findCapacityWindows } from "../capacity-analyzer.js";
|
||||
import type { CapacityAnalysisInput } from "../capacity-analyzer.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AllocationStatus } from "@capakraken/shared";
|
||||
import { AllocationStatus } from "@nexus/shared";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { analyzeUtilization, findCapacityWindows } from "../capacity-analyzer.js";
|
||||
import type { CapacityAnalysisInput } from "../capacity-analyzer.js";
|
||||
|
||||
@@ -5,14 +5,11 @@ import {
|
||||
type Resource,
|
||||
type UtilizationAnalysis,
|
||||
type UtilizationPeriod,
|
||||
} from "@capakraken/shared";
|
||||
} from "@nexus/shared";
|
||||
|
||||
export interface CapacityAnalysisInput {
|
||||
resource: Pick<Resource, "id" | "displayName" | "chargeabilityTarget" | "availability">;
|
||||
allocations: (Pick<
|
||||
Allocation,
|
||||
"startDate" | "endDate" | "hoursPerDay" | "status"
|
||||
> & {
|
||||
allocations: (Pick<Allocation, "startDate" | "endDate" | "hoursPerDay" | "status"> & {
|
||||
projectName: string;
|
||||
isChargeable: boolean;
|
||||
})[];
|
||||
@@ -71,7 +68,13 @@ export function analyzeUtilization(input: CapacityAnalysisInput): UtilizationAna
|
||||
let totalAvailableHours = 0;
|
||||
|
||||
const DOW_KEYS = [
|
||||
"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday",
|
||||
"sunday",
|
||||
"monday",
|
||||
"tuesday",
|
||||
"wednesday",
|
||||
"thursday",
|
||||
"friday",
|
||||
"saturday",
|
||||
] as const;
|
||||
|
||||
const current = new Date(analysisStart);
|
||||
@@ -154,7 +157,13 @@ export function findCapacityWindows(
|
||||
let windowMinHours = Infinity;
|
||||
|
||||
const DOW_KEYS = [
|
||||
"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday",
|
||||
"sunday",
|
||||
"monday",
|
||||
"tuesday",
|
||||
"wednesday",
|
||||
"thursday",
|
||||
"friday",
|
||||
"saturday",
|
||||
] as const;
|
||||
|
||||
function closeWindow(closeDate: Date) {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import type { Resource, ScoreBreakdown, SkillEntry, StaffingSuggestion } from "@capakraken/shared";
|
||||
import { SCORE_WEIGHTS } from "@capakraken/shared";
|
||||
import type { Resource, ScoreBreakdown, SkillEntry, StaffingSuggestion } from "@nexus/shared";
|
||||
import { SCORE_WEIGHTS } from "@nexus/shared";
|
||||
|
||||
export interface SkillMatchInput {
|
||||
requiredSkills: string[];
|
||||
preferredSkills?: string[];
|
||||
resources: (Pick<Resource, "id" | "displayName" | "eid" | "skills" | "lcrCents" | "chargeabilityTarget"> & {
|
||||
resources: (Pick<
|
||||
Resource,
|
||||
"id" | "displayName" | "eid" | "skills" | "lcrCents" | "chargeabilityTarget"
|
||||
> & {
|
||||
currentUtilizationPercent: number;
|
||||
hasAvailabilityConflicts: boolean;
|
||||
conflictDays?: string[];
|
||||
@@ -79,10 +82,7 @@ export function computeSkillScore(
|
||||
/**
|
||||
* Computes availability score (0-100) based on whether conflicts exist.
|
||||
*/
|
||||
export function computeAvailabilityScore(
|
||||
hasConflicts: boolean,
|
||||
conflictDayCount = 0,
|
||||
): number {
|
||||
export function computeAvailabilityScore(hasConflicts: boolean, conflictDayCount = 0): number {
|
||||
if (!hasConflicts) return 100;
|
||||
// Reduce score by 10 per conflict day, minimum 0
|
||||
return Math.max(0, 100 - conflictDayCount * 10);
|
||||
@@ -92,10 +92,7 @@ export function computeAvailabilityScore(
|
||||
* Computes cost score (0-100). Lower LCR = higher score.
|
||||
* Normalized against a budget target.
|
||||
*/
|
||||
export function computeCostScore(
|
||||
resourceLcrCents: number,
|
||||
budgetLcrCentsPerHour?: number,
|
||||
): number {
|
||||
export function computeCostScore(resourceLcrCents: number, budgetLcrCentsPerHour?: number): number {
|
||||
if (!budgetLcrCentsPerHour || budgetLcrCentsPerHour <= 0) return 50; // Neutral
|
||||
if (resourceLcrCents <= budgetLcrCentsPerHour) return 100;
|
||||
// Above budget: score decreases linearly, 0 at 2× budget
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { SkillEntry, ValueScoreBreakdown } from "@capakraken/shared";
|
||||
import type { SkillEntry, ValueScoreBreakdown } from "@nexus/shared";
|
||||
|
||||
export interface ValueScoreInput {
|
||||
skills: SkillEntry[];
|
||||
lcrCents: number;
|
||||
chargeabilityTarget: number;
|
||||
currentChargeability: number; // actual % (computed from allocations by caller)
|
||||
maxLcrCents: number; // org-wide max (for normalization)
|
||||
maxLcrCents: number; // org-wide max (for normalization)
|
||||
}
|
||||
|
||||
export interface ValueScoreWeights {
|
||||
@@ -46,16 +46,15 @@ export function computeValueScore(
|
||||
}
|
||||
|
||||
// 4. Chargeability: closer to target = higher; ±50pp gap = 0
|
||||
const chargeability = Math.max(
|
||||
0,
|
||||
100 - Math.abs(chargeabilityTarget - currentChargeability) * 2,
|
||||
);
|
||||
const chargeability = Math.max(0, 100 - Math.abs(chargeabilityTarget - currentChargeability) * 2);
|
||||
|
||||
// 5. Experience: avg yearsExperience capped at 10yr → 100
|
||||
let experience = 0;
|
||||
const skillsWithYears = skills.filter((s) => (s.yearsExperience ?? 0) > 0);
|
||||
if (skillsWithYears.length > 0) {
|
||||
const avgYears = skillsWithYears.reduce((sum, s) => sum + (s.yearsExperience ?? 0), 0) / skillsWithYears.length;
|
||||
const avgYears =
|
||||
skillsWithYears.reduce((sum, s) => sum + (s.yearsExperience ?? 0), 0) /
|
||||
skillsWithYears.length;
|
||||
experience = Math.min(100, Math.round(avgYears * 10));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@capakraken/tsconfig/base.json",
|
||||
"extends": "@nexus/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
|
||||
Reference in New Issue
Block a user