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

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:
2026-05-21 16:28:40 +02:00
committed by Hartmut
parent d9a7ec0338
commit b41c1d2501
943 changed files with 24548 additions and 16832 deletions
@@ -1,6 +1,6 @@
import type { TRPCContext } from "../../trpc.js";
import { AllocationStatus, PermissionKey, UpdateAssignmentSchema } from "@capakraken/shared";
import { SystemRole } from "@capakraken/shared";
import { AllocationStatus, PermissionKey, UpdateAssignmentSchema } from "@nexus/shared";
import { SystemRole } from "@nexus/shared";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { fmtEur } from "../../lib/format-utils.js";
@@ -104,132 +104,168 @@ type AllocationPlanningDeps = {
toAssistantAllocationNotFoundError: (error: unknown) => unknown;
};
export const allocationPlanningReadToolDefinitions: ToolDef[] = withToolAccess([
{
type: "function",
function: {
name: "list_allocations",
description: "List assignments/allocations, optionally filtered by resource or project. Shows who is assigned where, hours/day, dates, and cost.",
parameters: {
type: "object",
properties: {
resourceId: { type: "string", description: "Filter by resource ID" },
projectId: { type: "string", description: "Filter by project ID" },
resourceName: { type: "string", description: "Filter by resource name (partial match)" },
projectCode: { type: "string", description: "Filter by project short code (partial match)" },
status: { type: "string", description: "Filter by status: PROPOSED, CONFIRMED, ACTIVE, COMPLETED, CANCELLED" },
limit: { type: "integer", description: "Max results. Default: 30" },
export const allocationPlanningReadToolDefinitions: ToolDef[] = withToolAccess(
[
{
type: "function",
function: {
name: "list_allocations",
description:
"List assignments/allocations, optionally filtered by resource or project. Shows who is assigned where, hours/day, dates, and cost.",
parameters: {
type: "object",
properties: {
resourceId: { type: "string", description: "Filter by resource ID" },
projectId: { type: "string", description: "Filter by project ID" },
resourceName: {
type: "string",
description: "Filter by resource name (partial match)",
},
projectCode: {
type: "string",
description: "Filter by project short code (partial match)",
},
status: {
type: "string",
description: "Filter by status: PROPOSED, CONFIRMED, ACTIVE, COMPLETED, CANCELLED",
},
limit: { type: "integer", description: "Max results. Default: 30" },
},
},
},
},
},
{
type: "function",
function: {
name: "get_budget_status",
description: "Get the budget status of a project: total budget, confirmed/proposed costs, remaining, utilization percentage.",
parameters: {
type: "object",
properties: {
projectId: { type: "string", description: "Project ID or short code" },
{
type: "function",
function: {
name: "get_budget_status",
description:
"Get the budget status of a project: total budget, confirmed/proposed costs, remaining, utilization percentage.",
parameters: {
type: "object",
properties: {
projectId: { type: "string", description: "Project ID or short code" },
},
required: ["projectId"],
},
required: ["projectId"],
},
},
],
{
list_allocations: {
requiresPlanningRead: true,
},
get_budget_status: {
allowedSystemRoles: [SystemRole.ADMIN, SystemRole.MANAGER, SystemRole.CONTROLLER],
requiresCostView: true,
},
},
], {
list_allocations: {
requiresPlanningRead: true,
},
get_budget_status: {
allowedSystemRoles: [SystemRole.ADMIN, SystemRole.MANAGER, SystemRole.CONTROLLER],
requiresCostView: true,
},
});
);
export const allocationPlanningMutationToolDefinitions: ToolDef[] = withToolAccess([
{
type: "function",
function: {
name: "create_allocation",
description: "Create a new allocation/booking for a resource on a project. Requires manageAllocations permission. Always confirm with the user before calling this. Created with PROPOSED status.",
parameters: {
type: "object",
properties: {
resourceId: { type: "string", description: "Resource ID" },
projectId: { type: "string", description: "Project ID" },
startDate: { type: "string", description: "Start date YYYY-MM-DD" },
endDate: { type: "string", description: "End date YYYY-MM-DD" },
hoursPerDay: { type: "number", description: "Hours per day (e.g. 8)" },
role: { type: "string", description: "Optional role name" },
},
required: ["resourceId", "projectId", "startDate", "endDate", "hoursPerDay"],
},
},
},
{
type: "function",
function: {
name: "cancel_allocation",
description: "Cancel an existing allocation. Can find by allocation ID, or by resource name + project code + date range. Requires manageAllocations permission. Always confirm with the user before calling this.",
parameters: {
type: "object",
properties: {
allocationId: { type: "string", description: "Allocation ID (if known)" },
resourceName: { type: "string", description: "Resource name (partial match)" },
projectCode: { type: "string", description: "Project short code (partial match)" },
startDate: { type: "string", description: "Filter by start date YYYY-MM-DD" },
endDate: { type: "string", description: "Filter by end date YYYY-MM-DD" },
export const allocationPlanningMutationToolDefinitions: ToolDef[] = withToolAccess(
[
{
type: "function",
function: {
name: "create_allocation",
description:
"Create a new allocation/booking for a resource on a project. Requires manageAllocations permission. Always confirm with the user before calling this. Created with PROPOSED status.",
parameters: {
type: "object",
properties: {
resourceId: { type: "string", description: "Resource ID" },
projectId: { type: "string", description: "Project ID" },
startDate: { type: "string", description: "Start date YYYY-MM-DD" },
endDate: { type: "string", description: "End date YYYY-MM-DD" },
hoursPerDay: { type: "number", description: "Hours per day (e.g. 8)" },
role: { type: "string", description: "Optional role name" },
},
required: ["resourceId", "projectId", "startDate", "endDate", "hoursPerDay"],
},
},
},
},
{
type: "function",
function: {
name: "update_allocation_status",
description: "Change the status of an existing allocation. Can reactivate cancelled allocations, confirm proposed ones, etc. Requires manageAllocations permission. Always confirm with the user before calling.",
parameters: {
type: "object",
properties: {
allocationId: { type: "string", description: "Allocation ID" },
resourceName: { type: "string", description: "Resource name (partial match, used if no allocationId)" },
projectCode: { type: "string", description: "Project short code (partial match, used if no allocationId)" },
startDate: { type: "string", description: "Start date filter YYYY-MM-DD (used if no allocationId)" },
newStatus: { type: "string", description: "New status: PROPOSED, CONFIRMED, ACTIVE, COMPLETED, CANCELLED" },
{
type: "function",
function: {
name: "cancel_allocation",
description:
"Cancel an existing allocation. Can find by allocation ID, or by resource name + project code + date range. Requires manageAllocations permission. Always confirm with the user before calling this.",
parameters: {
type: "object",
properties: {
allocationId: { type: "string", description: "Allocation ID (if known)" },
resourceName: { type: "string", description: "Resource name (partial match)" },
projectCode: { type: "string", description: "Project short code (partial match)" },
startDate: { type: "string", description: "Filter by start date YYYY-MM-DD" },
endDate: { type: "string", description: "Filter by end date YYYY-MM-DD" },
},
},
required: ["newStatus"],
},
},
{
type: "function",
function: {
name: "update_allocation_status",
description:
"Change the status of an existing allocation. Can reactivate cancelled allocations, confirm proposed ones, etc. Requires manageAllocations permission. Always confirm with the user before calling.",
parameters: {
type: "object",
properties: {
allocationId: { type: "string", description: "Allocation ID" },
resourceName: {
type: "string",
description: "Resource name (partial match, used if no allocationId)",
},
projectCode: {
type: "string",
description: "Project short code (partial match, used if no allocationId)",
},
startDate: {
type: "string",
description: "Start date filter YYYY-MM-DD (used if no allocationId)",
},
newStatus: {
type: "string",
description: "New status: PROPOSED, CONFIRMED, ACTIVE, COMPLETED, CANCELLED",
},
},
required: ["newStatus"],
},
},
},
],
{
create_allocation: {
requiredPermissions: [PermissionKey.MANAGE_ALLOCATIONS],
},
cancel_allocation: {
requiredPermissions: [PermissionKey.MANAGE_ALLOCATIONS],
},
update_allocation_status: {
requiredPermissions: [PermissionKey.MANAGE_ALLOCATIONS],
},
},
], {
create_allocation: {
requiredPermissions: [PermissionKey.MANAGE_ALLOCATIONS],
},
cancel_allocation: {
requiredPermissions: [PermissionKey.MANAGE_ALLOCATIONS],
},
update_allocation_status: {
requiredPermissions: [PermissionKey.MANAGE_ALLOCATIONS],
},
});
);
export function createAllocationPlanningExecutors(
deps: AllocationPlanningDeps,
): Record<string, ToolExecutor> {
return {
async list_allocations(params: {
resourceId?: string;
projectId?: string;
resourceName?: string;
projectCode?: string;
status?: string;
limit?: number;
}, ctx: ToolContext) {
async list_allocations(
params: {
resourceId?: string;
projectId?: string;
resourceName?: string;
projectCode?: string;
status?: string;
limit?: number;
},
ctx: ToolContext,
) {
const caller = deps.createAllocationCaller(deps.createScopedCallerContext(ctx));
const status = params.status && Object.values(AllocationStatus).includes(params.status as AllocationStatus)
? params.status as AllocationStatus
: undefined;
const status =
params.status && Object.values(AllocationStatus).includes(params.status as AllocationStatus)
? (params.status as AllocationStatus)
: undefined;
const readModel = await caller.listView({
...(params.resourceId ? { resourceId: params.resourceId } : {}),
...(params.projectId ? { projectId: params.projectId } : {}),
@@ -243,14 +279,14 @@ export function createAllocationPlanningExecutors(
return readModel.assignments
.filter((assignment) => {
if (
resourceNameQuery
&& !assignment.resource?.displayName?.toLowerCase().includes(resourceNameQuery)
resourceNameQuery &&
!assignment.resource?.displayName?.toLowerCase().includes(resourceNameQuery)
) {
return false;
}
if (
projectCodeQuery
&& !assignment.project?.shortCode?.toLowerCase().includes(projectCodeQuery)
projectCodeQuery &&
!assignment.project?.shortCode?.toLowerCase().includes(projectCodeQuery)
) {
return false;
}
@@ -304,14 +340,17 @@ export function createAllocationPlanningExecutors(
};
},
async create_allocation(params: {
resourceId: string;
projectId: string;
startDate: string;
endDate: string;
hoursPerDay: number;
role?: string;
}, ctx: ToolContext) {
async create_allocation(
params: {
resourceId: string;
projectId: string;
startDate: string;
endDate: string;
hoursPerDay: number;
role?: string;
},
ctx: ToolContext,
) {
deps.assertPermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
const [resource, project] = await Promise.all([
deps.resolveResourceIdentifier(ctx, params.resourceId),
@@ -345,19 +384,25 @@ export function createAllocationPlanningExecutors(
};
} catch (error) {
if (error instanceof TRPCError && error.code === "CONFLICT") {
return { error: "Allocation already exists for this resource/project/dates. No new allocation created." };
return {
error:
"Allocation already exists for this resource/project/dates. No new allocation created.",
};
}
throw error;
}
},
async cancel_allocation(params: {
allocationId?: string;
resourceName?: string;
projectCode?: string;
startDate?: string;
endDate?: string;
}, ctx: ToolContext) {
async cancel_allocation(
params: {
allocationId?: string;
resourceName?: string;
projectCode?: string;
startDate?: string;
endDate?: string;
},
ctx: ToolContext,
) {
deps.assertPermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
const caller = deps.createAllocationCaller(deps.createScopedCallerContext(ctx));
@@ -420,13 +465,16 @@ export function createAllocationPlanningExecutors(
};
},
async update_allocation_status(params: {
allocationId?: string;
resourceName?: string;
projectCode?: string;
startDate?: string;
newStatus: string;
}, ctx: ToolContext) {
async update_allocation_status(
params: {
allocationId?: string;
resourceName?: string;
projectCode?: string;
startDate?: string;
newStatus: string;
},
ctx: ToolContext,
) {
deps.assertPermission(ctx, PermissionKey.MANAGE_ALLOCATIONS);
const validStatuses = ["PROPOSED", "CONFIRMED", "ACTIVE", "COMPLETED", "CANCELLED"];