Something went wrong. Try again.
A functional toolkit for authoring resource-leveling algorithms — compose constraint and scoring blocks, enumerate feasible schedules
Something went wrong. Try again.
2.4 kB · 57 lines
TypeScript
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758// Coded run issues — spaCy's "errors are a product surface" applied to the// leveling pipeline. Every issue has a stable code (searchable, testable,// documentable) and an actionable message. E-codes are errors that make a// run invalid; W-codes are warnings a run can proceed under.
export type RunIssueCode = /** A constraint or scorer references a resourceUniqueId not in the project. */ | "LEVELSET_E101" /** A constraint or scorer references a taskUniqueId not in the project. */ | "LEVELSET_E102" /** A constraint or scorer references a work-unit id not in ResolvedProject.workUnits. */ | "LEVELSET_E103" /** A task's Deadline is earlier than its Release — no feasible placement. */ | "LEVELSET_E104" /** A task's Deadline is closer than its duration — no feasible placement. */ | "LEVELSET_E105" /** UnitPrecedence constraints form a cycle. */ | "LEVELSET_E106" /** Precedence edges (project + constraints) form a cycle. */ | "LEVELSET_E107" /** A PeakCap window is empty or inverted (fromDay >= toDay). */ | "LEVELSET_E108" /** A Calendars constraint references a calendar not in the project. */ | "LEVELSET_E109" /** A CrewBorrow task has no static assignment on its declared home resource. */ | "LEVELSET_E110" /** More than one mode-producing policy governs the same task. */ | "LEVELSET_E111" /** A constraint kind the chosen search records but does not enforce. */ | "LEVELSET_W201" /** A constraint governs an empty set (no units/modes/edges) — it can never bind. */ | "LEVELSET_W202" /** Two constraint instances share an explicit name — attribution is ambiguous. */ | "LEVELSET_W203";
export interface RunIssue { readonly code: RunIssueCode; readonly severity: "error" | "warning"; /** The named instance the issue attributes to (constraintLabel / scorer * name), or "run" for whole-run issues. */ readonly source: string; readonly message: string;}
export class RunAnalysisError extends Error { readonly issues: readonly RunIssue[];
constructor(issues: readonly RunIssue[]) { const errors = issues.filter((i) => i.severity === "error"); super( `Run analysis found ${String(errors.length)} error(s):\n` + errors.map((i) => `- [${i.code}] ${i.source}: ${i.message}`).join("\n"), ); this.name = "RunAnalysisError"; this.issues = issues; }}