dabke 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/LICENSE +21 -0
  3. package/README.md +187 -0
  4. package/dist/client.d.ts +14 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +42 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/client.schemas.d.ts +250 -0
  9. package/dist/client.schemas.d.ts.map +1 -0
  10. package/dist/client.schemas.js +137 -0
  11. package/dist/client.schemas.js.map +1 -0
  12. package/dist/client.types.d.ts +34 -0
  13. package/dist/client.types.d.ts.map +1 -0
  14. package/dist/client.types.js +18 -0
  15. package/dist/client.types.js.map +1 -0
  16. package/dist/cpsat/model-builder.d.ts +128 -0
  17. package/dist/cpsat/model-builder.d.ts.map +1 -0
  18. package/dist/cpsat/model-builder.js +640 -0
  19. package/dist/cpsat/model-builder.js.map +1 -0
  20. package/dist/cpsat/response.d.ts +74 -0
  21. package/dist/cpsat/response.d.ts.map +1 -0
  22. package/dist/cpsat/response.js +92 -0
  23. package/dist/cpsat/response.js.map +1 -0
  24. package/dist/cpsat/rules/assign-together.d.ts +23 -0
  25. package/dist/cpsat/rules/assign-together.d.ts.map +1 -0
  26. package/dist/cpsat/rules/assign-together.js +78 -0
  27. package/dist/cpsat/rules/assign-together.js.map +1 -0
  28. package/dist/cpsat/rules/employee-assignment-priority.d.ts +64 -0
  29. package/dist/cpsat/rules/employee-assignment-priority.d.ts.map +1 -0
  30. package/dist/cpsat/rules/employee-assignment-priority.js +151 -0
  31. package/dist/cpsat/rules/employee-assignment-priority.js.map +1 -0
  32. package/dist/cpsat/rules/index.d.ts +13 -0
  33. package/dist/cpsat/rules/index.d.ts.map +1 -0
  34. package/dist/cpsat/rules/index.js +13 -0
  35. package/dist/cpsat/rules/index.js.map +1 -0
  36. package/dist/cpsat/rules/location-preference.d.ts +29 -0
  37. package/dist/cpsat/rules/location-preference.d.ts.map +1 -0
  38. package/dist/cpsat/rules/location-preference.js +59 -0
  39. package/dist/cpsat/rules/location-preference.js.map +1 -0
  40. package/dist/cpsat/rules/max-consecutive-days.d.ts +28 -0
  41. package/dist/cpsat/rules/max-consecutive-days.d.ts.map +1 -0
  42. package/dist/cpsat/rules/max-consecutive-days.js +70 -0
  43. package/dist/cpsat/rules/max-consecutive-days.js.map +1 -0
  44. package/dist/cpsat/rules/max-hours-day.d.ts +57 -0
  45. package/dist/cpsat/rules/max-hours-day.d.ts.map +1 -0
  46. package/dist/cpsat/rules/max-hours-day.js +159 -0
  47. package/dist/cpsat/rules/max-hours-day.js.map +1 -0
  48. package/dist/cpsat/rules/max-hours-week.d.ts +62 -0
  49. package/dist/cpsat/rules/max-hours-week.d.ts.map +1 -0
  50. package/dist/cpsat/rules/max-hours-week.js +169 -0
  51. package/dist/cpsat/rules/max-hours-week.js.map +1 -0
  52. package/dist/cpsat/rules/max-shifts-day.d.ts +69 -0
  53. package/dist/cpsat/rules/max-shifts-day.d.ts.map +1 -0
  54. package/dist/cpsat/rules/max-shifts-day.js +170 -0
  55. package/dist/cpsat/rules/max-shifts-day.js.map +1 -0
  56. package/dist/cpsat/rules/min-consecutive-days.d.ts +29 -0
  57. package/dist/cpsat/rules/min-consecutive-days.d.ts.map +1 -0
  58. package/dist/cpsat/rules/min-consecutive-days.js +104 -0
  59. package/dist/cpsat/rules/min-consecutive-days.js.map +1 -0
  60. package/dist/cpsat/rules/min-hours-day.d.ts +28 -0
  61. package/dist/cpsat/rules/min-hours-day.d.ts.map +1 -0
  62. package/dist/cpsat/rules/min-hours-day.js +61 -0
  63. package/dist/cpsat/rules/min-hours-day.js.map +1 -0
  64. package/dist/cpsat/rules/min-hours-week.d.ts +29 -0
  65. package/dist/cpsat/rules/min-hours-week.d.ts.map +1 -0
  66. package/dist/cpsat/rules/min-hours-week.js +68 -0
  67. package/dist/cpsat/rules/min-hours-week.js.map +1 -0
  68. package/dist/cpsat/rules/min-rest-between-shifts.d.ts +28 -0
  69. package/dist/cpsat/rules/min-rest-between-shifts.d.ts.map +1 -0
  70. package/dist/cpsat/rules/min-rest-between-shifts.js +95 -0
  71. package/dist/cpsat/rules/min-rest-between-shifts.js.map +1 -0
  72. package/dist/cpsat/rules/registry.d.ts +7 -0
  73. package/dist/cpsat/rules/registry.d.ts.map +1 -0
  74. package/dist/cpsat/rules/registry.js +28 -0
  75. package/dist/cpsat/rules/registry.js.map +1 -0
  76. package/dist/cpsat/rules/resolver.d.ts +31 -0
  77. package/dist/cpsat/rules/resolver.d.ts.map +1 -0
  78. package/dist/cpsat/rules/resolver.js +124 -0
  79. package/dist/cpsat/rules/resolver.js.map +1 -0
  80. package/dist/cpsat/rules/rules.types.d.ts +32 -0
  81. package/dist/cpsat/rules/rules.types.d.ts.map +1 -0
  82. package/dist/cpsat/rules/rules.types.js +2 -0
  83. package/dist/cpsat/rules/rules.types.js.map +1 -0
  84. package/dist/cpsat/rules/scoping.d.ts +129 -0
  85. package/dist/cpsat/rules/scoping.d.ts.map +1 -0
  86. package/dist/cpsat/rules/scoping.js +190 -0
  87. package/dist/cpsat/rules/scoping.js.map +1 -0
  88. package/dist/cpsat/rules/time-off.d.ts +78 -0
  89. package/dist/cpsat/rules/time-off.d.ts.map +1 -0
  90. package/dist/cpsat/rules/time-off.js +261 -0
  91. package/dist/cpsat/rules/time-off.js.map +1 -0
  92. package/dist/cpsat/rules.d.ts +5 -0
  93. package/dist/cpsat/rules.d.ts.map +1 -0
  94. package/dist/cpsat/rules.js +4 -0
  95. package/dist/cpsat/rules.js.map +1 -0
  96. package/dist/cpsat/semantic-time.d.ts +198 -0
  97. package/dist/cpsat/semantic-time.d.ts.map +1 -0
  98. package/dist/cpsat/semantic-time.js +222 -0
  99. package/dist/cpsat/semantic-time.js.map +1 -0
  100. package/dist/cpsat/types.d.ts +180 -0
  101. package/dist/cpsat/types.d.ts.map +1 -0
  102. package/dist/cpsat/types.js +2 -0
  103. package/dist/cpsat/types.js.map +1 -0
  104. package/dist/cpsat/utils.d.ts +47 -0
  105. package/dist/cpsat/utils.d.ts.map +1 -0
  106. package/dist/cpsat/utils.js +92 -0
  107. package/dist/cpsat/utils.js.map +1 -0
  108. package/dist/cpsat/validation-reporter.d.ts +54 -0
  109. package/dist/cpsat/validation-reporter.d.ts.map +1 -0
  110. package/dist/cpsat/validation-reporter.js +261 -0
  111. package/dist/cpsat/validation-reporter.js.map +1 -0
  112. package/dist/cpsat/validation.types.d.ts +141 -0
  113. package/dist/cpsat/validation.types.d.ts.map +1 -0
  114. package/dist/cpsat/validation.types.js +14 -0
  115. package/dist/cpsat/validation.types.js.map +1 -0
  116. package/dist/datetime.utils.d.ts +245 -0
  117. package/dist/datetime.utils.d.ts.map +1 -0
  118. package/dist/datetime.utils.js +372 -0
  119. package/dist/datetime.utils.js.map +1 -0
  120. package/dist/errors.d.ts +12 -0
  121. package/dist/errors.d.ts.map +1 -0
  122. package/dist/errors.js +17 -0
  123. package/dist/errors.js.map +1 -0
  124. package/dist/index.d.ts +112 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +116 -0
  127. package/dist/index.js.map +1 -0
  128. package/dist/llms.d.ts +5 -0
  129. package/dist/llms.d.ts.map +1 -0
  130. package/dist/llms.js +8 -0
  131. package/dist/llms.js.map +1 -0
  132. package/dist/testing/index.d.ts +12 -0
  133. package/dist/testing/index.d.ts.map +1 -0
  134. package/dist/testing/index.js +11 -0
  135. package/dist/testing/index.js.map +1 -0
  136. package/dist/testing/solver-container.d.ts +49 -0
  137. package/dist/testing/solver-container.d.ts.map +1 -0
  138. package/dist/testing/solver-container.js +127 -0
  139. package/dist/testing/solver-container.js.map +1 -0
  140. package/dist/types.d.ts +155 -0
  141. package/dist/types.d.ts.map +1 -0
  142. package/dist/types.js +20 -0
  143. package/dist/types.js.map +1 -0
  144. package/dist/validation.d.ts +105 -0
  145. package/dist/validation.d.ts.map +1 -0
  146. package/dist/validation.js +130 -0
  147. package/dist/validation.js.map +1 -0
  148. package/llms.txt +2188 -0
  149. package/package.json +76 -0
  150. package/solver/Dockerfile +31 -0
  151. package/solver/README.md +23 -0
  152. package/solver/pyproject.toml +28 -0
  153. package/solver/src/solver/__init__.py +1 -0
  154. package/solver/src/solver/app.py +24 -0
  155. package/solver/src/solver/models.py +120 -0
  156. package/solver/src/solver/solver.py +359 -0
  157. package/solver/tests/test_solver.py +156 -0
  158. package/solver/uv.lock +661 -0
  159. package/src/client.schemas.ts +163 -0
  160. package/src/client.ts +67 -0
  161. package/src/client.types.ts +66 -0
  162. package/src/cpsat/model-builder.ts +858 -0
  163. package/src/cpsat/response.ts +130 -0
  164. package/src/cpsat/rules/assign-together.ts +96 -0
  165. package/src/cpsat/rules/employee-assignment-priority.ts +182 -0
  166. package/src/cpsat/rules/index.ts +12 -0
  167. package/src/cpsat/rules/location-preference.ts +68 -0
  168. package/src/cpsat/rules/max-consecutive-days.ts +98 -0
  169. package/src/cpsat/rules/max-hours-day.ts +187 -0
  170. package/src/cpsat/rules/max-hours-week.ts +197 -0
  171. package/src/cpsat/rules/max-shifts-day.ts +198 -0
  172. package/src/cpsat/rules/min-consecutive-days.ts +140 -0
  173. package/src/cpsat/rules/min-hours-day.ts +69 -0
  174. package/src/cpsat/rules/min-hours-week.ts +77 -0
  175. package/src/cpsat/rules/min-rest-between-shifts.ts +121 -0
  176. package/src/cpsat/rules/registry.ts +49 -0
  177. package/src/cpsat/rules/resolver.ts +181 -0
  178. package/src/cpsat/rules/rules.types.ts +41 -0
  179. package/src/cpsat/rules/scoping.ts +340 -0
  180. package/src/cpsat/rules/time-off.ts +336 -0
  181. package/src/cpsat/rules.ts +27 -0
  182. package/src/cpsat/semantic-time.ts +463 -0
  183. package/src/cpsat/types.ts +194 -0
  184. package/src/cpsat/utils.ts +105 -0
  185. package/src/cpsat/validation-reporter.ts +366 -0
  186. package/src/cpsat/validation.types.ts +185 -0
  187. package/src/datetime.utils.ts +426 -0
  188. package/src/errors.ts +17 -0
  189. package/src/index.ts +289 -0
  190. package/src/llms.ts +9 -0
  191. package/src/testing/index.ts +12 -0
  192. package/src/testing/solver-container.ts +172 -0
  193. package/src/types.ts +191 -0
  194. package/src/validation.ts +188 -0
@@ -0,0 +1,47 @@
1
+ import type { DayOfWeek, TimeOfDay } from "../types.js";
2
+ import type { Priority } from "./types.js";
3
+ export declare const MINUTES_PER_DAY: number;
4
+ /**
5
+ * Standard objective weights for the scheduling solver.
6
+ *
7
+ * These weights define the relative importance of different objectives.
8
+ * Higher weights mean stronger preference. Rules can use these as reference
9
+ * points when adding their own penalties.
10
+ *
11
+ * Weight hierarchy (highest to lowest priority):
12
+ * - SHIFT_ACTIVE (1000): Minimize number of active shift patterns
13
+ * - ASSIGNMENT_PREFERENCE (10): Per-assignment preference (e.g., prefer permanent staff)
14
+ * - FAIRNESS (5): Fair distribution of shifts across team members
15
+ * - ASSIGNMENT_BASE (1): Tiebreaker - minimize total assignments
16
+ *
17
+ * @example Using weights in a custom rule
18
+ * ```ts
19
+ * import { OBJECTIVE_WEIGHTS } from "feasible";
20
+ *
21
+ * // Prefer senior staff with same weight as employee-assignment-priority
22
+ * b.addPenalty(assignment, -OBJECTIVE_WEIGHTS.ASSIGNMENT_PREFERENCE);
23
+ *
24
+ * // Strong preference (2x normal)
25
+ * b.addPenalty(assignment, -2 * OBJECTIVE_WEIGHTS.ASSIGNMENT_PREFERENCE);
26
+ * ```
27
+ */
28
+ export declare const OBJECTIVE_WEIGHTS: {
29
+ /** Weight for minimizing active shift patterns (reduces fragmentation) */
30
+ readonly SHIFT_ACTIVE: 1000;
31
+ /** Weight for per-assignment preferences (e.g., prefer/avoid certain team members) */
32
+ readonly ASSIGNMENT_PREFERENCE: 10;
33
+ /** Weight for fair distribution objective (minimizes max shifts per employee) */
34
+ readonly FAIRNESS: 5;
35
+ /** Base weight per assignment (tiebreaker) */
36
+ readonly ASSIGNMENT_BASE: 1;
37
+ };
38
+ /**
39
+ * Parse a day string (YYYY-MM-DD) to a UTC Date.
40
+ * Used internally for day-of-week calculations and date comparisons.
41
+ */
42
+ export declare function parseDayString(day: string): Date;
43
+ export declare function timeOfDayToMinutes(time: TimeOfDay): number;
44
+ export declare function normalizeEndMinutes(startMinutes: number, endMinutes: number): number;
45
+ export declare function priorityToPenalty(priority: Priority): number;
46
+ export declare function splitIntoWeeks(days: string[], weekStartsOn: DayOfWeek): string[][];
47
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/cpsat/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,eAAe,QAAU,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,iBAAiB;IAC5B,0EAA0E;;IAE1E,sFAAsF;;IAEtF,iFAAiF;;IAEjF,8CAA8C;;CAEtC,CAAC;AAEX;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGpF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAa5D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,SAAS,GAAG,MAAM,EAAE,EAAE,CA+BlF"}
@@ -0,0 +1,92 @@
1
+ import { DAY_OF_WEEK_MAP } from "../datetime.utils.js";
2
+ export const MINUTES_PER_DAY = 24 * 60;
3
+ /**
4
+ * Standard objective weights for the scheduling solver.
5
+ *
6
+ * These weights define the relative importance of different objectives.
7
+ * Higher weights mean stronger preference. Rules can use these as reference
8
+ * points when adding their own penalties.
9
+ *
10
+ * Weight hierarchy (highest to lowest priority):
11
+ * - SHIFT_ACTIVE (1000): Minimize number of active shift patterns
12
+ * - ASSIGNMENT_PREFERENCE (10): Per-assignment preference (e.g., prefer permanent staff)
13
+ * - FAIRNESS (5): Fair distribution of shifts across team members
14
+ * - ASSIGNMENT_BASE (1): Tiebreaker - minimize total assignments
15
+ *
16
+ * @example Using weights in a custom rule
17
+ * ```ts
18
+ * import { OBJECTIVE_WEIGHTS } from "feasible";
19
+ *
20
+ * // Prefer senior staff with same weight as employee-assignment-priority
21
+ * b.addPenalty(assignment, -OBJECTIVE_WEIGHTS.ASSIGNMENT_PREFERENCE);
22
+ *
23
+ * // Strong preference (2x normal)
24
+ * b.addPenalty(assignment, -2 * OBJECTIVE_WEIGHTS.ASSIGNMENT_PREFERENCE);
25
+ * ```
26
+ */
27
+ export const OBJECTIVE_WEIGHTS = {
28
+ /** Weight for minimizing active shift patterns (reduces fragmentation) */
29
+ SHIFT_ACTIVE: 1000,
30
+ /** Weight for per-assignment preferences (e.g., prefer/avoid certain team members) */
31
+ ASSIGNMENT_PREFERENCE: 10,
32
+ /** Weight for fair distribution objective (minimizes max shifts per employee) */
33
+ FAIRNESS: 5,
34
+ /** Base weight per assignment (tiebreaker) */
35
+ ASSIGNMENT_BASE: 1,
36
+ };
37
+ /**
38
+ * Parse a day string (YYYY-MM-DD) to a UTC Date.
39
+ * Used internally for day-of-week calculations and date comparisons.
40
+ */
41
+ export function parseDayString(day) {
42
+ return new Date(`${day}T00:00:00Z`);
43
+ }
44
+ export function timeOfDayToMinutes(time) {
45
+ return time.hours * 60 + (time.minutes ?? 0);
46
+ }
47
+ export function normalizeEndMinutes(startMinutes, endMinutes) {
48
+ if (endMinutes === startMinutes)
49
+ return endMinutes + MINUTES_PER_DAY;
50
+ return endMinutes < startMinutes ? endMinutes + MINUTES_PER_DAY : endMinutes;
51
+ }
52
+ export function priorityToPenalty(priority) {
53
+ switch (priority) {
54
+ case "HIGH":
55
+ return 25;
56
+ case "MEDIUM":
57
+ return 10;
58
+ case "LOW":
59
+ return 1;
60
+ case "MANDATORY":
61
+ return 0;
62
+ default:
63
+ return 0;
64
+ }
65
+ }
66
+ export function splitIntoWeeks(days, weekStartsOn) {
67
+ if (days.length === 0)
68
+ return [];
69
+ const weekStartIndex = DAY_OF_WEEK_MAP[weekStartsOn];
70
+ const result = [];
71
+ let currentWeek = [];
72
+ let currentWeekStart = null;
73
+ for (const day of days) {
74
+ const date = parseDayString(day);
75
+ const isWeekStartDay = date.getUTCDay() === weekStartIndex;
76
+ const isNewWeek = isWeekStartDay && currentWeekStart !== null && date.getTime() !== currentWeekStart.getTime();
77
+ if (isNewWeek) {
78
+ result.push(currentWeek);
79
+ currentWeek = [];
80
+ currentWeekStart = null;
81
+ }
82
+ if (currentWeekStart === null) {
83
+ currentWeekStart = date;
84
+ }
85
+ currentWeek.push(day);
86
+ }
87
+ if (currentWeek.length > 0) {
88
+ result.push(currentWeek);
89
+ }
90
+ return result;
91
+ }
92
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cpsat/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAIvD,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,0EAA0E;IAC1E,YAAY,EAAE,IAAI;IAClB,sFAAsF;IACtF,qBAAqB,EAAE,EAAE;IACzB,iFAAiF;IACjF,QAAQ,EAAE,CAAC;IACX,8CAA8C;IAC9C,eAAe,EAAE,CAAC;CACV,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,IAAI,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAe;IAChD,OAAO,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,YAAoB,EAAE,UAAkB;IAC1E,IAAI,UAAU,KAAK,YAAY;QAAE,OAAO,UAAU,GAAG,eAAe,CAAC;IACrE,OAAO,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,UAAU,GAAG,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAkB;IAClD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,OAAO,EAAE,CAAC;QACZ,KAAK,QAAQ;YACX,OAAO,EAAE,CAAC;QACZ,KAAK,KAAK;YACR,OAAO,CAAC,CAAC;QACX,KAAK,WAAW;YACd,OAAO,CAAC,CAAC;QACX;YACE,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,YAAuB;IACpE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,MAAM,cAAc,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAI,WAAW,GAAa,EAAE,CAAC;IAC/B,IAAI,gBAAgB,GAAgB,IAAI,CAAC;IAEzC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,cAAc,CAAC;QAC3D,MAAM,SAAS,GACb,cAAc,IAAI,gBAAgB,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAE/F,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACzB,WAAW,GAAG,EAAE,CAAC;YACjB,gBAAgB,GAAG,IAAI,CAAC;QAC1B,CAAC;QAED,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAC9B,gBAAgB,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,54 @@
1
+ import type { SolverResponse } from "../client.types.js";
2
+ import { type ScheduleValidation, type TrackedConstraint, type CoverageError, type CoverageViolation, type CoveragePassed, type RuleError, type RuleViolation, type RulePassed, type CoverageExclusion, type ValidationSummary } from "./validation.types.js";
3
+ export interface ValidationReporter {
4
+ excludeFromCoverage(exclusion: CoverageExclusion): void;
5
+ reportCoverageError(error: Omit<CoverageError, "type" | "id">): void;
6
+ reportRuleError(error: Omit<RuleError, "type" | "id">): void;
7
+ reportSolverError(reason: string): void;
8
+ reportCoverageViolation(violation: Omit<CoverageViolation, "type" | "id">): void;
9
+ reportRuleViolation(violation: Omit<RuleViolation, "type" | "id">): void;
10
+ reportCoveragePassed(passed: Omit<CoveragePassed, "type" | "id">): void;
11
+ reportRulePassed(passed: Omit<RulePassed, "type" | "id">): void;
12
+ trackConstraint(constraint: TrackedConstraint): void;
13
+ hasErrors(): boolean;
14
+ getValidation(): ScheduleValidation;
15
+ getExclusions(): CoverageExclusion[];
16
+ analyzeSolution(response: SolverResponse): void;
17
+ }
18
+ export declare class ValidationReporterImpl implements ValidationReporter {
19
+ #private;
20
+ excludeFromCoverage(exclusion: CoverageExclusion): void;
21
+ reportCoverageError(error: Omit<CoverageError, "type" | "id">): void;
22
+ reportRuleError(error: Omit<RuleError, "type" | "id">): void;
23
+ reportSolverError(reason: string): void;
24
+ reportCoverageViolation(violation: Omit<CoverageViolation, "type" | "id">): void;
25
+ reportRuleViolation(violation: Omit<RuleViolation, "type" | "id">): void;
26
+ reportCoveragePassed(passed: Omit<CoveragePassed, "type" | "id">): void;
27
+ reportRulePassed(passed: Omit<RulePassed, "type" | "id">): void;
28
+ getExclusions(): CoverageExclusion[];
29
+ trackConstraint(constraint: TrackedConstraint): void;
30
+ hasErrors(): boolean;
31
+ getValidation(): ScheduleValidation;
32
+ getTrackedConstraints(): TrackedConstraint[];
33
+ analyzeSolution(response: SolverResponse): void;
34
+ }
35
+ /**
36
+ * Aggregates validation items by their groupKey into summaries.
37
+ * This is a pure function that doesn't modify the input.
38
+ *
39
+ * Items without a groupKey are grouped by their ID (ungrouped).
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const validation = reporter.getValidation();
44
+ * const summaries = summarizeValidation(validation);
45
+ * // summaries[0] = {
46
+ * // groupKey: "2x waiter during lunch",
47
+ * // status: "passed",
48
+ * // passedCount: 180,
49
+ * // days: ["2026-02-02", "2026-02-03", ...]
50
+ * // }
51
+ * ```
52
+ */
53
+ export declare function summarizeValidation(validation: ScheduleValidation): readonly ValidationSummary[];
54
+ //# sourceMappingURL=validation-reporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-reporter.d.ts","sourceRoot":"","sources":["../../src/cpsat/validation-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EAEvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,kBAAkB;IAEjC,mBAAmB,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAGxD,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACrE,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7D,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAGxC,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACjF,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAGzE,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACxE,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAGhE,eAAe,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAGrD,SAAS,IAAI,OAAO,CAAC;IACrB,aAAa,IAAI,kBAAkB,CAAC;IACpC,aAAa,IAAI,iBAAiB,EAAE,CAAC;IAGrC,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CACjD;AA2CD,qBAAa,sBAAuB,YAAW,kBAAkB;;IAQ/D,mBAAmB,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAIvD,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI;IAKpE,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI;IAK5D,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMvC,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI;IAWhF,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI;IAKxE,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI;IAKvE,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI;IAK/D,aAAa,IAAI,iBAAiB,EAAE;IAIpC,eAAe,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI;IAIpD,SAAS,IAAI,OAAO;IAIpB,aAAa,IAAI,kBAAkB;IAQnC,qBAAqB,IAAI,iBAAiB,EAAE;IAI5C,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;CAiEhD;AAQD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,kBAAkB,GAAG,SAAS,iBAAiB,EAAE,CAgFhG"}
@@ -0,0 +1,261 @@
1
+ import { groupKey, } from "./validation.types.js";
2
+ /**
3
+ * Generates a deterministic ID for a coverage-based validation item.
4
+ * Format: {category}:coverage:{day}:{timeSlots}:{roleIds}:{skillIds}
5
+ */
6
+ function coverageId(category, day, timeSlots, roleIds, skillIds) {
7
+ const parts = [
8
+ category,
9
+ "coverage",
10
+ day,
11
+ [...timeSlots].toSorted().join(",") || "_",
12
+ roleIds && roleIds.length > 0 ? [...roleIds].toSorted().join(",") : "_",
13
+ skillIds ? [...skillIds].toSorted().join(",") : "_",
14
+ ];
15
+ return parts.join(":");
16
+ }
17
+ /**
18
+ * Generates a deterministic ID for a rule-based validation item.
19
+ * Format: {category}:rule:{rule}:{days}:{employeeIds}
20
+ */
21
+ function ruleId(category, rule, context) {
22
+ const parts = [
23
+ category,
24
+ "rule",
25
+ rule,
26
+ context.days ? [...context.days].toSorted().join(",") : "_",
27
+ context.employeeIds ? [...context.employeeIds].toSorted().join(",") : "_",
28
+ ];
29
+ return parts.join(":");
30
+ }
31
+ export class ValidationReporterImpl {
32
+ #errors = [];
33
+ #violations = [];
34
+ #passed = [];
35
+ #trackedConstraints = new Map();
36
+ #exclusions = [];
37
+ #solverErrorCount = 0;
38
+ excludeFromCoverage(exclusion) {
39
+ this.#exclusions.push(exclusion);
40
+ }
41
+ reportCoverageError(error) {
42
+ const id = coverageId("error", error.day, error.timeSlots, error.roleIds, error.skillIds);
43
+ this.#errors.push({ id, type: "coverage", ...error });
44
+ }
45
+ reportRuleError(error) {
46
+ const id = ruleId("error", error.rule, error.context);
47
+ this.#errors.push({ id, type: "rule", ...error });
48
+ }
49
+ reportSolverError(reason) {
50
+ this.#solverErrorCount++;
51
+ const id = `error:solver:${this.#solverErrorCount}`;
52
+ this.#errors.push({ id, type: "solver", reason });
53
+ }
54
+ reportCoverageViolation(violation) {
55
+ const id = coverageId("violation", violation.day, violation.timeSlots, violation.roleIds, violation.skillIds);
56
+ this.#violations.push({ id, type: "coverage", ...violation });
57
+ }
58
+ reportRuleViolation(violation) {
59
+ const id = ruleId("violation", violation.rule, violation.context);
60
+ this.#violations.push({ id, type: "rule", ...violation });
61
+ }
62
+ reportCoveragePassed(passed) {
63
+ const id = coverageId("passed", passed.day, passed.timeSlots, passed.roleIds, passed.skillIds);
64
+ this.#passed.push({ id, type: "coverage", ...passed });
65
+ }
66
+ reportRulePassed(passed) {
67
+ const id = ruleId("passed", passed.rule, passed.context);
68
+ this.#passed.push({ id, type: "rule", ...passed });
69
+ }
70
+ getExclusions() {
71
+ return [...this.#exclusions];
72
+ }
73
+ trackConstraint(constraint) {
74
+ this.#trackedConstraints.set(constraint.id, constraint);
75
+ }
76
+ hasErrors() {
77
+ return this.#errors.length > 0;
78
+ }
79
+ getValidation() {
80
+ return {
81
+ errors: [...this.#errors],
82
+ violations: [...this.#violations],
83
+ passed: [...this.#passed],
84
+ };
85
+ }
86
+ getTrackedConstraints() {
87
+ return [...this.#trackedConstraints.values()];
88
+ }
89
+ analyzeSolution(response) {
90
+ if (response.status !== "OPTIMAL" && response.status !== "FEASIBLE") {
91
+ if (response.status === "INFEASIBLE") {
92
+ this.reportSolverError(response.solutionInfo ?? "Schedule is infeasible");
93
+ }
94
+ else if (response.status === "TIMEOUT") {
95
+ this.reportSolverError("Solver timed out");
96
+ }
97
+ else if (response.error) {
98
+ this.reportSolverError(response.error);
99
+ }
100
+ return;
101
+ }
102
+ const solverViolations = response.softViolations ?? [];
103
+ for (const violation of solverViolations) {
104
+ const tracked = this.#trackedConstraints.get(violation.constraintId);
105
+ if (tracked?.type === "coverage") {
106
+ this.reportCoverageViolation({
107
+ day: tracked.day ?? "",
108
+ timeSlots: tracked.timeSlot ? [tracked.timeSlot] : [],
109
+ roleIds: tracked.roleIds,
110
+ skillIds: tracked.skillIds,
111
+ targetCount: violation.targetValue,
112
+ actualCount: violation.actualValue,
113
+ shortfall: violation.violationAmount,
114
+ groupKey: tracked.groupKey,
115
+ });
116
+ }
117
+ else if (tracked?.type === "rule") {
118
+ const isShortfall = tracked.comparator === ">=";
119
+ this.reportRuleViolation({
120
+ rule: tracked.rule ?? "unknown",
121
+ reason: `${tracked.description}: needed ${violation.targetValue}, got ${violation.actualValue}`,
122
+ context: tracked.context,
123
+ shortfall: isShortfall ? violation.violationAmount : undefined,
124
+ overflow: !isShortfall ? violation.violationAmount : undefined,
125
+ groupKey: tracked.groupKey,
126
+ });
127
+ }
128
+ else {
129
+ // Unknown constraint - create generic rule violation
130
+ this.reportRuleViolation({
131
+ rule: "unknown",
132
+ reason: `Constraint ${violation.constraintId} violated by ${violation.violationAmount}`,
133
+ context: {},
134
+ });
135
+ }
136
+ }
137
+ // Mark tracked coverage constraints as passed if not violated
138
+ const violatedIds = new Set(solverViolations.map((v) => v.constraintId));
139
+ for (const tracked of this.#trackedConstraints.values()) {
140
+ if (violatedIds.has(tracked.id))
141
+ continue;
142
+ if (tracked.type === "coverage") {
143
+ this.reportCoveragePassed({
144
+ day: tracked.day ?? "",
145
+ timeSlots: tracked.timeSlot ? [tracked.timeSlot] : [],
146
+ roleIds: tracked.roleIds,
147
+ skillIds: tracked.skillIds,
148
+ description: tracked.description,
149
+ groupKey: tracked.groupKey,
150
+ });
151
+ }
152
+ }
153
+ }
154
+ }
155
+ /**
156
+ * Aggregates validation items by their groupKey into summaries.
157
+ * This is a pure function that doesn't modify the input.
158
+ *
159
+ * Items without a groupKey are grouped by their ID (ungrouped).
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const validation = reporter.getValidation();
164
+ * const summaries = summarizeValidation(validation);
165
+ * // summaries[0] = {
166
+ * // groupKey: "2x waiter during lunch",
167
+ * // status: "passed",
168
+ * // passedCount: 180,
169
+ * // days: ["2026-02-02", "2026-02-03", ...]
170
+ * // }
171
+ * ```
172
+ */
173
+ export function summarizeValidation(validation) {
174
+ const groups = new Map();
175
+ const getOrCreateGroup = (key, type) => {
176
+ if (!groups.has(key)) {
177
+ groups.set(key, {
178
+ type,
179
+ items: [],
180
+ days: new Set(),
181
+ passedCount: 0,
182
+ violatedCount: 0,
183
+ errorCount: 0,
184
+ });
185
+ }
186
+ return groups.get(key);
187
+ };
188
+ // Group passed items
189
+ for (const item of validation.passed) {
190
+ const key = item.groupKey ?? groupKey(`ungrouped:${item.id}`);
191
+ const group = getOrCreateGroup(key, item.type);
192
+ group.items.push(item);
193
+ group.passedCount++;
194
+ if (item.type === "coverage" && item.day) {
195
+ group.days.add(item.day);
196
+ }
197
+ }
198
+ // Group violations
199
+ for (const item of validation.violations) {
200
+ const key = item.groupKey ?? groupKey(`ungrouped:${item.id}`);
201
+ const group = getOrCreateGroup(key, item.type);
202
+ group.items.push(item);
203
+ group.violatedCount++;
204
+ if (item.type === "coverage" && item.day) {
205
+ group.days.add(item.day);
206
+ }
207
+ }
208
+ // Group errors (except solver errors which don't have groupKey)
209
+ for (const item of validation.errors) {
210
+ if (item.type === "solver")
211
+ continue;
212
+ const key = item.groupKey ?? groupKey(`ungrouped:${item.id}`);
213
+ const group = getOrCreateGroup(key, item.type);
214
+ group.items.push(item);
215
+ group.errorCount++;
216
+ if (item.type === "coverage" && item.day) {
217
+ group.days.add(item.day);
218
+ }
219
+ }
220
+ // Build summaries
221
+ const summaries = [];
222
+ for (const [key, group] of groups) {
223
+ const status = group.errorCount > 0 ? "failed" : group.violatedCount > 0 ? "partial" : "passed";
224
+ summaries.push({
225
+ groupKey: key,
226
+ type: group.type,
227
+ description: inferDescription(key, group.items),
228
+ days: [...group.days].sort(),
229
+ status,
230
+ passedCount: group.passedCount,
231
+ violatedCount: group.violatedCount,
232
+ errorCount: group.errorCount,
233
+ });
234
+ }
235
+ return summaries;
236
+ }
237
+ /**
238
+ * Infers a human-readable description from the groupKey or items.
239
+ */
240
+ function inferDescription(key, items) {
241
+ // If the key looks like a human-readable description, use it
242
+ if (!key.startsWith("ungrouped:")) {
243
+ return key;
244
+ }
245
+ // Try to infer from the first item with a description
246
+ for (const item of items) {
247
+ if ("description" in item && item.description) {
248
+ // Extract the meaningful part (e.g., "2x waiter" from "2x waiter on 2026-02-03 at 09:00")
249
+ const match = item.description.match(/^(\d+x \w+)/);
250
+ if (match?.[1]) {
251
+ return match[1];
252
+ }
253
+ return item.description;
254
+ }
255
+ if ("reason" in item && item.reason) {
256
+ return item.reason;
257
+ }
258
+ }
259
+ return key;
260
+ }
261
+ //# sourceMappingURL=validation-reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-reporter.js","sourceRoot":"","sources":["../../src/cpsat/validation-reporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,141 @@
1
+ import type { TimeOfDay } from "../types.js";
2
+ declare const GroupKeyBrand: unique symbol;
3
+ /**
4
+ * Branded type for validation group keys.
5
+ * Groups related validation items that originated from the same instruction.
6
+ */
7
+ export type GroupKey = string & {
8
+ readonly [GroupKeyBrand]: never;
9
+ };
10
+ /**
11
+ * Creates a GroupKey from a description string.
12
+ * Use this to create keys that group related validation items together.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const key = groupKey("2x waiter during lunch");
17
+ * coverage.groupKey = key;
18
+ * ```
19
+ */
20
+ export declare function groupKey(description: string): GroupKey;
21
+ /**
22
+ * Context shared across validation results for grouping/display.
23
+ */
24
+ export interface ValidationContext {
25
+ days?: string[];
26
+ timeSlots?: string[];
27
+ employeeIds?: string[];
28
+ }
29
+ export interface CoverageError {
30
+ readonly id: string;
31
+ readonly type: "coverage";
32
+ readonly day: string;
33
+ readonly timeSlots: readonly string[];
34
+ readonly roleIds?: string[];
35
+ readonly skillIds?: readonly string[];
36
+ readonly reason: string;
37
+ readonly suggestions?: readonly string[];
38
+ readonly groupKey?: GroupKey;
39
+ }
40
+ export interface RuleError {
41
+ readonly id: string;
42
+ readonly type: "rule";
43
+ readonly rule: string;
44
+ readonly reason: string;
45
+ readonly context: ValidationContext;
46
+ readonly suggestions?: readonly string[];
47
+ readonly groupKey?: GroupKey;
48
+ }
49
+ export interface SolverError {
50
+ readonly id: string;
51
+ readonly type: "solver";
52
+ readonly reason: string;
53
+ }
54
+ export type ScheduleError = CoverageError | RuleError | SolverError;
55
+ export interface CoverageViolation {
56
+ readonly id: string;
57
+ readonly type: "coverage";
58
+ readonly day: string;
59
+ readonly timeSlots: readonly string[];
60
+ readonly roleIds?: string[];
61
+ readonly skillIds?: readonly string[];
62
+ readonly targetCount: number;
63
+ readonly actualCount: number;
64
+ readonly shortfall: number;
65
+ readonly groupKey?: GroupKey;
66
+ }
67
+ export interface RuleViolation {
68
+ readonly id: string;
69
+ readonly type: "rule";
70
+ readonly rule: string;
71
+ readonly reason: string;
72
+ readonly context: ValidationContext;
73
+ readonly shortfall?: number;
74
+ readonly overflow?: number;
75
+ readonly groupKey?: GroupKey;
76
+ }
77
+ export type ScheduleViolation = CoverageViolation | RuleViolation;
78
+ export interface CoveragePassed {
79
+ readonly id: string;
80
+ readonly type: "coverage";
81
+ readonly day: string;
82
+ readonly timeSlots: readonly string[];
83
+ readonly roleIds?: string[];
84
+ readonly skillIds?: readonly string[];
85
+ readonly description: string;
86
+ readonly groupKey?: GroupKey;
87
+ }
88
+ export interface RulePassed {
89
+ readonly id: string;
90
+ readonly type: "rule";
91
+ readonly rule: string;
92
+ readonly description: string;
93
+ readonly context: ValidationContext;
94
+ readonly groupKey?: GroupKey;
95
+ }
96
+ export type SchedulePassed = CoveragePassed | RulePassed;
97
+ export interface ScheduleValidation {
98
+ readonly errors: readonly ScheduleError[];
99
+ readonly violations: readonly ScheduleViolation[];
100
+ readonly passed: readonly SchedulePassed[];
101
+ }
102
+ /**
103
+ * Summary of validation items grouped by their source instruction.
104
+ * Use `summarizeValidation()` to create these from a ScheduleValidation.
105
+ */
106
+ export interface ValidationSummary {
107
+ readonly groupKey: GroupKey;
108
+ readonly type: "coverage" | "rule";
109
+ readonly description: string;
110
+ readonly days: readonly string[];
111
+ readonly status: "passed" | "partial" | "failed";
112
+ readonly passedCount: number;
113
+ readonly violatedCount: number;
114
+ readonly errorCount: number;
115
+ }
116
+ export interface TrackedConstraint {
117
+ readonly id: string;
118
+ readonly type: "coverage" | "rule";
119
+ readonly rule?: string;
120
+ readonly description: string;
121
+ readonly targetValue: number;
122
+ readonly comparator: "<=" | ">=";
123
+ readonly day?: string;
124
+ readonly timeSlot?: string;
125
+ readonly roleIds?: string[];
126
+ readonly skillIds?: readonly string[];
127
+ readonly context: ValidationContext;
128
+ readonly groupKey?: GroupKey;
129
+ }
130
+ /**
131
+ * Coverage exclusion - indicates a team member is unavailable for coverage during a time period.
132
+ * Used during compile-time to determine coverage feasibility.
133
+ */
134
+ export interface CoverageExclusion {
135
+ employeeId: string;
136
+ day: string;
137
+ startTime?: TimeOfDay;
138
+ endTime?: TimeOfDay;
139
+ }
140
+ export {};
141
+ //# sourceMappingURL=validation.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.types.d.ts","sourceRoot":"","sources":["../../src/cpsat/validation.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Creates a GroupKey from a description string.
3
+ * Use this to create keys that group related validation items together.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const key = groupKey("2x waiter during lunch");
8
+ * coverage.groupKey = key;
9
+ * ```
10
+ */
11
+ export function groupKey(description) {
12
+ return description;
13
+ }
14
+ //# sourceMappingURL=validation.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.types.js","sourceRoot":"","sources":["../../src/cpsat/validation.types.ts"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CAAC,WAAmB;IAC1C,OAAO,WAAuB,CAAC;AACjC,CAAC"}