@outbuild-company/schedule-core 1.12.0 → 1.13.2

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.
package/dist/index.cjs CHANGED
@@ -1,6 +1,19 @@
1
1
  'use strict';
2
2
 
3
+ // src/activity-types/constants.ts
4
+ var ACTIVITY_TYPE = {
5
+ TASK: "task",
6
+ PROJECT: "project",
7
+ MILESTONE: "milestone"
8
+ };
9
+ var ACTIVITY_TYPES = Object.values(ACTIVITY_TYPE);
10
+ function isActivityType(value) {
11
+ return ACTIVITY_TYPES.includes(value);
12
+ }
13
+
3
14
  // src/types.ts
15
+ var NOTIFICATION_TYPE = {
16
+ CONSTRAINT: "constraint"};
4
17
  var WORK_TIME_DIRECTION = {
5
18
  FUTURE: "future",
6
19
  PAST: "past"
@@ -25,6 +38,11 @@ var STATUS = {
25
38
  WAITING: "Waiting",
26
39
  DOING: "Doing"
27
40
  };
41
+ var ENTITY_CHANGE_KIND = {
42
+ CREATED: "created",
43
+ UPDATED: "updated",
44
+ DELETED: "deleted"
45
+ };
28
46
 
29
47
  // src/constraints/index.ts
30
48
  var CONSTRAINT_TYPE = {
@@ -38,12 +56,12 @@ var CONSTRAINT_TYPE = {
38
56
  MFO: "mfo"
39
57
  };
40
58
  var VIOLATION_RULES = {
41
- mso: () => true,
42
- mfo: () => true,
43
- snlt: (constraint, projected) => constraint < projected,
44
- snet: (constraint, projected) => constraint > projected,
45
- fnlt: (constraint, projected) => constraint < projected,
46
- fnet: (constraint, projected) => constraint > projected
59
+ [CONSTRAINT_TYPE.MSO]: () => true,
60
+ [CONSTRAINT_TYPE.MFO]: () => true,
61
+ [CONSTRAINT_TYPE.SNLT]: (constraint, projected) => constraint < projected,
62
+ [CONSTRAINT_TYPE.SNET]: (constraint, projected) => constraint > projected,
63
+ [CONSTRAINT_TYPE.FNLT]: (constraint, projected) => constraint < projected,
64
+ [CONSTRAINT_TYPE.FNET]: (constraint, projected) => constraint > projected
47
65
  };
48
66
  function checkConstraintViolation(constraintType, constraintDate, projectedDate) {
49
67
  if (!constraintDate) return { violated: false };
@@ -55,16 +73,16 @@ function checkConstraintViolation(constraintType, constraintDate, projectedDate)
55
73
  return { violated: false };
56
74
  }
57
75
  var START_BASED_CONSTRAINTS = /* @__PURE__ */ new Set([
58
- "mso",
59
- "snet",
60
- "snlt"
76
+ CONSTRAINT_TYPE.MSO,
77
+ CONSTRAINT_TYPE.SNET,
78
+ CONSTRAINT_TYPE.SNLT
61
79
  ]);
62
80
  function pickProjectedDateForConstraint(constraintType, projectedStart, projectedEnd) {
63
81
  return START_BASED_CONSTRAINTS.has(constraintType) ? projectedStart : projectedEnd;
64
82
  }
65
83
  function buildConstraintNotification(constraintType, constraintDate, projectedDate) {
66
84
  return {
67
- type: "constraint",
85
+ type: NOTIFICATION_TYPE.CONSTRAINT,
68
86
  messageKey: "constraint_violation",
69
87
  data: {
70
88
  constraintType,
@@ -74,12 +92,30 @@ function buildConstraintNotification(constraintType, constraintDate, projectedDa
74
92
  };
75
93
  }
76
94
  var CONSTRAINT_CASES = {
77
- snet: { startOfDay: true, direction: WORK_TIME_DIRECTION.FUTURE },
78
- snlt: { startOfDay: true, direction: WORK_TIME_DIRECTION.PAST },
79
- fnet: { startOfDay: false, direction: WORK_TIME_DIRECTION.FUTURE },
80
- fnlt: { startOfDay: false, direction: WORK_TIME_DIRECTION.PAST },
81
- mso: { startOfDay: true, direction: WORK_TIME_DIRECTION.FUTURE },
82
- mfo: { startOfDay: false, direction: WORK_TIME_DIRECTION.PAST }
95
+ [CONSTRAINT_TYPE.SNET]: {
96
+ startOfDay: true,
97
+ direction: WORK_TIME_DIRECTION.FUTURE
98
+ },
99
+ [CONSTRAINT_TYPE.SNLT]: {
100
+ startOfDay: true,
101
+ direction: WORK_TIME_DIRECTION.PAST
102
+ },
103
+ [CONSTRAINT_TYPE.FNET]: {
104
+ startOfDay: false,
105
+ direction: WORK_TIME_DIRECTION.FUTURE
106
+ },
107
+ [CONSTRAINT_TYPE.FNLT]: {
108
+ startOfDay: false,
109
+ direction: WORK_TIME_DIRECTION.PAST
110
+ },
111
+ [CONSTRAINT_TYPE.MSO]: {
112
+ startOfDay: true,
113
+ direction: WORK_TIME_DIRECTION.FUTURE
114
+ },
115
+ [CONSTRAINT_TYPE.MFO]: {
116
+ startOfDay: false,
117
+ direction: WORK_TIME_DIRECTION.PAST
118
+ }
83
119
  };
84
120
  var startOfUtcDay = (d) => new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
85
121
  var addUtcDays = (d, n) => new Date(d.getTime() + n * 864e5);
@@ -131,7 +167,9 @@ function computeConstraintBounds(activity, adapter) {
131
167
  latestEnd: null
132
168
  };
133
169
  const type = activity.constraintType;
134
- if (!type || type === "asap" || type === "alap") return empty;
170
+ if (!type || type === CONSTRAINT_TYPE.ASAP || type === CONSTRAINT_TYPE.ALAP) {
171
+ return empty;
172
+ }
135
173
  const constraintDate = getEffectiveConstraintDate(activity, adapter);
136
174
  if (!constraintDate) return empty;
137
175
  const endFromStart = (start) => adapter.calculateEndDate({
@@ -145,35 +183,35 @@ function computeConstraintBounds(activity, adapter) {
145
183
  task: activity
146
184
  });
147
185
  switch (type) {
148
- case "snet":
186
+ case CONSTRAINT_TYPE.SNET:
149
187
  return {
150
188
  earliestStart: constraintDate,
151
189
  latestStart: null,
152
190
  earliestEnd: endFromStart(constraintDate),
153
191
  latestEnd: null
154
192
  };
155
- case "snlt":
193
+ case CONSTRAINT_TYPE.SNLT:
156
194
  return {
157
195
  earliestStart: null,
158
196
  latestStart: constraintDate,
159
197
  earliestEnd: null,
160
198
  latestEnd: endFromStart(constraintDate)
161
199
  };
162
- case "fnet":
200
+ case CONSTRAINT_TYPE.FNET:
163
201
  return {
164
202
  earliestStart: startFromEnd(constraintDate),
165
203
  latestStart: null,
166
204
  earliestEnd: constraintDate,
167
205
  latestEnd: null
168
206
  };
169
- case "fnlt":
207
+ case CONSTRAINT_TYPE.FNLT:
170
208
  return {
171
209
  earliestStart: null,
172
210
  latestStart: startFromEnd(constraintDate),
173
211
  earliestEnd: null,
174
212
  latestEnd: constraintDate
175
213
  };
176
- case "mso": {
214
+ case CONSTRAINT_TYPE.MSO: {
177
215
  const end = endFromStart(constraintDate);
178
216
  return {
179
217
  earliestStart: constraintDate,
@@ -182,7 +220,7 @@ function computeConstraintBounds(activity, adapter) {
182
220
  latestEnd: end
183
221
  };
184
222
  }
185
- case "mfo": {
223
+ case CONSTRAINT_TYPE.MFO: {
186
224
  const start = startFromEnd(constraintDate);
187
225
  return {
188
226
  earliestStart: start,
@@ -210,13 +248,17 @@ function clampStartToBounds(candidate, bounds) {
210
248
  return candidate;
211
249
  }
212
250
 
213
- // src/autoscheduler/types.ts
251
+ // src/autoscheduler/links/constants.ts
214
252
  var LINK_TYPE = {
215
253
  FINISH_TO_START: "0",
216
254
  START_TO_START: "1",
217
255
  FINISH_TO_FINISH: "2",
218
256
  START_TO_FINISH: "3"
219
257
  };
258
+ var LINK_TYPES = Object.values(LINK_TYPE);
259
+ function isLinkType(value) {
260
+ return LINK_TYPES.includes(value);
261
+ }
220
262
 
221
263
  // src/constants/columns.ts
222
264
  var EDITABLE = {
@@ -302,6 +344,7 @@ var DISPATCH_ACTION_KIND = {
302
344
  ACTIVITY_INDENT: "activity-indent",
303
345
  ACTIVITY_OUTDENT: "activity-outdent",
304
346
  ACTIVITY_SET_PROGRESS: "activity-set-progress",
347
+ ACTIVITY_LOOKAHEAD_CONVERT: "activity-lookahead-convert",
305
348
  SELECTION_TOGGLE: "selection-toggle",
306
349
  SELECTION_REPLACE: "selection-replace",
307
350
  VISIBILITY_SET: "visibility-set",
@@ -384,14 +427,14 @@ function activityEditToColumnEdit(activityId, edit) {
384
427
  }
385
428
 
386
429
  // src/api/schedule-api.ts
387
- var LINK_TYPES = {
430
+ var LINK_TYPES2 = {
388
431
  [LINK_RELATIONSHIP.FINISH_TO_START]: LINK_TYPE.FINISH_TO_START,
389
432
  [LINK_RELATIONSHIP.START_TO_START]: LINK_TYPE.START_TO_START,
390
433
  [LINK_RELATIONSHIP.FINISH_TO_FINISH]: LINK_TYPE.FINISH_TO_FINISH,
391
434
  [LINK_RELATIONSHIP.START_TO_FINISH]: LINK_TYPE.START_TO_FINISH
392
435
  };
393
436
  function linkType(relationship) {
394
- return LINK_TYPES[relationship];
437
+ return LINK_TYPES2[relationship];
395
438
  }
396
439
  function batchLink(operation) {
397
440
  if (operation.kind === LINK_BATCH_OPERATION_KIND.CREATE) {
@@ -493,6 +536,8 @@ function createActivitiesApi(engine) {
493
536
  { ...input, kind: DISPATCH_ACTION_KIND.ACTIVITY_MOVE },
494
537
  options
495
538
  ),
539
+ planLookaheadConversion: (input) => engine.planLookaheadConversion(input),
540
+ applyLookaheadConversion: (input) => engine.applyLookaheadConversion(input),
496
541
  indent: (activityIds, context = {}) => engine.dispatch({
497
542
  ...context,
498
543
  kind: DISPATCH_ACTION_KIND.ACTIVITY_INDENT,
@@ -671,6 +716,7 @@ function createScheduleNamespaces(engine) {
671
716
  diagnostics: {
672
717
  auditEffectiveGraph: () => engine.auditEffectiveGraph(),
673
718
  revision: () => engine.getScheduleRevision(),
719
+ stateRevision: () => engine.getStateRevision(),
674
720
  canonicalDigest: () => engine.getCanonicalDigest()
675
721
  }
676
722
  };
@@ -822,6 +868,7 @@ var REJECTION_REASON = {
822
868
  OUTDENT_ROOT_LEVEL_NOT_EDITABLE: "outdent_root_level_not_editable",
823
869
  HIERARCHY_CYCLE: "hierarchy_cycle",
824
870
  SANDBOX_PERSISTENCE_FORBIDDEN: "sandbox_persistence_forbidden",
871
+ STALE_STATE_REVISION: "stale-state-revision",
825
872
  INVALID_PROGRESS_VALUE: "invalid_progress_value_must_be_0_or_100"
826
873
  };
827
874
 
@@ -926,11 +973,6 @@ function dispatchVisibilitySet(action, deps) {
926
973
  }
927
974
 
928
975
  // src/autoscheduler/constants.ts
929
- var ACTIVITY_TYPE = {
930
- TASK: "task",
931
- PROJECT: "project",
932
- MILESTONE: "milestone"
933
- };
934
976
  var TIMING = {
935
977
  YIELD_SLICE_MS: 8
936
978
  };
@@ -1973,53 +2015,55 @@ function filterTopoOrder(order, scopedIds) {
1973
2015
  }
1974
2016
 
1975
2017
  // src/activity-types/behavior.ts
2018
+ var PONDERATOR_WEIGHT = {
2019
+ OWN_BASELINE: "own-baseline",
2020
+ RECURSIVE_LEAF_SUM: "recursive-leaf-sum",
2021
+ ZERO: "zero"
2022
+ };
1976
2023
  var ACTIVITY_TYPE_BEHAVIOR = {
1977
- project: {
2024
+ [ACTIVITY_TYPE.PROJECT]: {
1978
2025
  alwaysSummary: true,
1979
2026
  holdsConstraint: false,
1980
2027
  carriesCustomId: false,
1981
2028
  forcedDuration: null,
1982
- ponderatorWeight: "recursive-leaf-sum",
2029
+ ponderatorWeight: PONDERATOR_WEIGHT.RECURSIVE_LEAF_SUM,
1983
2030
  promotesToProjectOnFirstChild: false
1984
2031
  },
1985
- task: {
2032
+ [ACTIVITY_TYPE.TASK]: {
1986
2033
  alwaysSummary: false,
1987
2034
  holdsConstraint: true,
1988
2035
  carriesCustomId: true,
1989
2036
  forcedDuration: null,
1990
- ponderatorWeight: "own-baseline",
2037
+ ponderatorWeight: PONDERATOR_WEIGHT.OWN_BASELINE,
1991
2038
  promotesToProjectOnFirstChild: true
1992
2039
  },
1993
- milestone: {
2040
+ [ACTIVITY_TYPE.MILESTONE]: {
1994
2041
  alwaysSummary: false,
1995
2042
  holdsConstraint: true,
1996
2043
  carriesCustomId: true,
1997
2044
  forcedDuration: 0,
1998
- ponderatorWeight: "zero",
2045
+ ponderatorWeight: PONDERATOR_WEIGHT.ZERO,
1999
2046
  promotesToProjectOnFirstChild: true
2000
2047
  }
2001
2048
  };
2002
2049
 
2003
2050
  // src/activity-types/predicates.ts
2004
- function isActivityType(value) {
2005
- return value === "project" || value === "task" || value === "milestone";
2006
- }
2007
2051
  function isSummary(type, hasChildren) {
2008
2052
  return hasChildren || isActivityType(type) && ACTIVITY_TYPE_BEHAVIOR[type].alwaysSummary;
2009
2053
  }
2010
2054
  function isMilestoneType(type) {
2011
- return type === "milestone";
2055
+ return type === ACTIVITY_TYPE.MILESTONE;
2012
2056
  }
2013
2057
  function isPromotableLeafType(type) {
2014
2058
  return isActivityType(type) && ACTIVITY_TYPE_BEHAVIOR[type].promotesToProjectOnFirstChild;
2015
2059
  }
2016
2060
 
2017
2061
  // src/activity-types/transitions.ts
2018
- var PROMOTION_TARGET_TYPE = "project";
2019
- var DEMOTION_TARGET_TYPE = "task";
2062
+ var PROMOTION_TARGET_TYPE = ACTIVITY_TYPE.PROJECT;
2063
+ var DEMOTION_TARGET_TYPE = ACTIVITY_TYPE.TASK;
2020
2064
  function typeForNewDuration(currentDuration, newDuration) {
2021
- if (newDuration === 0) return "milestone";
2022
- if (currentDuration === 0 && newDuration > 0) return "task";
2065
+ if (newDuration === 0) return ACTIVITY_TYPE.MILESTONE;
2066
+ if (currentDuration === 0 && newDuration > 0) return ACTIVITY_TYPE.TASK;
2023
2067
  return null;
2024
2068
  }
2025
2069
 
@@ -2605,7 +2649,7 @@ function processConstraints(activityIds, adapter, plans) {
2605
2649
  startDate: activity.startDate,
2606
2650
  endDate: activity.endDate,
2607
2651
  drivingLinkId: null,
2608
- kind: "asap",
2652
+ kind: CONSTRAINT_TYPE.ASAP,
2609
2653
  conflict: false,
2610
2654
  earliestStart: bounds.earliestStart,
2611
2655
  latestStart: bounds.latestStart,
@@ -2757,7 +2801,7 @@ async function asapPass(orderedIds, links, adapter, options, isCurrent, plans) {
2757
2801
  startDate: activity.startDate,
2758
2802
  endDate: activity.endDate,
2759
2803
  drivingLinkId: null,
2760
- kind: "asap",
2804
+ kind: CONSTRAINT_TYPE.ASAP,
2761
2805
  conflict: false
2762
2806
  };
2763
2807
  const hasConstraintBounds = plan.earliestStart || plan.latestStart || plan.earliestEnd || plan.latestEnd;
@@ -2961,13 +3005,13 @@ async function alapPass(reversedIds, links, asapPlans, adapter, _options, isCurr
2961
3005
  startDate: snappedStart,
2962
3006
  endDate: snappedEnd,
2963
3007
  drivingLinkId: null,
2964
- kind: "alap",
3008
+ kind: CONSTRAINT_TYPE.ALAP,
2965
3009
  conflict: false
2966
3010
  };
2967
3011
  plan.startDate = snappedStart;
2968
3012
  plan.endDate = snappedEnd;
2969
3013
  plan.drivingLinkId = null;
2970
- plan.kind = "alap";
3014
+ plan.kind = CONSTRAINT_TYPE.ALAP;
2971
3015
  const predecessorFloor = plan.earliestSchedulingStart ?? null;
2972
3016
  plan.earliestSchedulingStart = null;
2973
3017
  plan.earliestSchedulingEnd = null;
@@ -2995,7 +3039,7 @@ var noopReporter = {
2995
3039
  // src/internal/state/calendar-duration.ts
2996
3040
  var CALENDAR_DAY_MS = 864e5;
2997
3041
  function computeCalendarDuration(activity) {
2998
- if (activity.type === "milestone") return 0;
3042
+ if (activity.type === ACTIVITY_TYPE.MILESTONE) return 0;
2999
3043
  const start = activity.startDate?.getTime();
3000
3044
  const end = activity.endDate?.getTime();
3001
3045
  if (start == null || end == null || Number.isNaN(start) || Number.isNaN(end)) {
@@ -3302,8 +3346,12 @@ var ReparentedPort = class {
3302
3346
 
3303
3347
  // src/internal/dependency-graph/effective-graph-validation.ts
3304
3348
  function validateTopologyCommit(input) {
3305
- const { port, currentLinks, proposedLinks, proposal } = input;
3306
- const proposedEdges = projectEffectiveEdges(port, proposedLinks, proposal);
3349
+ const { port, proposedPort, currentLinks, proposedLinks, proposal } = input;
3350
+ const proposedEdges = projectEffectiveEdges(
3351
+ proposedPort ?? port,
3352
+ proposedLinks,
3353
+ proposal
3354
+ );
3307
3355
  if (!hasDirectedCycle(proposedEdges)) return { ok: true };
3308
3356
  const currentEdges = projectEffectiveEdges(port, currentLinks);
3309
3357
  const corruptBefore = corruptActivityIds(currentEdges);
@@ -3513,19 +3561,25 @@ function defaultNewLinkId() {
3513
3561
  }
3514
3562
 
3515
3563
  // src/autoscheduler/links/link-display.ts
3564
+ var LINK_CODE = {
3565
+ FINISH_TO_START: "fs",
3566
+ START_TO_START: "ss",
3567
+ FINISH_TO_FINISH: "ff",
3568
+ START_TO_FINISH: "sf"
3569
+ };
3516
3570
  var LINK_TYPE_CODE = {
3517
- [LINK_TYPE.FINISH_TO_START]: "fs",
3518
- [LINK_TYPE.START_TO_START]: "ss",
3519
- [LINK_TYPE.FINISH_TO_FINISH]: "ff",
3520
- [LINK_TYPE.START_TO_FINISH]: "sf"
3571
+ [LINK_TYPE.FINISH_TO_START]: LINK_CODE.FINISH_TO_START,
3572
+ [LINK_TYPE.START_TO_START]: LINK_CODE.START_TO_START,
3573
+ [LINK_TYPE.FINISH_TO_FINISH]: LINK_CODE.FINISH_TO_FINISH,
3574
+ [LINK_TYPE.START_TO_FINISH]: LINK_CODE.START_TO_FINISH
3521
3575
  };
3522
3576
  var LINK_CODE_TO_TYPE = {
3523
- fs: LINK_TYPE.FINISH_TO_START,
3524
- ss: LINK_TYPE.START_TO_START,
3525
- ff: LINK_TYPE.FINISH_TO_FINISH,
3526
- sf: LINK_TYPE.START_TO_FINISH
3577
+ [LINK_CODE.FINISH_TO_START]: LINK_TYPE.FINISH_TO_START,
3578
+ [LINK_CODE.START_TO_START]: LINK_TYPE.START_TO_START,
3579
+ [LINK_CODE.FINISH_TO_FINISH]: LINK_TYPE.FINISH_TO_FINISH,
3580
+ [LINK_CODE.START_TO_FINISH]: LINK_TYPE.START_TO_FINISH
3527
3581
  };
3528
- var DEFAULT_LINK_CODE = "fs";
3582
+ var DEFAULT_LINK_CODE = LINK_CODE.FINISH_TO_START;
3529
3583
  function parseLinkTypeCode(raw) {
3530
3584
  if (raw in LINK_CODE_TO_TYPE) {
3531
3585
  return LINK_CODE_TO_TYPE[raw];
@@ -3533,33 +3587,53 @@ function parseLinkTypeCode(raw) {
3533
3587
  return void 0;
3534
3588
  }
3535
3589
  var LINK_ENTRY_SEPARATOR = ";";
3536
- var ENTRY_RE = /^(\d+)(fs|ss|ff|sf)?(?:([+-]?)(\d+(?:\.\d+)?)d?)?$/i;
3590
+ var LAG_UNIT = {
3591
+ DAY: "d",
3592
+ WEEK: "w",
3593
+ WEEK_DHTMLX: "wk",
3594
+ MONTH: "m",
3595
+ MONTH_DHTMLX: "mon",
3596
+ YEAR: "y"
3597
+ };
3598
+ var ENTRY_RE = /^(\d+)(fs|ss|ff|sf)?(?:([+-]?)(\d+(?:\.\d+)?)(wk|w|mon|m|d|y)?)?$/i;
3537
3599
 
3538
3600
  // src/autoscheduler/links/parse-predecessor-string.ts
3539
- function parsePredecessorString(input) {
3601
+ var DEFAULT_WORKING_DAYS_PER_WEEK = 5;
3602
+ var DAYS_PER_MONTH = 30;
3603
+ var DAYS_PER_YEAR = 365;
3604
+ var FIXED_UNIT_DAYS = {
3605
+ [LAG_UNIT.DAY]: 1,
3606
+ [LAG_UNIT.MONTH]: DAYS_PER_MONTH,
3607
+ [LAG_UNIT.MONTH_DHTMLX]: DAYS_PER_MONTH,
3608
+ [LAG_UNIT.YEAR]: DAYS_PER_YEAR
3609
+ };
3610
+ function parsePredecessorString(input, options = {}) {
3540
3611
  const specs = [];
3541
3612
  const errors = [];
3613
+ const daysPerWeek = options.daysPerWeek !== void 0 && Number.isFinite(options.daysPerWeek) && options.daysPerWeek > 0 ? options.daysPerWeek : DEFAULT_WORKING_DAYS_PER_WEEK;
3542
3614
  const trimmed = input.replace(/\s+/g, "");
3543
3615
  if (trimmed.length === 0) return { specs, errors };
3544
3616
  for (const raw of trimmed.split(LINK_ENTRY_SEPARATOR)) {
3545
3617
  if (raw.length === 0) continue;
3546
- const spec = parseEntry(raw);
3618
+ const spec = parseEntry(raw, daysPerWeek);
3547
3619
  if (spec) specs.push(spec);
3548
3620
  else errors.push(raw);
3549
3621
  }
3550
3622
  return { specs, errors };
3551
3623
  }
3552
- function parseEntry(entry) {
3624
+ function parseEntry(entry, daysPerWeek) {
3553
3625
  const lower = entry.toLowerCase();
3554
3626
  const match = ENTRY_RE.exec(lower);
3555
3627
  if (!match) return null;
3556
- const [, correlativeId, typeStr, sign, magnitude] = match;
3628
+ const [, correlativeId, typeStr, sign, magnitude, unit] = match;
3557
3629
  const type = typeStr ? LINK_CODE_TO_TYPE[typeStr] : LINK_CODE_TO_TYPE[DEFAULT_LINK_CODE];
3558
3630
  let lag = 0;
3559
3631
  if (magnitude !== void 0) {
3560
3632
  const value = Number(magnitude);
3561
3633
  if (Number.isNaN(value)) return null;
3562
- lag = sign === "-" ? -value : value;
3634
+ const unitDays = unit === LAG_UNIT.WEEK || unit === LAG_UNIT.WEEK_DHTMLX ? daysPerWeek : FIXED_UNIT_DAYS[unit ?? LAG_UNIT.DAY];
3635
+ const days = value * unitDays;
3636
+ lag = sign === "-" ? -days : days;
3563
3637
  }
3564
3638
  return {
3565
3639
  correlativeId,
@@ -3591,20 +3665,24 @@ function diffLinks(input) {
3591
3665
  const operations = [];
3592
3666
  for (const [key, link] of currentByKey) {
3593
3667
  if (!desired.has(key)) {
3594
- operations.push({ kind: "delete", linkId: link.id });
3668
+ operations.push({ kind: LINK_OPERATION_KIND.DELETE, linkId: link.id });
3595
3669
  }
3596
3670
  }
3597
3671
  for (const [key, spec] of desired) {
3598
3672
  const existing = currentByKey.get(key);
3599
3673
  if (!existing) continue;
3600
3674
  if (existing.lag !== spec.lag) {
3601
- operations.push({ kind: "update", linkId: existing.id, lag: spec.lag });
3675
+ operations.push({
3676
+ kind: LINK_OPERATION_KIND.UPDATE,
3677
+ linkId: existing.id,
3678
+ lag: spec.lag
3679
+ });
3602
3680
  }
3603
3681
  }
3604
3682
  for (const [key, spec] of desired) {
3605
3683
  if (currentByKey.has(key)) continue;
3606
3684
  operations.push({
3607
- kind: "create",
3685
+ kind: LINK_OPERATION_KIND.CREATE,
3608
3686
  source: spec.source,
3609
3687
  target: targetActivityId,
3610
3688
  type: spec.type,
@@ -3638,20 +3716,24 @@ function diffOutgoingLinks(input) {
3638
3716
  const operations = [];
3639
3717
  for (const [key, link] of currentByKey) {
3640
3718
  if (!desired.has(key)) {
3641
- operations.push({ kind: "delete", linkId: link.id });
3719
+ operations.push({ kind: LINK_OPERATION_KIND.DELETE, linkId: link.id });
3642
3720
  }
3643
3721
  }
3644
3722
  for (const [key, spec] of desired) {
3645
3723
  const existing = currentByKey.get(key);
3646
3724
  if (!existing) continue;
3647
3725
  if (existing.lag !== spec.lag) {
3648
- operations.push({ kind: "update", linkId: existing.id, lag: spec.lag });
3726
+ operations.push({
3727
+ kind: LINK_OPERATION_KIND.UPDATE,
3728
+ linkId: existing.id,
3729
+ lag: spec.lag
3730
+ });
3649
3731
  }
3650
3732
  }
3651
3733
  for (const [key, spec] of desired) {
3652
3734
  if (currentByKey.has(key)) continue;
3653
3735
  operations.push({
3654
- kind: "create",
3736
+ kind: LINK_OPERATION_KIND.CREATE,
3655
3737
  source: sourceActivityId,
3656
3738
  target: spec.target,
3657
3739
  type: spec.type,
@@ -3695,13 +3777,13 @@ var currentImpl = {
3695
3777
  // src/autoscheduler/date-math/types.ts
3696
3778
  function pickDatesForLinkType(source, target, linkType2) {
3697
3779
  switch (linkType2) {
3698
- case "0":
3780
+ case LINK_TYPE.FINISH_TO_START:
3699
3781
  return { sourceDate: source.endDate, targetDate: target.startDate };
3700
- case "1":
3782
+ case LINK_TYPE.START_TO_START:
3701
3783
  return { sourceDate: source.startDate, targetDate: target.startDate };
3702
- case "2":
3784
+ case LINK_TYPE.FINISH_TO_FINISH:
3703
3785
  return { sourceDate: source.endDate, targetDate: target.endDate };
3704
- case "3":
3786
+ case LINK_TYPE.START_TO_FINISH:
3705
3787
  return { sourceDate: source.startDate, targetDate: target.endDate };
3706
3788
  }
3707
3789
  }
@@ -3834,7 +3916,7 @@ var AutoScheduler = class {
3834
3916
  };
3835
3917
  } catch (error) {
3836
3918
  this.reporter.error("[AutoScheduler] Error during scheduling", error);
3837
- return emptyResult;
3919
+ throw error;
3838
3920
  }
3839
3921
  }
3840
3922
  };
@@ -3914,7 +3996,7 @@ function adjustLinkLagOnTaskMove(targetId, adapter, preEditTarget) {
3914
3996
  if (!link) continue;
3915
3997
  const source = adapter.getActivity(link.source);
3916
3998
  if (!source) continue;
3917
- if (source.constraintType === "alap") continue;
3999
+ if (source.constraintType === CONSTRAINT_TYPE.ALAP) continue;
3918
4000
  const isEndAnchoredIntoMilestone = isMilestoneType(target.type) && (link.type === LINK_TYPE.START_TO_FINISH || link.type === LINK_TYPE.FINISH_TO_FINISH);
3919
4001
  if (isEndAnchoredIntoMilestone) continue;
3920
4002
  const { sourceDate, targetDate } = pickDatesForLinkType(
@@ -3928,7 +4010,10 @@ function adjustLinkLagOnTaskMove(targetId, adapter, preEditTarget) {
3928
4010
  calendarApi
3929
4011
  );
3930
4012
  if (newLag === link.lag) continue;
3931
- applyLinkUpdate({ linkId: link.id, lag: newLag }, adapter);
4013
+ applyLinkUpdate(
4014
+ { kind: LINK_OPERATION_KIND.UPDATE, linkId: link.id, lag: newLag },
4015
+ adapter
4016
+ );
3932
4017
  }
3933
4018
  }
3934
4019
 
@@ -4040,15 +4125,19 @@ function computeLeafRealWork(workHours, progress) {
4040
4125
  }
4041
4126
 
4042
4127
  // src/propagations/upward/parent-bounds.ts
4128
+ var PARENT_PROGRESS_MODE = {
4129
+ SKIP: "skip",
4130
+ FREEZE_WITHOUT_CONTRIBUTION: "freeze-when-no-contribution"
4131
+ };
4043
4132
  async function updateParentBoundsFromChildren(adapter, dirtyIds, recomputeProgress = true, options = {}) {
4044
4133
  const parents = dirtyIds ? findAncestorsOfDirty(adapter, dirtyIds) : findAllParents(adapter);
4045
- const progressMode = recomputeProgress ? options.progressMode ?? "freeze-when-no-contribution" : "skip";
4134
+ const progressMode = recomputeProgress ? options.progressMode ?? PARENT_PROGRESS_MODE.FREEZE_WITHOUT_CONTRIBUTION : PARENT_PROGRESS_MODE.SKIP;
4046
4135
  await recomputeParentsCooperatively(parents, adapter, progressMode, {
4047
4136
  recomputeRealWork: options.recomputeRealWork ?? false
4048
4137
  });
4049
4138
  }
4050
4139
  function recomputeSingleParentDisplayBounds(parentId, adapter) {
4051
- recomputeParentFromChildren(parentId, adapter, "skip");
4140
+ recomputeParentFromChildren(parentId, adapter, PARENT_PROGRESS_MODE.SKIP);
4052
4141
  }
4053
4142
  async function recomputeParentsCooperatively(parents, adapter, progressMode, options = {
4054
4143
  recomputeRealWork: false
@@ -4134,7 +4223,7 @@ function aggregateChildren(childrenIds, adapter, includeRealWork) {
4134
4223
  }
4135
4224
  return { minStart, maxEnd, realWorkSum, weightedChildren };
4136
4225
  }
4137
- function recomputeParentFromChildren(parentId, adapter, progressMode = "freeze-when-no-contribution", recomputeRealWork = false) {
4226
+ function recomputeParentFromChildren(parentId, adapter, progressMode = PARENT_PROGRESS_MODE.FREEZE_WITHOUT_CONTRIBUTION, recomputeRealWork = false) {
4138
4227
  const parent = adapter.getActivity(parentId);
4139
4228
  if (!parent) return;
4140
4229
  const childrenIds = adapter.getChildren(parentId);
@@ -4149,7 +4238,7 @@ function recomputeParentFromChildren(parentId, adapter, progressMode = "freeze-w
4149
4238
  adapter.setActivityField(parentId, "startDate", newStart);
4150
4239
  adapter.setActivityField(parentId, "endDate", newEnd);
4151
4240
  adapter.setActivityField(parentId, "durationHours", durationHours);
4152
- if (progressMode !== "skip") {
4241
+ if (progressMode !== PARENT_PROGRESS_MODE.SKIP) {
4153
4242
  applyWeightedProgressRollup(parentId, aggregate.weightedChildren, adapter);
4154
4243
  }
4155
4244
  if (recomputeRealWork) {
@@ -4256,6 +4345,21 @@ function fieldChanges(patch, options = {}) {
4256
4345
  };
4257
4346
  }
4258
4347
 
4348
+ // src/columns/shared/tracking-events.ts
4349
+ var COLUMN_TRACK_EVENT = {
4350
+ PROGRESS_ENTRY: "activity_progress_entry",
4351
+ PROGRESS_UPDATE_RADIO_BUTTON: "activity_progress_update_radio_button",
4352
+ DURATION_ENTRY: "activity_duration_entry",
4353
+ START_DATE_ENTRY: "activity_start_date_entry",
4354
+ END_DATE_ENTRY: "activity_end_date_entry",
4355
+ NAME_ENTRY: "activity_name_entry",
4356
+ DESCRIPTION_ENTRY: "activity_description_entry",
4357
+ CALENDAR_ASSIGNMENT: "activity_calendar_assignment",
4358
+ COST_BUDGETED_ENTRY: "activity_cost_budgeted_entry",
4359
+ COST_SPENT_ENTRY: "activity_cost_spent_entry",
4360
+ LABOR_HOURS_BUDGETED_ENTRY: "activity_labor_hours_budgeted_entry"
4361
+ };
4362
+
4259
4363
  // src/columns/text/text-pipeline.ts
4260
4364
  var textPipeline = {
4261
4365
  targetField: "name",
@@ -4275,7 +4379,7 @@ var textPipeline = {
4275
4379
  postProcessors: []
4276
4380
  });
4277
4381
  },
4278
- trackEvent: "activity_name_entry"
4382
+ trackEvent: COLUMN_TRACK_EVENT.NAME_ENTRY
4279
4383
  };
4280
4384
 
4281
4385
  // src/columns/description/description-pipeline.ts
@@ -4297,7 +4401,7 @@ var descriptionPipeline = {
4297
4401
  { autoSchedule: false, postProcessors: [] }
4298
4402
  );
4299
4403
  },
4300
- trackEvent: "activity_description_entry"
4404
+ trackEvent: COLUMN_TRACK_EVENT.DESCRIPTION_ENTRY
4301
4405
  };
4302
4406
 
4303
4407
  // src/columns/shared/activity-predicates.ts
@@ -4329,6 +4433,7 @@ var setEndDate = (value) => ({
4329
4433
  });
4330
4434
 
4331
4435
  // src/columns/shared/date-normalize.ts
4436
+ var UTC_TIME_ZONE = "UTC";
4332
4437
  function truncateToUtcDay(date2, tz) {
4333
4438
  {
4334
4439
  const parts = new Intl.DateTimeFormat("en-CA", {
@@ -4349,11 +4454,11 @@ function endOfLocalDay(date2, tz) {
4349
4454
  }
4350
4455
  }
4351
4456
  function nextWorkingDay(calendar, domainDay) {
4352
- let cursor = truncateToUtcDay(domainDay, "UTC");
4457
+ let cursor = truncateToUtcDay(domainDay, UTC_TIME_ZONE);
4353
4458
  while (!calendar.isWorkTime(cursor, CALENDAR_UNIT.DAY)) {
4354
4459
  cursor = new Date(cursor);
4355
4460
  cursor.setUTCDate(cursor.getUTCDate() + 1);
4356
- cursor = truncateToUtcDay(cursor, "UTC");
4461
+ cursor = truncateToUtcDay(cursor, UTC_TIME_ZONE);
4357
4462
  }
4358
4463
  return cursor;
4359
4464
  }
@@ -4376,22 +4481,22 @@ function shiftEnd(calendar, domainDay) {
4376
4481
  });
4377
4482
  }
4378
4483
  var START_BASED_CONSTRAINTS2 = /* @__PURE__ */ new Set([
4379
- "snet",
4380
- "snlt",
4381
- "mso"
4484
+ CONSTRAINT_TYPE.SNET,
4485
+ CONSTRAINT_TYPE.SNLT,
4486
+ CONSTRAINT_TYPE.MSO
4382
4487
  ]);
4383
4488
  var END_BASED_CONSTRAINTS = /* @__PURE__ */ new Set([
4384
- "fnet",
4385
- "fnlt",
4386
- "mfo"
4489
+ CONSTRAINT_TYPE.FNET,
4490
+ CONSTRAINT_TYPE.FNLT,
4491
+ CONSTRAINT_TYPE.MFO
4387
4492
  ]);
4388
4493
  var DATELESS_CONSTRAINTS = /* @__PURE__ */ new Set([
4389
- "asap",
4390
- "alap"
4494
+ CONSTRAINT_TYPE.ASAP,
4495
+ CONSTRAINT_TYPE.ALAP
4391
4496
  ]);
4392
- var IMPLIED_CONSTRAINT_ON_DATE_EDIT = "snet";
4497
+ var IMPLIED_CONSTRAINT_ON_DATE_EDIT = CONSTRAINT_TYPE.SNET;
4393
4498
  function normalizeConstraintDate(typedDay, calendar, constraintType) {
4394
- const constraintDay = truncateToUtcDay(typedDay, "UTC");
4499
+ const constraintDay = truncateToUtcDay(typedDay, UTC_TIME_ZONE);
4395
4500
  if (!START_BASED_CONSTRAINTS2.has(constraintType) && !END_BASED_CONSTRAINTS.has(constraintType)) {
4396
4501
  return constraintDay;
4397
4502
  }
@@ -4427,6 +4532,20 @@ var POST_PROCESSOR = {
4427
4532
  // src/columns/shared/error-codes.ts
4428
4533
  var VALIDATION_REASON = {
4429
4534
  NEGATIVE_DURATION: "negative_duration"};
4535
+ var EDIT_DENIAL_REASON = {
4536
+ COMPLETED: "completed",
4537
+ SUMMARY: "summary",
4538
+ HAS_PROGRESS: "has_progress",
4539
+ HAS_LOOKAHEAD_TASKS: "has_lookahead_tasks",
4540
+ SIR_START_AFTER_PROGRESS: "sir_start_after_progress"
4541
+ };
4542
+ var EDIT_ALERT_KEY = {
4543
+ CANT_EDIT_COMPLETED: "cant_edit_completed_activity",
4544
+ SUMMARY_COLUMN_VALUE: "summary_column_value",
4545
+ CANT_EDIT_WITH_PROGRESS: "cant_edit_activity_with_progress",
4546
+ SIR_CANT_MOVE_START_AFTER_PROGRESS: "sir_cant_move_start_after_progress",
4547
+ CANT_EDIT_WITH_TASK: "cant_edit_actvity_with_task"
4548
+ };
4430
4549
 
4431
4550
  // src/columns/shared/constraint-validation.ts
4432
4551
  function checkConstraintViolation2(constraintType, constraintDate, projectedDate) {
@@ -4491,7 +4610,7 @@ var durationPipeline = {
4491
4610
  } : {}
4492
4611
  };
4493
4612
  },
4494
- trackEvent: "activity_duration_entry"
4613
+ trackEvent: COLUMN_TRACK_EVENT.DURATION_ENTRY
4495
4614
  };
4496
4615
  function isNegativeDuration(value) {
4497
4616
  return Math.sign(value) === -1;
@@ -4503,7 +4622,7 @@ function checkDurationAgainstConstraints(activity, newDuration, ctx) {
4503
4622
  const calendar = ctx.calendars.getCalendar(activity.calendarId);
4504
4623
  if (!calendar) return { violated: false };
4505
4624
  const type = activity.constraintType;
4506
- if (type !== "fnet" && type !== "fnlt" && type !== "mfo") {
4625
+ if (type !== CONSTRAINT_TYPE.FNET && type !== CONSTRAINT_TYPE.FNLT && type !== CONSTRAINT_TYPE.MFO) {
4507
4626
  return { violated: false };
4508
4627
  }
4509
4628
  const projectedEnd = calendar.calculateEndDate(
@@ -4549,10 +4668,10 @@ var MAX_PROGRESS = PROGRESS_COMPLETE;
4549
4668
  var progressPipeline = {
4550
4669
  targetField: "progress",
4551
4670
  canEdit(activity, hierarchy) {
4552
- if (hasLookaheadTasks(activity))
4553
- return cannotEdit("has_lookahead_tasks", "cant_edit_actvity_with_task");
4554
4671
  if (isSummaryActivity2(activity, hierarchy))
4555
4672
  return cannotEdit("summary", "summary_column_value");
4673
+ if (hasLookaheadTasks(activity))
4674
+ return cannotEdit("has_lookahead_tasks", "cant_edit_actvity_with_task");
4556
4675
  return canEdit();
4557
4676
  },
4558
4677
  parseInput(rawValue) {
@@ -4596,7 +4715,7 @@ var progressPipeline = {
4596
4715
  trackingEvents
4597
4716
  });
4598
4717
  },
4599
- trackEvent: "activity_progress_entry"
4718
+ trackEvent: COLUMN_TRACK_EVENT.PROGRESS_ENTRY
4600
4719
  };
4601
4720
  function isOutOfRange(value) {
4602
4721
  return value < MIN_PROGRESS || value > MAX_PROGRESS;
@@ -4676,7 +4795,7 @@ function computeWeightedProgress(parentId, overlay, hierarchy) {
4676
4795
  function buildRecursiveTrackingEvents(activity, newValue) {
4677
4796
  return [
4678
4797
  {
4679
- name: "activity_progress_update_radio_button",
4798
+ name: COLUMN_TRACK_EVENT.PROGRESS_UPDATE_RADIO_BUTTON,
4680
4799
  properties: {
4681
4800
  activity_id: activity.id,
4682
4801
  activity_name: activity.name,
@@ -4716,7 +4835,7 @@ var costPipeline = {
4716
4835
  cascadeMutations
4717
4836
  });
4718
4837
  },
4719
- trackEvent: "activity_cost_budgeted_entry"
4838
+ trackEvent: COLUMN_TRACK_EVENT.COST_BUDGETED_ENTRY
4720
4839
  };
4721
4840
  function buildCostAncestorCascade(activity, newCost, hierarchy) {
4722
4841
  const overlay = /* @__PURE__ */ new Map();
@@ -4769,7 +4888,7 @@ var usedCostPipeline = {
4769
4888
  }
4770
4889
  );
4771
4890
  },
4772
- trackEvent: "activity_cost_spent_entry"
4891
+ trackEvent: COLUMN_TRACK_EVENT.COST_SPENT_ENTRY
4773
4892
  };
4774
4893
  function buildUsedCostAncestorCascade(activity, newUsedCost, hierarchy) {
4775
4894
  const overlay = /* @__PURE__ */ new Map();
@@ -4824,7 +4943,7 @@ var hhWorkTimePipeline = {
4824
4943
  }
4825
4944
  );
4826
4945
  },
4827
- trackEvent: "activity_labor_hours_budgeted_entry"
4946
+ trackEvent: COLUMN_TRACK_EVENT.LABOR_HOURS_BUDGETED_ENTRY
4828
4947
  };
4829
4948
  function computeRealWork(hhWorkTime, progress) {
4830
4949
  return computeLeafRealWork(hhWorkTime, progress);
@@ -4917,7 +5036,7 @@ var startDatePipeline = {
4917
5036
  throw new Error("startDatePipeline: no calendar resolved (integrity)");
4918
5037
  }
4919
5038
  const finalStart = shiftStart(calendar, newValue);
4920
- const milestoneActivity = activity.type === "milestone";
5039
+ const milestoneActivity = activity.type === ACTIVITY_TYPE.MILESTONE;
4921
5040
  const finalEnd = milestoneActivity ? finalStart : calendar.calculateEndDate(finalStart, activity.durationHours);
4922
5041
  const constraintDate = finalStart;
4923
5042
  return {
@@ -4937,7 +5056,7 @@ var startDatePipeline = {
4937
5056
  constraintWarning: detectConstraintWarning(activity, finalStart, calendar)
4938
5057
  };
4939
5058
  },
4940
- trackEvent: "activity_start_date_entry"
5059
+ trackEvent: COLUMN_TRACK_EVENT.START_DATE_ENTRY
4941
5060
  };
4942
5061
  function checkParentStartConstraint(activity, newDate, ctx) {
4943
5062
  const parentStartDate = ctx.hierarchy.getParentStartDateIfHasPredecessors(
@@ -5031,7 +5150,7 @@ var endDatePipeline = {
5031
5150
  ...constraintWarning ? { constraintWarning } : {}
5032
5151
  };
5033
5152
  },
5034
- trackEvent: "activity_end_date_entry"
5153
+ trackEvent: COLUMN_TRACK_EVENT.END_DATE_ENTRY
5035
5154
  };
5036
5155
  function isNearlyCompleted(activity) {
5037
5156
  return activity.progress >= NEAR_COMPLETE_THRESHOLD;
@@ -5142,7 +5261,9 @@ function buildConstraintTypeExtraFields(activity, newType, ctx) {
5142
5261
  };
5143
5262
  }
5144
5263
  function normalizeMilestoneConstraintDate(activity, newType, derivedDate, ctx) {
5145
- if (activity.type !== "milestone" || !derivedDate) return derivedDate;
5264
+ if (activity.type !== ACTIVITY_TYPE.MILESTONE || !derivedDate) {
5265
+ return derivedDate;
5266
+ }
5146
5267
  const calendar = ctx.calendars.getCalendar(String(activity.calendarId));
5147
5268
  if (!calendar) return derivedDate;
5148
5269
  return normalizeConstraintDate(derivedDate, calendar, newType);
@@ -5220,7 +5341,7 @@ var calendarIdPipeline = {
5220
5341
  postProcessors: []
5221
5342
  });
5222
5343
  },
5223
- trackEvent: "activity_calendar_assignment"
5344
+ trackEvent: COLUMN_TRACK_EVENT.CALENDAR_ASSIGNMENT
5224
5345
  };
5225
5346
  function isEmpty(value) {
5226
5347
  return value === "";
@@ -5302,8 +5423,7 @@ var customIdPipeline = {
5302
5423
  { customId: newValue },
5303
5424
  { autoSchedule: false, postProcessors: [] }
5304
5425
  );
5305
- },
5306
- trackEvent: "schedule_custom_id_edition"
5426
+ }
5307
5427
  };
5308
5428
 
5309
5429
  // src/columns/subcontract-id/subcontract-id-pipeline.ts
@@ -5442,6 +5562,9 @@ var ACTIVITY_BATCH_MODE = {
5442
5562
  APPEND: "append",
5443
5563
  REPLACE: "replace"
5444
5564
  };
5565
+ var ACTIVITY_PROGRESS_ORIGIN = {
5566
+ ACTION_BUTTON: "action-button"
5567
+ };
5445
5568
  var SCHEDULE_EFFECT_KIND = {
5446
5569
  SIR_AUTO_REJECT: "sir-auto-reject"
5447
5570
  };
@@ -5460,7 +5583,9 @@ var CHANGE_SET_SOURCE_KIND = {
5460
5583
 
5461
5584
  // src/dispatch/shared/constraint-warnings.ts
5462
5585
  function toConstraintWarning(activityId, notification) {
5463
- if (!notification || notification.type !== "constraint") return null;
5586
+ if (!notification || notification.type !== NOTIFICATION_TYPE.CONSTRAINT) {
5587
+ return null;
5588
+ }
5464
5589
  const data = notification.data;
5465
5590
  if (!data?.constraintType || !data.constraintDate) return null;
5466
5591
  return {
@@ -5506,6 +5631,7 @@ var ACTIVITY_PROPERTY = {
5506
5631
  TYPE: "type",
5507
5632
  START_DATE: "startDate",
5508
5633
  END_DATE: "endDate",
5634
+ DURATION_HOURS: "durationHours",
5509
5635
  CONSTRAINT_TYPE: "constraintType",
5510
5636
  CONSTRAINT_DATE: "constraintDate",
5511
5637
  PROGRESS: "progress",
@@ -5638,7 +5764,7 @@ async function buildActivityChanges(adapter, before, touched, correlativeBefore)
5638
5764
  function buildEntryForTouchedId(adapter, before, activityId, correlativeBefore) {
5639
5765
  const afterSnap = adapter.getActivity(activityId);
5640
5766
  if (!afterSnap) {
5641
- return { id: activityId, kind: "deleted", after: null };
5767
+ return { id: activityId, kind: ENTITY_CHANGE_KIND.DELETED, after: null };
5642
5768
  }
5643
5769
  const beforeSnap = before.get(activityId);
5644
5770
  if (!beforeSnap && correlativeBefore?.has(activityId)) {
@@ -5653,7 +5779,7 @@ function buildEntryForTouchedId(adapter, before, activityId, correlativeBefore)
5653
5779
  if (beforeSnap && Object.keys(diff).length === 0) return null;
5654
5780
  return {
5655
5781
  id: activityId,
5656
- kind: beforeSnap ? "updated" : "created",
5782
+ kind: beforeSnap ? ENTITY_CHANGE_KIND.UPDATED : ENTITY_CHANGE_KIND.CREATED,
5657
5783
  fields: diff,
5658
5784
  after: structuredCloneActivity(afterSnap)
5659
5785
  };
@@ -5662,7 +5788,7 @@ function buildCorrelativeOnlyEntry(activityId, correlativeIdBefore, liveActivity
5662
5788
  if (correlativeIdBefore === liveActivity.correlativeId) return null;
5663
5789
  return {
5664
5790
  id: activityId,
5665
- kind: "updated",
5791
+ kind: ENTITY_CHANGE_KIND.UPDATED,
5666
5792
  fields: {
5667
5793
  correlativeId: {
5668
5794
  before: correlativeIdBefore,
@@ -5787,7 +5913,7 @@ function expectedProgressFromBaseline(start, end, now, calendar) {
5787
5913
  }
5788
5914
 
5789
5915
  // src/columns/expected-progress/compute.ts
5790
- var isProject = (activity) => activity.type === "project";
5916
+ var isProject = (activity) => activity.type === ACTIVITY_TYPE.PROJECT;
5791
5917
  var leafExpectedLive = (activity, now, state) => {
5792
5918
  const calendarId = activity.calendarId;
5793
5919
  const calendar = calendarId != null ? state.calendarReader.getCalendar(String(calendarId)) : null;
@@ -5841,7 +5967,7 @@ function applyExpectedProgressLive(state, now) {
5841
5967
  }
5842
5968
 
5843
5969
  // src/columns/expected-progress-base/compute.ts
5844
- var isProject2 = (a) => a.type === "project";
5970
+ var isProject2 = (a) => a.type === ACTIVITY_TYPE.PROJECT;
5845
5971
  var activeBaselineOf = (a) => getActiveBaseline(a);
5846
5972
  var leafExpected = (a, now, adapter, defaultBaseCalendarId) => {
5847
5973
  const base = activeBaselineOf(a);
@@ -6003,15 +6129,44 @@ function getNextWorkingHour(activityParams) {
6003
6129
  return newDate;
6004
6130
  }
6005
6131
 
6132
+ // src/critical-path/legacy/constants/constraints.js
6133
+ var CONSTRAINT_TYPES = CONSTRAINT_TYPE;
6134
+
6135
+ // src/critical-path/legacy/constants/linkTypes.js
6136
+ var LINK_TYPES3 = Object.freeze({
6137
+ FS: LINK_CODE.FINISH_TO_START,
6138
+ SS: LINK_CODE.START_TO_START,
6139
+ FF: LINK_CODE.FINISH_TO_FINISH,
6140
+ SF: LINK_CODE.START_TO_FINISH
6141
+ });
6142
+
6143
+ // src/critical-path/legacy/constants/linkByCode.js
6144
+ function getLinkNameByCode(code) {
6145
+ return LINK_TYPE_CODE[String(Number(code))] ?? LINK_CODE.START_TO_FINISH;
6146
+ }
6147
+
6148
+ // src/critical-path/legacy/constants/calculation.js
6149
+ var CALCULATION_DIRECTION = Object.freeze({
6150
+ FORWARD: "forward",
6151
+ BACKWARD: "backward"
6152
+ });
6153
+ var COMPARISON_DIRECTION = Object.freeze({
6154
+ GREATER: "greater",
6155
+ LESS: "less"
6156
+ });
6157
+ var GANTT_FIELD = Object.freeze({
6158
+ SOURCE: "$source"
6159
+ });
6160
+
6006
6161
  // src/critical-path/legacy/helpers/filters.js
6007
6162
  var byFirstLevel = (activity) => {
6008
6163
  if (!activity) return false;
6009
6164
  return activity["$level"] === 1;
6010
6165
  };
6011
- var filterByParentType = (activity) => activity.type === "project";
6166
+ var filterByParentType = (activity) => activity.type === ACTIVITY_TYPE.PROJECT;
6012
6167
  var avoidSubproject = (activity) => activity["$level"] !== 0;
6013
- var byTaskType = (activity) => activity.type === "task";
6014
- var byTaskTypeAndMilestone = (activity) => activity.type === "task" || activity.type === "milestone";
6168
+ var byTaskType = (activity) => activity.type === ACTIVITY_TYPE.TASK;
6169
+ var byTaskTypeAndMilestone = (activity) => activity.type === ACTIVITY_TYPE.TASK || activity.type === ACTIVITY_TYPE.MILESTONE;
6015
6170
  var filters_default = {
6016
6171
  byFirstLevel,
6017
6172
  filterByParentType,
@@ -6020,37 +6175,6 @@ var filters_default = {
6020
6175
  byTaskTypeAndMilestone
6021
6176
  };
6022
6177
 
6023
- // src/critical-path/legacy/constants/constraints.js
6024
- var CONSTRAINT_TYPES = Object.freeze({
6025
- MFO: "mfo",
6026
- MSO: "mso",
6027
- FNLT: "fnlt",
6028
- FNET: "fnet",
6029
- SNET: "snet",
6030
- SNLT: "snlt",
6031
- ALAP: "alap",
6032
- ASAP: "asap"
6033
- });
6034
-
6035
- // src/critical-path/legacy/constants/linkTypes.js
6036
- var LINK_TYPES2 = Object.freeze({
6037
- FS: "fs",
6038
- SS: "ss",
6039
- FF: "ff",
6040
- SF: "sf"
6041
- });
6042
-
6043
- // src/critical-path/legacy/constants/linkByCode.js
6044
- function getLinkNameByCode(code) {
6045
- const linkMap = {
6046
- 0: "fs",
6047
- 1: "ss",
6048
- 2: "ff",
6049
- 3: "sf"
6050
- };
6051
- return linkMap[Number(code)] || "sf";
6052
- }
6053
-
6054
6178
  // src/critical-path/legacy/base/identifiers/secondLevelActivities.js
6055
6179
  function identifySecondLevelActivities(params) {
6056
6180
  const { gantt, pendingParentsWithNoLinks, calculations, linkProperty } = params;
@@ -6112,7 +6236,7 @@ function filterChildrenThatCanBeCalculated(params) {
6112
6236
  const linkedActivities = getArrayOfLinkedActivities3({
6113
6237
  gantt,
6114
6238
  links,
6115
- linkDirection: linkProperty === "$source" ? "target" : "source"
6239
+ linkDirection: linkProperty === GANTT_FIELD.SOURCE ? "target" : "source"
6116
6240
  });
6117
6241
  const isLinkedWithCalculatedOrSibling = linkedActivities.every(
6118
6242
  (linkedActivityId) => calculations.has(linkedActivityId)
@@ -6141,13 +6265,13 @@ function getArrayOfLinkedActivities(params) {
6141
6265
  function identifyInitialActivities({ gantt, linkProperty, direction }) {
6142
6266
  try {
6143
6267
  const chainStartActivities = getChainStartActivities(gantt, linkProperty);
6144
- if (direction === "forward") {
6268
+ if (direction === CALCULATION_DIRECTION.FORWARD) {
6145
6269
  return {
6146
6270
  chainStartActivities,
6147
6271
  activitiesStartChainButChildrenOfLinkedParents: null
6148
6272
  };
6149
6273
  }
6150
- if (direction === "backward") {
6274
+ if (direction === CALCULATION_DIRECTION.BACKWARD) {
6151
6275
  return processBackwardActivities(
6152
6276
  chainStartActivities,
6153
6277
  gantt,
@@ -6171,7 +6295,7 @@ function processBackwardActivities(chainStartActivities, gantt, linkProperty) {
6171
6295
  if (!parentActivity) return;
6172
6296
  if (parentActivity[linkProperty].length > 0) {
6173
6297
  activitiesStartChainButChildrenOfLinkedParents.add(activity.id);
6174
- } else if (parentActivity.constraint_type !== "fnlt") {
6298
+ } else if (parentActivity.constraint_type !== CONSTRAINT_TYPES.FNLT) {
6175
6299
  withoutLinkedParents.push(activity);
6176
6300
  }
6177
6301
  });
@@ -6192,7 +6316,7 @@ function identifyParentsWithAndWithoutLinks({
6192
6316
  const parentsWithFullProgress = /* @__PURE__ */ new Set();
6193
6317
  const pendingParentsWithNoLinks = /* @__PURE__ */ new Set();
6194
6318
  const pendingParentsWithLinks = /* @__PURE__ */ new Set();
6195
- if (direction === "backward") {
6319
+ if (direction === CALCULATION_DIRECTION.BACKWARD) {
6196
6320
  const parentsWithFullProgressArray = getParentsWithFullProgress(allParentActivities);
6197
6321
  parentsWithFullProgressArray.forEach((activity) => {
6198
6322
  parentsWithFullProgress.add(activity.id);
@@ -6230,9 +6354,9 @@ function getParentsWithNoLinks(activities, direction, linkProperty) {
6230
6354
  }
6231
6355
  const hasLinks = links.length > 0;
6232
6356
  const constraintType = activity.constraint_type || "";
6233
- const isNotFnlt = constraintType !== "fnlt";
6234
- if (direction === "forward") {
6235
- const isNotSnet = constraintType !== "snet";
6357
+ const isNotFnlt = constraintType !== CONSTRAINT_TYPES.FNLT;
6358
+ if (direction === CALCULATION_DIRECTION.FORWARD) {
6359
+ const isNotSnet = constraintType !== CONSTRAINT_TYPES.SNET;
6236
6360
  return !hasLinks && isNotFnlt && isNotSnet;
6237
6361
  } else {
6238
6362
  return !hasLinks && isNotFnlt;
@@ -6288,10 +6412,10 @@ function identifyForbiddenActivities({
6288
6412
  }
6289
6413
  }
6290
6414
  function getLinkProperty(direction) {
6291
- return direction === "forward" ? "$source" : "$target";
6415
+ return direction === CALCULATION_DIRECTION.FORWARD ? GANTT_FIELD.SOURCE : "$target";
6292
6416
  }
6293
6417
  function getLinkDirection(direction) {
6294
- return direction === "forward" ? "target" : "source";
6418
+ return direction === CALCULATION_DIRECTION.FORWARD ? "target" : "source";
6295
6419
  }
6296
6420
  function getArrayOfLinkedActivities2(gantt, links, direction) {
6297
6421
  return links.map((link) => {
@@ -6327,7 +6451,7 @@ function mutateDate({
6327
6451
  activityCalendar,
6328
6452
  activity
6329
6453
  }) {
6330
- if (linkType2 === LINK_TYPES2.FS && lag === 0) {
6454
+ if (linkType2 === LINK_TYPES3.FS && lag === 0) {
6331
6455
  return getNextWorkingHour({
6332
6456
  activityCalendar,
6333
6457
  direction: "future",
@@ -6363,10 +6487,10 @@ function calculateRestrictionSnet({
6363
6487
  return { es, ef };
6364
6488
  }
6365
6489
  function mutateTheDateToFutureOrPastInBaseRestriction(dateBaseToCalculate, restrictionOfLink, activityCalendar, activity) {
6366
- if (![LINK_TYPES2.FS, LINK_TYPES2.SS, LINK_TYPES2.FF].includes(restrictionOfLink)) {
6490
+ if (![LINK_TYPES3.FS, LINK_TYPES3.SS, LINK_TYPES3.FF].includes(restrictionOfLink)) {
6367
6491
  return dateBaseToCalculate;
6368
6492
  }
6369
- let constraintThatGoToNextWorkingHour = [LINK_TYPES2.FS, LINK_TYPES2.SS];
6493
+ let constraintThatGoToNextWorkingHour = [LINK_TYPES3.FS, LINK_TYPES3.SS];
6370
6494
  let direction = constraintThatGoToNextWorkingHour.includes(restrictionOfLink) ? "future" : "past";
6371
6495
  return getNextWorkingHour({
6372
6496
  dateBaseToCalculate,
@@ -6394,10 +6518,10 @@ var CalculateForwardParentsWithLinks = class {
6394
6518
  const calculationsFromLinks = this.calculateLinks();
6395
6519
  const maxEfFromLinks = getMaxEarlyStartSet(calculationsFromLinks);
6396
6520
  const constraintType = this.activity.constraint_type;
6397
- if (constraintType === "snet") {
6521
+ if (constraintType === CONSTRAINT_TYPES.SNET) {
6398
6522
  return this.handleSNETConstraint(maxEfFromLinks);
6399
6523
  }
6400
- if (constraintType === "fnlt") {
6524
+ if (constraintType === CONSTRAINT_TYPES.FNLT) {
6401
6525
  return this.handleFNLTConstraint(maxEfFromLinks);
6402
6526
  }
6403
6527
  return maxEfFromLinks;
@@ -6411,13 +6535,13 @@ var CalculateForwardParentsWithLinks = class {
6411
6535
  const predecessorEs = linkedActivity.es;
6412
6536
  const predecessorEf = linkedActivity.ef;
6413
6537
  let calculation = null;
6414
- if (linkType2 === "ss") {
6538
+ if (linkType2 === LINK_TYPES3.SS) {
6415
6539
  calculation = this.calculateSSLink({ lag, predecessorEs });
6416
- } else if (linkType2 === "ff") {
6540
+ } else if (linkType2 === LINK_TYPES3.FF) {
6417
6541
  calculation = this.calculateFFLink({ lag, predecessorEf });
6418
- } else if (linkType2 === "fs") {
6542
+ } else if (linkType2 === LINK_TYPES3.FS) {
6419
6543
  calculation = this.calculateFSLink({ lag, predecessorEf });
6420
- } else if (linkType2 === "sf") {
6544
+ } else if (linkType2 === LINK_TYPES3.SF) {
6421
6545
  calculation = this.calculateSFLink({
6422
6546
  lag,
6423
6547
  predecessorEs,
@@ -6462,7 +6586,7 @@ var CalculateForwardParentsWithLinks = class {
6462
6586
  }
6463
6587
  calculateSSLink({ lag, predecessorEs }) {
6464
6588
  const esLinked = mutateDate({
6465
- linkType: "ss",
6589
+ linkType: LINK_TYPES3.SS,
6466
6590
  lag,
6467
6591
  predecessorTime: predecessorEs,
6468
6592
  activityCalendar: this.activityCalendar,
@@ -6477,7 +6601,7 @@ var CalculateForwardParentsWithLinks = class {
6477
6601
  if (lag > 0) {
6478
6602
  es = mutateTheDateToFutureOrPastInBaseRestriction(
6479
6603
  es,
6480
- "ss",
6604
+ LINK_TYPES3.SS,
6481
6605
  this.activityCalendar,
6482
6606
  this.activity
6483
6607
  );
@@ -6492,7 +6616,7 @@ var CalculateForwardParentsWithLinks = class {
6492
6616
  }
6493
6617
  calculateFFLink({ lag, predecessorEf }) {
6494
6618
  const efLinked = mutateDate({
6495
- linkType: "ff",
6619
+ linkType: LINK_TYPES3.FF,
6496
6620
  lag,
6497
6621
  predecessorTime: predecessorEf,
6498
6622
  activityCalendar: this.activityCalendar,
@@ -6513,7 +6637,7 @@ var CalculateForwardParentsWithLinks = class {
6513
6637
  if (lag > 0) {
6514
6638
  es = mutateTheDateToFutureOrPastInBaseRestriction(
6515
6639
  es,
6516
- "ff",
6640
+ LINK_TYPES3.FF,
6517
6641
  this.activityCalendar,
6518
6642
  this.activity
6519
6643
  );
@@ -6560,7 +6684,7 @@ var CalculateForwardParentsWithLinks = class {
6560
6684
  if (lag > 0) {
6561
6685
  es = mutateTheDateToFutureOrPastInBaseRestriction(
6562
6686
  es,
6563
- "sf",
6687
+ LINK_TYPES3.SF,
6564
6688
  this.activityCalendar,
6565
6689
  this.activity
6566
6690
  );
@@ -6587,16 +6711,16 @@ var CalculateBackwardParentsLinks = class {
6587
6711
  const calculationsFromLinks = [];
6588
6712
  for (let linkedActivity of this.linkedActivitiesData) {
6589
6713
  const linkType2 = getLinkNameByCode(linkedActivity.linkType);
6590
- if (linkedActivity.type === "task" && Number(linkedActivity.progress) > 0) {
6714
+ if (linkedActivity.type === ACTIVITY_TYPE.TASK && Number(linkedActivity.progress) > 0) {
6591
6715
  continue;
6592
6716
  }
6593
- if (linkedActivity.type === "project" && Number(linkedActivity.progress) === 100) {
6717
+ if (linkedActivity.type === ACTIVITY_TYPE.PROJECT && Number(linkedActivity.progress) === 100) {
6594
6718
  continue;
6595
6719
  }
6596
6720
  const lag = linkedActivity.linkLag;
6597
6721
  let sucessorLs = linkedActivity.ls;
6598
6722
  let sucessorLf = linkedActivity.lf;
6599
- if (linkType2 === "ss") {
6723
+ if (linkType2 === LINK_TYPES3.SS) {
6600
6724
  const valuesToDoCalculation = {
6601
6725
  lag,
6602
6726
  workTime: sucessorLs,
@@ -6606,7 +6730,7 @@ var CalculateBackwardParentsLinks = class {
6606
6730
  let { ls, lf } = this.calculateSSLink(valuesToDoCalculation);
6607
6731
  calculationsFromLinks.push({ ls, lf });
6608
6732
  }
6609
- if (linkType2 === "ff") {
6733
+ if (linkType2 === LINK_TYPES3.FF) {
6610
6734
  const valuesToDoCalculation = {
6611
6735
  lag,
6612
6736
  workTime: sucessorLf,
@@ -6616,7 +6740,7 @@ var CalculateBackwardParentsLinks = class {
6616
6740
  let { ls, lf } = this.calculateFFLink(valuesToDoCalculation);
6617
6741
  calculationsFromLinks.push({ ls, lf });
6618
6742
  }
6619
- if (linkType2 === "fs") {
6743
+ if (linkType2 === LINK_TYPES3.FS) {
6620
6744
  const valuesToDoCalculation = {
6621
6745
  lag,
6622
6746
  workTime: sucessorLs,
@@ -6626,7 +6750,7 @@ var CalculateBackwardParentsLinks = class {
6626
6750
  let { ls, lf } = this.calculateFsLink(valuesToDoCalculation);
6627
6751
  calculationsFromLinks.push({ ls, lf });
6628
6752
  }
6629
- if (linkType2 === "sf") {
6753
+ if (linkType2 === LINK_TYPES3.SF) {
6630
6754
  const valuesToDoCalculation = {
6631
6755
  lag,
6632
6756
  workTime: sucessorLf,
@@ -6637,7 +6761,7 @@ var CalculateBackwardParentsLinks = class {
6637
6761
  calculationsFromLinks.push({ ls, lf });
6638
6762
  }
6639
6763
  }
6640
- if (this.activity.constraint_type === "fnlt") {
6764
+ if (this.activity.constraint_type === CONSTRAINT_TYPES.FNLT) {
6641
6765
  const maxLfFromLinks = this.getMinLfFromLinks(calculationsFromLinks);
6642
6766
  let restriction = this.calculateSfRestrictionDates();
6643
6767
  if (!maxLfFromLinks) {
@@ -6684,7 +6808,7 @@ var CalculateBackwardParentsLinks = class {
6684
6808
  lfSucessor = this.getLastWorkingHour(
6685
6809
  lfSucessor,
6686
6810
  this.activityCalendar,
6687
- "past"
6811
+ WORK_TIME_DIRECTION.PAST
6688
6812
  );
6689
6813
  }
6690
6814
  lfPred = addDurationToDate(
@@ -6714,7 +6838,7 @@ var CalculateBackwardParentsLinks = class {
6714
6838
  const lsSucessor2 = this.getLastWorkingHour(
6715
6839
  workTime,
6716
6840
  this.activityCalendar,
6717
- "past"
6841
+ WORK_TIME_DIRECTION.PAST
6718
6842
  );
6719
6843
  lfPred = addDurationToDate(
6720
6844
  this.activityCalendar,
@@ -6722,7 +6846,7 @@ var CalculateBackwardParentsLinks = class {
6722
6846
  lfDataCalculation,
6723
6847
  this.activity
6724
6848
  );
6725
- lfPred = this.getLastWorkingHour(lfPred, this.activityCalendar, "past");
6849
+ lfPred = this.getLastWorkingHour(lfPred, this.activityCalendar, WORK_TIME_DIRECTION.PAST);
6726
6850
  lsPred = addDurationToDate(
6727
6851
  this.activityCalendar,
6728
6852
  lfPred,
@@ -6748,7 +6872,7 @@ var CalculateBackwardParentsLinks = class {
6748
6872
  this.activity
6749
6873
  );
6750
6874
  if (!isMilestone) {
6751
- lfPred = this.getLastWorkingHour(lfPred, this.activityCalendar, "past");
6875
+ lfPred = this.getLastWorkingHour(lfPred, this.activityCalendar, WORK_TIME_DIRECTION.PAST);
6752
6876
  }
6753
6877
  return { ls: lsPred, lf: lfPred };
6754
6878
  }
@@ -6835,10 +6959,10 @@ var CalculateBackwardParentsLinks = class {
6835
6959
  );
6836
6960
  return { ls: lsRestriction, lf: lfRestriction };
6837
6961
  }
6838
- getLastWorkingHour(date2, activityCalendar, dir = "past") {
6962
+ getLastWorkingHour(date2, activityCalendar, dir = WORK_TIME_DIRECTION.PAST) {
6839
6963
  const normalizedDate = date2 instanceof Date ? date2 : new Date(date2);
6840
6964
  let resetedDate = moment_default(normalizedDate).clone();
6841
- if (this.isActivityInInitHour(activityCalendar, normalizedDate) && dir === "past") {
6965
+ if (this.isActivityInInitHour(activityCalendar, normalizedDate) && dir === WORK_TIME_DIRECTION.PAST) {
6842
6966
  resetedDate = resetedDate.hours(0).minutes(0).seconds(0).milliseconds(0);
6843
6967
  }
6844
6968
  let newDate = getNextWorkingHour({
@@ -6884,7 +7008,7 @@ function parentWithLinks(params) {
6884
7008
  const linksArray = parent[linkProperty];
6885
7009
  const parentData = extractParentData(parent);
6886
7010
  let calculation = null;
6887
- if (direction === "forward") {
7011
+ if (direction === CALCULATION_DIRECTION.FORWARD) {
6888
7012
  const linksWithActivityData = getLinksWithActivityDataForward(
6889
7013
  linksArray,
6890
7014
  linkDirection,
@@ -7002,7 +7126,7 @@ function getCalculatedChildren(childrenIds, calculations) {
7002
7126
  return childrenIds.filter((childId) => calculations.has(childId)).map((childId) => calculations.get(childId));
7003
7127
  }
7004
7128
  function computeParentCalculation(childrenCalculations, direction) {
7005
- if (direction === "forward") {
7129
+ if (direction === CALCULATION_DIRECTION.FORWARD) {
7006
7130
  const earliestStart = calculateEarliestDate(childrenCalculations, "es");
7007
7131
  const latestFinish = calculateLatestDate(childrenCalculations, "ef");
7008
7132
  return { es: earliestStart, ef: latestFinish };
@@ -7034,8 +7158,8 @@ var CalculationOfParent = class {
7034
7158
  constructor(params) {
7035
7159
  this.activity = params.activity;
7036
7160
  this.direction = params.direction;
7037
- this.linkProperty = params.direction === "forward" ? "$target" : "$source";
7038
- this.linkDirection = params.direction === "forward" ? "source" : "target";
7161
+ this.linkProperty = params.direction === CALCULATION_DIRECTION.FORWARD ? "$target" : GANTT_FIELD.SOURCE;
7162
+ this.linkDirection = params.direction === CALCULATION_DIRECTION.FORWARD ? "source" : "target";
7039
7163
  this.calculationsOfParentThatImpactChildrens = params.calculationsOfParentThatImpactChildrens;
7040
7164
  this.calculations = params.calculations;
7041
7165
  this.calculationOfParentsFromLinks = params.calculationOfParentsFromLinks;
@@ -7049,7 +7173,7 @@ var CalculationOfParent = class {
7049
7173
  const allLinkedTasks = this.getArrayOfIdOfLinkedActivities(
7050
7174
  this.activity[this.linkProperty]
7051
7175
  );
7052
- if (this.direction === "backward") {
7176
+ if (this.direction === CALCULATION_DIRECTION.BACKWARD) {
7053
7177
  const restrictions = [CONSTRAINT_TYPES.FNLT];
7054
7178
  if (this.shouldCalculateParentWithLinksBackward(restrictions)) {
7055
7179
  this.calculateAndStoreParentWithLinks(this.activity);
@@ -7062,10 +7186,10 @@ var CalculationOfParent = class {
7062
7186
  }
7063
7187
  const areAllLinksCalculated = this.areAllLinksCalculated(allLinkedTasks);
7064
7188
  if (areAllLinksCalculated && this.calculationsOfParentThatImpactChildrens.has(this.activity.id)) {
7065
- if (this.direction === "forward") {
7189
+ if (this.direction === CALCULATION_DIRECTION.FORWARD) {
7066
7190
  this.setDatesToParentsWithLinks();
7067
7191
  }
7068
- if (this.direction === "backward") {
7192
+ if (this.direction === CALCULATION_DIRECTION.BACKWARD) {
7069
7193
  this.setDatesToParentsWithLinksBackward();
7070
7194
  }
7071
7195
  return;
@@ -7266,7 +7390,7 @@ var ThirdLevelActivityIdentifier = class {
7266
7390
  this.addActivityToLevel(activity, activitiesByLevel);
7267
7391
  }
7268
7392
  isProjectActivity(activity) {
7269
- return activity.type === "project";
7393
+ return activity.type === ACTIVITY_TYPE.PROJECT;
7270
7394
  }
7271
7395
  hasLink(activity) {
7272
7396
  return Boolean(activity[this.linkProperty]?.length);
@@ -7335,8 +7459,8 @@ var CriticalPathHelpers = class {
7335
7459
  constructor(ganttInstace, direction) {
7336
7460
  this.direction = direction;
7337
7461
  this.gantt = ganttInstace;
7338
- this.linkProperty = this.direction === "forward" ? "$target" : "$source";
7339
- this.linkDirection = this.direction === "forward" ? "source" : "target";
7462
+ this.linkProperty = this.direction === CALCULATION_DIRECTION.FORWARD ? "$target" : GANTT_FIELD.SOURCE;
7463
+ this.linkDirection = this.direction === CALCULATION_DIRECTION.FORWARD ? "source" : "target";
7340
7464
  this.projectDates = ganttInstace.getSubtaskDates();
7341
7465
  }
7342
7466
  tryToCalculateLastLevelChildrens() {
@@ -7428,7 +7552,7 @@ var CriticalPathHelpers = class {
7428
7552
  function(activity) {
7429
7553
  const parentId = Number(activity.parent);
7430
7554
  allTasks.add(activity.id);
7431
- if (activity.type === "project") {
7555
+ if (activity.type === ACTIVITY_TYPE.PROJECT) {
7432
7556
  const parentInfo = {
7433
7557
  level: activity["$level"],
7434
7558
  hasLink: Boolean(activity[this.linkProperty].length),
@@ -7449,7 +7573,7 @@ var CriticalPathHelpers = class {
7449
7573
  }
7450
7574
  level.get(Number(activity.parent)).push({
7451
7575
  id: activity.id,
7452
- isParent: activity.type === "project",
7576
+ isParent: activity.type === ACTIVITY_TYPE.PROJECT,
7453
7577
  calculated: false
7454
7578
  });
7455
7579
  }.bind(this),
@@ -7499,7 +7623,7 @@ var CriticalPathHelpers = class {
7499
7623
  }
7500
7624
  calculateSecondLevelActivities() {
7501
7625
  try {
7502
- if (this.direction === "forward") {
7626
+ if (this.direction === CALCULATION_DIRECTION.FORWARD) {
7503
7627
  this.recursiveCalculateEfAndEs(
7504
7628
  Array.from(this.secondLevelActivities),
7505
7629
  0,
@@ -7517,12 +7641,12 @@ var CriticalPathHelpers = class {
7517
7641
  this.chainStartActivities.forEach((activity) => {
7518
7642
  if (!activity) return;
7519
7643
  if (activity.progress > 100) return;
7520
- if (activity.type === "project") return;
7644
+ if (activity.type === ACTIVITY_TYPE.PROJECT) return;
7521
7645
  const dates = this.calculateStartAndFinishOfChainOrigin(
7522
7646
  activity,
7523
7647
  this.direction
7524
7648
  );
7525
- if (this.direction === "forward") {
7649
+ if (this.direction === CALCULATION_DIRECTION.FORWARD) {
7526
7650
  let { es, ef } = dates;
7527
7651
  this.calculations.set(activity.id, { es, ef, text: activity.text });
7528
7652
  this.activitiesWaitingForCalculation.delete(activity.id);
@@ -7603,7 +7727,7 @@ var CriticalPathHelpers = class {
7603
7727
  );
7604
7728
  }
7605
7729
  let direction = customDirection || this.direction;
7606
- if (direction === "forward") {
7730
+ if (direction === CALCULATION_DIRECTION.FORWARD) {
7607
7731
  let es = activity.start_date;
7608
7732
  let ef = activity.end_date;
7609
7733
  return {
@@ -7714,14 +7838,14 @@ var CriticalPathHelpers = class {
7714
7838
  }
7715
7839
  );
7716
7840
  arrayOfActivitiesObject.forEach((activity) => {
7717
- const isAParent = activity.type === "project";
7841
+ const isAParent = activity.type === ACTIVITY_TYPE.PROJECT;
7718
7842
  this.setDatesForActivityWithFullProgress(activity);
7719
7843
  this.activitiesWaitingForCalculation.delete(activity.id);
7720
7844
  if (isAParent && this.pendingParentsWithLinks.has(activity.id)) {
7721
7845
  this.parentCalculationFromChildren.add(activity.id);
7722
7846
  this.calculationsOfParentThatImpactChildrens.set(activity.id, {
7723
- [this.direction === "forward" ? "es" : "ls"]: activity.start_date,
7724
- [this.direction === "forward" ? "ef" : "lf"]: activity.end_date
7847
+ [this.direction === CALCULATION_DIRECTION.FORWARD ? "es" : "ls"]: activity.start_date,
7848
+ [this.direction === CALCULATION_DIRECTION.FORWARD ? "ef" : "lf"]: activity.end_date
7725
7849
  });
7726
7850
  this.calculationOfParentsFromLinks.add(activity.id);
7727
7851
  }
@@ -7816,7 +7940,7 @@ var LinksRulesCalculationsMethods = class {
7816
7940
  }
7817
7941
  return this.calculatedActivities.get(Number(activity));
7818
7942
  }
7819
- calculateSucessorTimes(predecessorTime, esDataCalculation, efDataCalculation = 0, lag, restrictionOfLink = LINK_TYPES2.FS) {
7943
+ calculateSucessorTimes(predecessorTime, esDataCalculation, efDataCalculation = 0, lag, restrictionOfLink = LINK_TYPES3.FS) {
7820
7944
  const activityCalendar = this.gantt.getCalendar(
7821
7945
  this.referenceActivity.calendar_id
7822
7946
  );
@@ -7828,9 +7952,9 @@ var LinksRulesCalculationsMethods = class {
7828
7952
  let dateBaseToCalculate = predecessorTime;
7829
7953
  let es = null;
7830
7954
  let ef = null;
7831
- const isAMilestone = this.referenceActivity.type === "milestone";
7955
+ const isAMilestone = this.referenceActivity.type === ACTIVITY_TYPE.MILESTONE;
7832
7956
  if (!isAMilestone) {
7833
- if (restrictionOfLink === LINK_TYPES2.FS && lag === 0) {
7957
+ if (restrictionOfLink === LINK_TYPES3.FS && lag === 0) {
7834
7958
  dateBaseToCalculate = getNextWorkingHour({
7835
7959
  dateBaseToCalculate,
7836
7960
  activityCalendar,
@@ -7845,7 +7969,7 @@ var LinksRulesCalculationsMethods = class {
7845
7969
  );
7846
7970
  }
7847
7971
  }
7848
- if ([LINK_TYPES2.FF, LINK_TYPES2.SF].includes(restrictionOfLink)) {
7972
+ if ([LINK_TYPES3.FF, LINK_TYPES3.SF].includes(restrictionOfLink)) {
7849
7973
  ef = addDurationToDate(
7850
7974
  activityCalendar,
7851
7975
  dateBaseToCalculate,
@@ -7899,7 +8023,7 @@ var LinksRulesCalculationsMethods = class {
7899
8023
  esDataCalculation,
7900
8024
  efDataCalculation,
7901
8025
  lag,
7902
- LINK_TYPES2.SS
8026
+ LINK_TYPES3.SS
7903
8027
  );
7904
8028
  }
7905
8029
  calculateFF(link) {
@@ -7913,7 +8037,7 @@ var LinksRulesCalculationsMethods = class {
7913
8037
  esDataCalculation,
7914
8038
  efDataCalculation,
7915
8039
  lag,
7916
- LINK_TYPES2.FF
8040
+ LINK_TYPES3.FF
7917
8041
  );
7918
8042
  }
7919
8043
  calculateFS(link) {
@@ -7927,7 +8051,7 @@ var LinksRulesCalculationsMethods = class {
7927
8051
  esDataCalculation,
7928
8052
  efDataCalculation,
7929
8053
  lag,
7930
- LINK_TYPES2.FS
8054
+ LINK_TYPES3.FS
7931
8055
  );
7932
8056
  }
7933
8057
  calculateSF(link) {
@@ -7941,17 +8065,17 @@ var LinksRulesCalculationsMethods = class {
7941
8065
  esDataCalculation,
7942
8066
  efDataCalculation,
7943
8067
  lag,
7944
- LINK_TYPES2.SF
8068
+ LINK_TYPES3.SF
7945
8069
  );
7946
8070
  }
7947
8071
  mutateTheDateToFutureOrPastInBaseRestriction(dateBaseToCalculate, restrictionOfLink, activityCalendar) {
7948
- if (![LINK_TYPES2.FS, LINK_TYPES2.SS, LINK_TYPES2.FF].includes(restrictionOfLink)) {
8072
+ if (![LINK_TYPES3.FS, LINK_TYPES3.SS, LINK_TYPES3.FF].includes(restrictionOfLink)) {
7949
8073
  return dateBaseToCalculate;
7950
8074
  }
7951
- const constraintThatGoToNextWorkingHour = [LINK_TYPES2.FS, LINK_TYPES2.SS];
8075
+ const constraintThatGoToNextWorkingHour = [LINK_TYPES3.FS, LINK_TYPES3.SS];
7952
8076
  const direction = constraintThatGoToNextWorkingHour.includes(
7953
8077
  restrictionOfLink
7954
- ) ? "future" : "past";
8078
+ ) ? "future" : WORK_TIME_DIRECTION.PAST;
7955
8079
  return getNextWorkingHour({
7956
8080
  dateBaseToCalculate,
7957
8081
  activityCalendar,
@@ -8032,7 +8156,7 @@ var ActivityCalculator = class {
8032
8156
  const pendingActivities = new Set(pendingToCalculate);
8033
8157
  for (const activityId of pendingToCalculate) {
8034
8158
  const activityData = this.gantt.getTask(activityId);
8035
- if (activityData.type === "project") {
8159
+ if (activityData.type === ACTIVITY_TYPE.PROJECT) {
8036
8160
  this.handleProjectActivity(
8037
8161
  activityId,
8038
8162
  activityData,
@@ -8096,7 +8220,7 @@ var ActivityCalculator = class {
8096
8220
  canCalculateParentActivity(activityData) {
8097
8221
  const hasNoLinks = (activityData[this.linkProperty] || []).length === 0;
8098
8222
  const constraintType = activityData.constraint_type;
8099
- const isSpecialConstraintType = this.direction === "forward" ? constraintType === "fnlt" || constraintType === "snlt" : constraintType === "fnlt";
8223
+ const isSpecialConstraintType = this.direction === CALCULATION_DIRECTION.FORWARD ? constraintType === CONSTRAINT_TYPES.FNLT || constraintType === CONSTRAINT_TYPES.SNLT : constraintType === CONSTRAINT_TYPES.FNLT;
8100
8224
  if (isSpecialConstraintType && hasNoLinks) {
8101
8225
  return true;
8102
8226
  }
@@ -8114,13 +8238,13 @@ var ActivityCalculator = class {
8114
8238
  if (isParentPendingWithLinks && !hasParentCalculationFromLinks) {
8115
8239
  return;
8116
8240
  }
8117
- if (this.direction === "backward") {
8241
+ if (this.direction === CALCULATION_DIRECTION.BACKWARD) {
8118
8242
  const isStartChainChildOfLinkedParent = this.activitiesStartChainButChildrenOfLinkedParents.has(activityId);
8119
8243
  if (isStartChainChildOfLinkedParent && !hasParentCalculationFromLinks) {
8120
8244
  return;
8121
8245
  }
8122
8246
  }
8123
- if (activityData["$target"].length === 0 && activityData["$source"].length === 0) {
8247
+ if (activityData["$target"].length === 0 && activityData[GANTT_FIELD.SOURCE].length === 0) {
8124
8248
  activitiesThatCanBeCalculated.add(activityId);
8125
8249
  pendingActivities.delete(activityId);
8126
8250
  return;
@@ -8131,7 +8255,7 @@ var ActivityCalculator = class {
8131
8255
  const arePredecessorsCalculated = linkedActivities.every(
8132
8256
  (act) => this.calculations.has(act.id)
8133
8257
  );
8134
- if (this.direction === "backward") {
8258
+ if (this.direction === CALCULATION_DIRECTION.BACKWARD) {
8135
8259
  const hasNoLinkedActivities = linkedActivities.length === 0;
8136
8260
  if ((hasNoLinkedActivities || arePredecessorsCalculated) && hasParentCalculationFromLinks) {
8137
8261
  activitiesThatCanBeCalculated.add(activityId);
@@ -8183,7 +8307,7 @@ var get_activities_to_calculate_default = ActivityCalculator;
8183
8307
  var createIsCurrent2 = (calculationId, getCurrentId) => () => getCurrentId() === calculationId;
8184
8308
 
8185
8309
  // src/critical-path/legacy/utils/validation.js
8186
- var shouldAbortCalculation = (gantt) => !gantt?.fullyParsed || typeof window !== "undefined" && window.to_use_react_gantt?.conversionMode?.isActive;
8310
+ var shouldAbortCalculation = (gantt) => !gantt?.fullyParsed;
8187
8311
 
8188
8312
  // src/critical-path/legacy/utils/timing.js
8189
8313
  var TIME_BUDGET_MS = 16;
@@ -8234,7 +8358,7 @@ var iterativeCalculate = async ({
8234
8358
  // src/critical-path/legacy/forward-path/index.js
8235
8359
  var ForwardPath = class extends generic_calculations_default {
8236
8360
  constructor(gantt) {
8237
- super(gantt, "forward");
8361
+ super(gantt, CALCULATION_DIRECTION.FORWARD);
8238
8362
  this.gantt = gantt;
8239
8363
  this.chainStartActivities = /* @__PURE__ */ new Set();
8240
8364
  this.secondLevelActivities = /* @__PURE__ */ new Set();
@@ -8299,7 +8423,7 @@ var ForwardPath = class extends generic_calculations_default {
8299
8423
  calculateStartAndFinishTimes(activitiesToCalculate) {
8300
8424
  activitiesToCalculate.forEach((activity) => {
8301
8425
  const activityReference = this.gantt.getTask(activity);
8302
- if (activityReference.type === "project") {
8426
+ if (activityReference.type === ACTIVITY_TYPE.PROJECT) {
8303
8427
  return this.doCalculationForParentType(activityReference);
8304
8428
  }
8305
8429
  if (!activityReference) {
@@ -8418,11 +8542,11 @@ var ForwardPath = class extends generic_calculations_default {
8418
8542
  this.activitiesWaitingForCalculation.delete(activity);
8419
8543
  });
8420
8544
  }
8421
- getTheGreatesDateBetweenRestrictionAndEsEf(restriction, linkCalculation, comparisonType = "greater") {
8422
- if (comparisonType === "greater") {
8545
+ getTheGreatesDateBetweenRestrictionAndEsEf(restriction, linkCalculation, comparisonType = COMPARISON_DIRECTION.GREATER) {
8546
+ if (comparisonType === COMPARISON_DIRECTION.GREATER) {
8423
8547
  return linkCalculation.ef > restriction.ef ? linkCalculation : restriction;
8424
8548
  }
8425
- if (comparisonType === "less") {
8549
+ if (comparisonType === COMPARISON_DIRECTION.LESS) {
8426
8550
  return linkCalculation.ef < restriction.ef ? linkCalculation : restriction;
8427
8551
  }
8428
8552
  }
@@ -8442,7 +8566,7 @@ var ForwardPath = class extends generic_calculations_default {
8442
8566
  const comparisontype = [
8443
8567
  CONSTRAINT_TYPES.SNET,
8444
8568
  CONSTRAINT_TYPES.FNET
8445
- ].includes(constraintType) ? "greater" : "less";
8569
+ ].includes(constraintType) ? COMPARISON_DIRECTION.GREATER : COMPARISON_DIRECTION.LESS;
8446
8570
  const { es, ef } = this.getTheGreatesDateBetweenRestrictionAndEsEf(
8447
8571
  calculatedRestriction,
8448
8572
  calculatedEsEf,
@@ -8458,9 +8582,9 @@ var ForwardPath = class extends generic_calculations_default {
8458
8582
  }
8459
8583
  const sourceId = ganttActivityLink.source;
8460
8584
  const targetId = ganttActivityLink.target;
8461
- if (!this.gantt.getTask(sourceId) || this.gantt.getTask(sourceId)?.type === "project")
8585
+ if (!this.gantt.getTask(sourceId) || this.gantt.getTask(sourceId)?.type === ACTIVITY_TYPE.PROJECT)
8462
8586
  return;
8463
- if (!this.gantt.getTask(targetId) || this.gantt.getTask(targetId)?.type === "project")
8587
+ if (!this.gantt.getTask(targetId) || this.gantt.getTask(targetId)?.type === ACTIVITY_TYPE.PROJECT)
8464
8588
  return;
8465
8589
  return link;
8466
8590
  }).filter(Boolean);
@@ -8483,7 +8607,7 @@ var CalculationsGenericMethods = class {
8483
8607
  }
8484
8608
  return this.calculatedActivities.get(activity);
8485
8609
  }
8486
- calculateSuccessorTimes(sucessorTime, lsDataCalculation, lfDataCalculation = 0, lag, type = LINK_TYPES2.FS) {
8610
+ calculateSuccessorTimes(sucessorTime, lsDataCalculation, lfDataCalculation = 0, lag, type = LINK_TYPES3.FS) {
8487
8611
  let activityCalendar = this.gantt.getCalendar(this.activity.calendar_id);
8488
8612
  if (!activityCalendar) {
8489
8613
  throw new Error(
@@ -8491,7 +8615,7 @@ var CalculationsGenericMethods = class {
8491
8615
  );
8492
8616
  }
8493
8617
  const workTime = sucessorTime;
8494
- let isMilestone = this.activity.type === "milestone";
8618
+ let isMilestone = this.activity.type === ACTIVITY_TYPE.MILESTONE;
8495
8619
  if (isMilestone && lag === 0) {
8496
8620
  let lsPred = addDurationToDate(
8497
8621
  activityCalendar,
@@ -8515,19 +8639,19 @@ var CalculationsGenericMethods = class {
8515
8639
  lfDataCalculation,
8516
8640
  isMilestone
8517
8641
  };
8518
- if (type === LINK_TYPES2.FS) {
8642
+ if (type === LINK_TYPES3.FS) {
8519
8643
  let { ls, lf } = this.calculateFsLink(valuesToDoCalculation);
8520
8644
  return { ls, lf };
8521
8645
  }
8522
- if (type === LINK_TYPES2.FF) {
8646
+ if (type === LINK_TYPES3.FF) {
8523
8647
  let { ls, lf } = this.calculateFFLink(valuesToDoCalculation);
8524
8648
  return { ls, lf };
8525
8649
  }
8526
- if (type === LINK_TYPES2.SS) {
8650
+ if (type === LINK_TYPES3.SS) {
8527
8651
  let { ls, lf } = this.calculateSSlink(valuesToDoCalculation);
8528
8652
  return { ls, lf };
8529
8653
  }
8530
- if (type === LINK_TYPES2.SF) {
8654
+ if (type === LINK_TYPES3.SF) {
8531
8655
  let { ls, lf } = this.calculateSFLink(valuesToDoCalculation);
8532
8656
  return { ls, lf };
8533
8657
  }
@@ -8542,7 +8666,7 @@ var CalculationsGenericMethods = class {
8542
8666
  lsDataForCalculation,
8543
8667
  lfDataForCalculation,
8544
8668
  lag,
8545
- LINK_TYPES2.SS
8669
+ LINK_TYPES3.SS
8546
8670
  );
8547
8671
  }
8548
8672
  calculateFF(link, constraint) {
@@ -8559,7 +8683,7 @@ var CalculationsGenericMethods = class {
8559
8683
  lsDataForCalculation,
8560
8684
  lfDataForCalculation,
8561
8685
  lag,
8562
- LINK_TYPES2.FF
8686
+ LINK_TYPES3.FF
8563
8687
  );
8564
8688
  }
8565
8689
  calculateFS(link, constraint) {
@@ -8577,7 +8701,7 @@ var CalculationsGenericMethods = class {
8577
8701
  lsDataForCalculation,
8578
8702
  lfDataForCalculation,
8579
8703
  lag,
8580
- LINK_TYPES2.FS
8704
+ LINK_TYPES3.FS
8581
8705
  );
8582
8706
  }
8583
8707
  calculateSF(link, getFromForward = false) {
@@ -8590,7 +8714,7 @@ var CalculationsGenericMethods = class {
8590
8714
  lsDataForCalculation,
8591
8715
  lfDataForCalculation,
8592
8716
  lag,
8593
- LINK_TYPES2.SF
8717
+ LINK_TYPES3.SF
8594
8718
  );
8595
8719
  }
8596
8720
  getEarlyStartFromForwardPath(link) {
@@ -8613,10 +8737,10 @@ var CalculationsGenericMethods = class {
8613
8737
  this.activity
8614
8738
  );
8615
8739
  }
8616
- getLastWorkingHour(date2, activityCalendar, dir = "past") {
8740
+ getLastWorkingHour(date2, activityCalendar, dir = WORK_TIME_DIRECTION.PAST) {
8617
8741
  const normalizedDate = date2 instanceof Date ? date2 : new Date(date2);
8618
8742
  let resetedDate = moment_default(normalizedDate).clone();
8619
- if (this.isActivityInInitHour(activityCalendar, normalizedDate) && dir === "past") {
8743
+ if (this.isActivityInInitHour(activityCalendar, normalizedDate) && dir === WORK_TIME_DIRECTION.PAST) {
8620
8744
  resetedDate = resetedDate.hours(0).minutes(0).seconds(0).milliseconds(0);
8621
8745
  }
8622
8746
  let newDate = getNextWorkingHour({
@@ -8659,7 +8783,7 @@ var CalculationsGenericMethods = class {
8659
8783
  const lsSucessor2 = this.getLastWorkingHour(
8660
8784
  workTime,
8661
8785
  activityCalendar,
8662
- "past"
8786
+ WORK_TIME_DIRECTION.PAST
8663
8787
  );
8664
8788
  lfPred = addDurationToDate(
8665
8789
  activityCalendar,
@@ -8667,7 +8791,7 @@ var CalculationsGenericMethods = class {
8667
8791
  lfDataCalculation,
8668
8792
  this.activity
8669
8793
  );
8670
- lfPred = this.getLastWorkingHour(lfPred, activityCalendar, "past");
8794
+ lfPred = this.getLastWorkingHour(lfPred, activityCalendar, WORK_TIME_DIRECTION.PAST);
8671
8795
  lsPred = addDurationToDate(
8672
8796
  activityCalendar,
8673
8797
  lfPred,
@@ -8693,7 +8817,7 @@ var CalculationsGenericMethods = class {
8693
8817
  this.activity
8694
8818
  );
8695
8819
  if (!isMilestone) {
8696
- lfPred = this.getLastWorkingHour(lfPred, activityCalendar, "past", true);
8820
+ lfPred = this.getLastWorkingHour(lfPred, activityCalendar, WORK_TIME_DIRECTION.PAST, true);
8697
8821
  }
8698
8822
  return { ls: lsPred, lf: lfPred };
8699
8823
  }
@@ -8726,7 +8850,7 @@ var CalculationsGenericMethods = class {
8726
8850
  lfSucessor = this.getLastWorkingHour(
8727
8851
  lfSucessor,
8728
8852
  activityCalendar,
8729
- "past"
8853
+ WORK_TIME_DIRECTION.PAST
8730
8854
  );
8731
8855
  }
8732
8856
  lfPred = addDurationToDate(
@@ -8840,7 +8964,7 @@ var LinksConstraintCalculator2 = class extends CalculationsGenericMethods_defaul
8840
8964
  if (this.links.length === 0) {
8841
8965
  return new generic_calculations_default(
8842
8966
  this.gantt,
8843
- "backward"
8967
+ CALCULATION_DIRECTION.BACKWARD
8844
8968
  ).calculateStartAndFinishOfChainOrigin(this.activity);
8845
8969
  }
8846
8970
  let activityProgressMajorThanZeroButLessThanOneHundred = this.activity.progress > 0 && this.activity.progress < 100;
@@ -8952,7 +9076,7 @@ var LinksConstraintCalculator2 = class extends CalculationsGenericMethods_defaul
8952
9076
  if (!activityFromLink) {
8953
9077
  return;
8954
9078
  }
8955
- if (activityFromLink.progress > 0 && activityFromLink.type !== "project") {
9079
+ if (activityFromLink.progress > 0 && activityFromLink.type !== ACTIVITY_TYPE.PROJECT) {
8956
9080
  return;
8957
9081
  }
8958
9082
  const specialParamForFS = this.getSpecialCalculationParamForConstraintLink();
@@ -9085,7 +9209,7 @@ var restrictionCalculation_default2 = calculateRestriction3;
9085
9209
  // src/critical-path/legacy/backward-path/index.js
9086
9210
  var BackwardPath = class extends generic_calculations_default {
9087
9211
  constructor(ganttInstance, forwardPathCalculations, forwardConstraintsMap) {
9088
- super(ganttInstance, "backward");
9212
+ super(ganttInstance, CALCULATION_DIRECTION.BACKWARD);
9089
9213
  this.gantt = ganttInstance;
9090
9214
  this.chainStartActivities = /* @__PURE__ */ new Set();
9091
9215
  this.secondLevelActivities = /* @__PURE__ */ new Set();
@@ -9204,7 +9328,7 @@ var BackwardPath = class extends generic_calculations_default {
9204
9328
  activityReference
9205
9329
  );
9206
9330
  }
9207
- if (activityReference.type === "project") {
9331
+ if (activityReference.type === ACTIVITY_TYPE.PROJECT) {
9208
9332
  return this.doCalculationForParentType(activityReference);
9209
9333
  }
9210
9334
  if (progress === 100) {
@@ -9285,7 +9409,7 @@ var BackwardPath = class extends generic_calculations_default {
9285
9409
  if (!activityData) {
9286
9410
  continue;
9287
9411
  }
9288
- if (activityData.type === "project") {
9412
+ if (activityData.type === ACTIVITY_TYPE.PROJECT) {
9289
9413
  allLinkedHasProgress = false;
9290
9414
  }
9291
9415
  if (activityData.progress === 0) {
@@ -9304,7 +9428,7 @@ var BackwardPath = class extends generic_calculations_default {
9304
9428
  const parent = Number(activity.parent);
9305
9429
  let { ls, lf } = this.calculateStartAndFinishOfChainOrigin(
9306
9430
  activity,
9307
- "backward"
9431
+ CALCULATION_DIRECTION.BACKWARD
9308
9432
  );
9309
9433
  if (this.calculationsOfParentThatImpactChildrens.has(parent)) {
9310
9434
  ls = activity.start_date;
@@ -9373,9 +9497,9 @@ var BackwardPath = class extends generic_calculations_default {
9373
9497
  return links.map((link) => {
9374
9498
  let sourceId = this.gantt.getLink(link).source;
9375
9499
  let targetId = this.gantt.getLink(link).target;
9376
- if (!this.gantt.getTask(sourceId) || this.gantt.getTask(sourceId)?.type === "project")
9500
+ if (!this.gantt.getTask(sourceId) || this.gantt.getTask(sourceId)?.type === ACTIVITY_TYPE.PROJECT)
9377
9501
  return;
9378
- if (!this.gantt.getTask(targetId) || this.gantt.getTask(targetId)?.type === "project")
9502
+ if (!this.gantt.getTask(targetId) || this.gantt.getTask(targetId)?.type === ACTIVITY_TYPE.PROJECT)
9379
9503
  return;
9380
9504
  return link;
9381
9505
  }).filter(Boolean);
@@ -10077,7 +10201,7 @@ var CriticalPath = class {
10077
10201
  var legacy_default = CriticalPath;
10078
10202
 
10079
10203
  // src/critical-path/gantt-adapter.ts
10080
- var isFinishConstraint = (type) => type === "fnet" || type === "fnlt" || type === "mfo";
10204
+ var isFinishConstraint = (type) => type === CONSTRAINT_TYPE.FNET || type === CONSTRAINT_TYPE.FNLT || type === CONSTRAINT_TYPE.MFO;
10081
10205
  var startOfUtcDay3 = (date2) => new Date(
10082
10206
  Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())
10083
10207
  );
@@ -10559,38 +10683,38 @@ var NON_SCHEDULING_INLINE_COLUMNS = /* @__PURE__ */ new Set([
10559
10683
  COLUMN.TAGS
10560
10684
  ]);
10561
10685
  var NON_SCHEDULING_KINDS = /* @__PURE__ */ new Set([
10562
- "activity-clipboard-clear",
10563
- "activity-copy",
10564
- "selection-toggle",
10565
- "selection-replace",
10566
- "visibility-set",
10567
- "filter-set",
10568
- "sort-set",
10569
- "sir-sync",
10570
- "activity-lookahead-sync",
10571
- "persistence-acknowledge",
10572
- "baseline-apply",
10573
- "ponderator-criterion-set",
10574
- "status-criteria-set"
10686
+ DISPATCH_ACTION_KIND.ACTIVITY_CLIPBOARD_CLEAR,
10687
+ DISPATCH_ACTION_KIND.ACTIVITY_COPY,
10688
+ DISPATCH_ACTION_KIND.SELECTION_TOGGLE,
10689
+ DISPATCH_ACTION_KIND.SELECTION_REPLACE,
10690
+ DISPATCH_ACTION_KIND.VISIBILITY_SET,
10691
+ DISPATCH_ACTION_KIND.FILTER_SET,
10692
+ DISPATCH_ACTION_KIND.SORT_SET,
10693
+ DISPATCH_ACTION_KIND.SIR_SYNC,
10694
+ DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC,
10695
+ DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE,
10696
+ DISPATCH_ACTION_KIND.BASELINE_APPLY,
10697
+ DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET,
10698
+ DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET
10575
10699
  ]);
10576
10700
  var PURE_VIEW_STATE_KINDS = /* @__PURE__ */ new Set([
10577
- "activity-clipboard-clear",
10578
- "activity-copy",
10579
- "selection-toggle",
10580
- "selection-replace",
10581
- "visibility-set",
10582
- "filter-set",
10583
- "sort-set"
10701
+ DISPATCH_ACTION_KIND.ACTIVITY_CLIPBOARD_CLEAR,
10702
+ DISPATCH_ACTION_KIND.ACTIVITY_COPY,
10703
+ DISPATCH_ACTION_KIND.SELECTION_TOGGLE,
10704
+ DISPATCH_ACTION_KIND.SELECTION_REPLACE,
10705
+ DISPATCH_ACTION_KIND.VISIBILITY_SET,
10706
+ DISPATCH_ACTION_KIND.FILTER_SET,
10707
+ DISPATCH_ACTION_KIND.SORT_SET
10584
10708
  ]);
10585
10709
  function reappliesViewState(action) {
10586
10710
  return !PURE_VIEW_STATE_KINDS.has(action.kind);
10587
10711
  }
10588
10712
  var NO_STRUCTURAL_EXEMPTIONS = /* @__PURE__ */ new Set();
10589
10713
  function editsOnlyNonSchedulingColumns(action) {
10590
- if (action.kind === "inline-edit") {
10714
+ if (action.kind === DISPATCH_ACTION_KIND.INLINE_EDIT) {
10591
10715
  return NON_SCHEDULING_INLINE_COLUMNS.has(action.column);
10592
10716
  }
10593
- if (action.kind === "bulk-edit") {
10717
+ if (action.kind === DISPATCH_ACTION_KIND.BULK_EDIT) {
10594
10718
  return action.edits.every(
10595
10719
  (edit) => NON_SCHEDULING_INLINE_COLUMNS.has(edit.column)
10596
10720
  );
@@ -10604,13 +10728,13 @@ function isSchedulingDispatch(action, structuralStaleKinds) {
10604
10728
  return true;
10605
10729
  }
10606
10730
  function dispatchChangesSchedulingState(action) {
10607
- if (action.kind === "activity-lookahead-sync") {
10731
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC) {
10608
10732
  return action.persistedProgress !== void 0;
10609
10733
  }
10610
10734
  return isSchedulingDispatch(action, NO_STRUCTURAL_EXEMPTIONS);
10611
10735
  }
10612
10736
  function resolveRunCriticalPath(action) {
10613
- if (action.kind === "activity-lookahead-sync") {
10737
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC) {
10614
10738
  return action.persistedProgress !== void 0;
10615
10739
  }
10616
10740
  return isSchedulingDispatch(
@@ -10625,9 +10749,11 @@ function resolveRunExpectedProgress(action) {
10625
10749
  );
10626
10750
  }
10627
10751
  function dispatchChangesProgress(action) {
10628
- if (action.kind === "activity-set-progress") return true;
10629
- if (action.kind === "inline-edit") return action.column === COLUMN.PROGRESS;
10630
- if (action.kind === "bulk-edit") {
10752
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_SET_PROGRESS) return true;
10753
+ if (action.kind === DISPATCH_ACTION_KIND.INLINE_EDIT) {
10754
+ return action.column === COLUMN.PROGRESS;
10755
+ }
10756
+ if (action.kind === DISPATCH_ACTION_KIND.BULK_EDIT) {
10631
10757
  return action.edits.some((edit) => edit.column === COLUMN.PROGRESS);
10632
10758
  }
10633
10759
  return false;
@@ -10644,11 +10770,11 @@ var PROGRESS_AFFECTING_COLUMNS = /* @__PURE__ */ new Set([
10644
10770
  COLUMN.REAL_COST
10645
10771
  ]);
10646
10772
  function shouldRecomputeParentProgress(action) {
10647
- if (action.kind === "activity-set-progress") return true;
10648
- if (action.kind === "inline-edit") {
10773
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_SET_PROGRESS) return true;
10774
+ if (action.kind === DISPATCH_ACTION_KIND.INLINE_EDIT) {
10649
10775
  return PROGRESS_AFFECTING_COLUMNS.has(action.column);
10650
10776
  }
10651
- if (action.kind === "bulk-edit") {
10777
+ if (action.kind === DISPATCH_ACTION_KIND.BULK_EDIT) {
10652
10778
  return action.edits.some(
10653
10779
  (edit) => PROGRESS_AFFECTING_COLUMNS.has(edit.column)
10654
10780
  );
@@ -10684,7 +10810,103 @@ function resolveDerivedPasses(action, autoSchedule, options) {
10684
10810
  return passes;
10685
10811
  }
10686
10812
 
10813
+ // src/internal/state/write-capture.ts
10814
+ var WRITE_OPERATION_KIND = {
10815
+ INSERT: "insert",
10816
+ REMOVE: "remove",
10817
+ LINK_ADD: "link-add",
10818
+ LINK_REMOVE: "link-remove",
10819
+ LINK_FIELD: "link-field"
10820
+ };
10821
+ var WriteCapture = class {
10822
+ _journal = null;
10823
+ begin() {
10824
+ this._journal = {
10825
+ dirty: /* @__PURE__ */ new Set(),
10826
+ before: /* @__PURE__ */ new Map(),
10827
+ ops: [],
10828
+ linkFieldCaptured: /* @__PURE__ */ new Set(),
10829
+ correlativeBefore: /* @__PURE__ */ new Map(),
10830
+ scheduledBefore: /* @__PURE__ */ new Map(),
10831
+ progressFallbackBefore: /* @__PURE__ */ new Map()
10832
+ };
10833
+ }
10834
+ peek() {
10835
+ return this._journal;
10836
+ }
10837
+ end() {
10838
+ this._journal = null;
10839
+ }
10840
+ note(key, current) {
10841
+ const journal = this._journal;
10842
+ if (!journal) return;
10843
+ if (!journal.before.has(key))
10844
+ journal.before.set(key, cloneCoreActivity(current));
10845
+ journal.dirty.add(key);
10846
+ }
10847
+ noteInsert(activityId) {
10848
+ this._journal?.ops.push({ kind: WRITE_OPERATION_KIND.INSERT, activityId });
10849
+ }
10850
+ noteRemove(activityId, current) {
10851
+ this._journal?.ops.push({
10852
+ kind: WRITE_OPERATION_KIND.REMOVE,
10853
+ activityId,
10854
+ before: cloneCoreActivity(current)
10855
+ });
10856
+ }
10857
+ noteLinkAdd(linkId) {
10858
+ this._journal?.ops.push({ kind: WRITE_OPERATION_KIND.LINK_ADD, linkId });
10859
+ }
10860
+ noteLinkRemove(linkId, current) {
10861
+ this._journal?.ops.push({
10862
+ kind: WRITE_OPERATION_KIND.LINK_REMOVE,
10863
+ linkId,
10864
+ before: cloneLink(current)
10865
+ });
10866
+ }
10867
+ noteCorrelativeBefore(activityId, before) {
10868
+ const journal = this._journal;
10869
+ if (!journal || journal.correlativeBefore.has(activityId)) return;
10870
+ const capturedBefore = journal.before.get(activityId)?.correlativeId;
10871
+ journal.correlativeBefore.set(
10872
+ activityId,
10873
+ typeof capturedBefore === "number" ? capturedBefore : before
10874
+ );
10875
+ }
10876
+ noteScheduledBefore(activityId, current) {
10877
+ const journal = this._journal;
10878
+ if (!journal) return;
10879
+ const beforeImage = cloneCoreActivity(current);
10880
+ if (!journal.scheduledBefore.has(activityId)) {
10881
+ journal.scheduledBefore.set(activityId, beforeImage);
10882
+ }
10883
+ if (!journal.before.has(activityId)) {
10884
+ journal.before.set(activityId, beforeImage);
10885
+ }
10886
+ journal.dirty.add(activityId);
10887
+ }
10888
+ noteLinkField(linkId, current) {
10889
+ const journal = this._journal;
10890
+ if (!journal || journal.linkFieldCaptured.has(linkId)) return;
10891
+ journal.linkFieldCaptured.add(linkId);
10892
+ journal.ops.push({
10893
+ kind: WRITE_OPERATION_KIND.LINK_FIELD,
10894
+ linkId,
10895
+ before: cloneLink(current)
10896
+ });
10897
+ }
10898
+ noteProgressFallback(activityId, current) {
10899
+ const journal = this._journal;
10900
+ if (!journal || journal.progressFallbackBefore.has(activityId)) return;
10901
+ journal.progressFallbackBefore.set(activityId, current);
10902
+ }
10903
+ };
10904
+ function cloneLink(link) {
10905
+ return { ...link };
10906
+ }
10907
+
10687
10908
  // src/dispatch/shared/post-mutation.ts
10909
+ var AUTOSCHEDULE_SCOPE = { ROOTS: "roots" };
10688
10910
  async function runPostMutation(deps, args) {
10689
10911
  const progressInvalidation = resolveProgressInvalidation(deps.adapter);
10690
10912
  const passes = resolvePasses(args, progressInvalidation);
@@ -10740,10 +10962,10 @@ function resolveProgressInvalidation(adapter) {
10740
10962
  }
10741
10963
  function collectStructuralProgressInvalidations(adapter, operations, affectParent) {
10742
10964
  for (const operation of operations) {
10743
- if (operation.kind === "insert") {
10965
+ if (operation.kind === WRITE_OPERATION_KIND.INSERT) {
10744
10966
  const inserted = adapter.getActivity(operation.activityId);
10745
10967
  if (inserted) affectParent(inserted.parentId);
10746
- } else if (operation.kind === "remove") {
10968
+ } else if (operation.kind === WRITE_OPERATION_KIND.REMOVE) {
10747
10969
  affectParent(operation.before.parentId);
10748
10970
  }
10749
10971
  }
@@ -10767,7 +10989,7 @@ function collectFieldProgressInvalidations(adapter, beforeById, dirtySeeds, affe
10767
10989
  }
10768
10990
  }
10769
10991
  async function runAutoschedule(deps, autoscheduleFrom, preventSummaryTargetPullback = false) {
10770
- const options = autoscheduleFrom === "roots" ? {} : { triggerId: autoscheduleFrom };
10992
+ const options = autoscheduleFrom === AUTOSCHEDULE_SCOPE.ROOTS ? {} : { triggerId: autoscheduleFrom };
10771
10993
  if (preventSummaryTargetPullback) {
10772
10994
  options.preventSummaryTargetPullback = true;
10773
10995
  }
@@ -10858,7 +11080,10 @@ var CONSTRAINT_EDIT_COLUMNS = /* @__PURE__ */ new Set([
10858
11080
  COLUMN.CONSTRAINT_TYPE,
10859
11081
  COLUMN.CONSTRAINT_DATE
10860
11082
  ]);
10861
- var MUST_CONSTRAINTS = /* @__PURE__ */ new Set(["mso", "mfo"]);
11083
+ var MUST_CONSTRAINTS = /* @__PURE__ */ new Set([
11084
+ CONSTRAINT_TYPE.MSO,
11085
+ CONSTRAINT_TYPE.MFO
11086
+ ]);
10862
11087
  function isConstraintEditColumn(column) {
10863
11088
  return CONSTRAINT_EDIT_COLUMNS.has(column);
10864
11089
  }
@@ -10989,6 +11214,10 @@ function snapshotToLink(l) {
10989
11214
  }
10990
11215
 
10991
11216
  // src/dispatch/shared/change-set.ts
11217
+ var SIR_DETECTION_PHASE = {
11218
+ BEFORE_DIFF: "before-diff",
11219
+ AFTER_DIFF: "after-diff"
11220
+ };
10992
11221
  async function assembleChangeSet(adapter, args) {
10993
11222
  const allTouched = collectChangeSetIds(adapter, args);
10994
11223
  const before = new Map(args.beforeSnap);
@@ -10998,7 +11227,7 @@ async function assembleChangeSet(adapter, args) {
10998
11227
  mergeDirtyBeforeImages(adapter, captured, insertedIds, before, allTouched);
10999
11228
  }
11000
11229
  const sirDetection = args.sirDetection;
11001
- const beforeDiffEffects = sirDetection === "before-diff" ? detectSirAutoReject(before, adapter, allTouched) : [];
11230
+ const beforeDiffEffects = sirDetection === SIR_DETECTION_PHASE.BEFORE_DIFF ? detectSirAutoReject(before, adapter, allTouched) : [];
11002
11231
  const correlativeBefore = buildCorrelativeBeforeMap(
11003
11232
  args.correlativeShifts,
11004
11233
  allTouched
@@ -11009,7 +11238,7 @@ async function assembleChangeSet(adapter, args) {
11009
11238
  allTouched,
11010
11239
  correlativeBefore
11011
11240
  );
11012
- const effects = sirDetection === "after-diff" ? detectSirAutoReject(before, adapter, allTouched) : beforeDiffEffects;
11241
+ const effects = sirDetection === SIR_DETECTION_PHASE.AFTER_DIFF ? detectSirAutoReject(before, adapter, allTouched) : beforeDiffEffects;
11013
11242
  const warnings = args.warnings ?? [];
11014
11243
  const linkChanges = mergeLinkChanges(
11015
11244
  args.links ?? [],
@@ -11028,7 +11257,7 @@ async function assembleChangeSet(adapter, args) {
11028
11257
  function buildCapturedCriticalPathLinkChanges(adapter, captured) {
11029
11258
  const changes = [];
11030
11259
  for (const operation of captured.ops) {
11031
- if (operation.kind !== "link-field") continue;
11260
+ if (operation.kind !== WRITE_OPERATION_KIND.LINK_FIELD) continue;
11032
11261
  const after = adapter.getLink(operation.linkId);
11033
11262
  if (!after) continue;
11034
11263
  const fields = {};
@@ -11043,7 +11272,7 @@ function buildCapturedCriticalPathLinkChanges(adapter, captured) {
11043
11272
  if (Object.keys(fields).length === 0) continue;
11044
11273
  changes.push({
11045
11274
  id: operation.linkId,
11046
- kind: "updated",
11275
+ kind: ENTITY_CHANGE_KIND.UPDATED,
11047
11276
  fields,
11048
11277
  after: snapshotToLink(after)
11049
11278
  });
@@ -11061,7 +11290,7 @@ function mergeLinkChanges(explicit, captured) {
11061
11290
  continue;
11062
11291
  }
11063
11292
  const current = merged[index];
11064
- if ((current.kind === "updated" || current.kind === "created") && change.kind === "updated") {
11293
+ if ((current.kind === ENTITY_CHANGE_KIND.UPDATED || current.kind === ENTITY_CHANGE_KIND.CREATED) && change.kind === ENTITY_CHANGE_KIND.UPDATED) {
11065
11294
  merged[index] = {
11066
11295
  ...current,
11067
11296
  fields: { ...current.fields, ...change.fields },
@@ -11079,8 +11308,8 @@ function mergeLinkChanges(explicit, captured) {
11079
11308
  continue;
11080
11309
  }
11081
11310
  const current = merged[index];
11082
- if (current.kind === "deleted") continue;
11083
- const capturedFields = current.kind === "created" ? Object.fromEntries(
11311
+ if (current.kind === ENTITY_CHANGE_KIND.DELETED) continue;
11312
+ const capturedFields = current.kind === ENTITY_CHANGE_KIND.CREATED ? Object.fromEntries(
11084
11313
  Object.entries(change.fields ?? {}).map(([field, value]) => [
11085
11314
  field,
11086
11315
  { before: void 0, after: value.after }
@@ -11125,7 +11354,7 @@ function mergeDirtyBeforeImages(adapter, captured, insertedIds, before, touched)
11125
11354
  }
11126
11355
  function collectInsertedIds(captured) {
11127
11356
  return new Set(
11128
- captured.ops.filter((operation) => operation.kind === "insert").map((operation) => operation.activityId)
11357
+ captured.ops.filter((operation) => operation.kind === WRITE_OPERATION_KIND.INSERT).map((operation) => operation.activityId)
11129
11358
  );
11130
11359
  }
11131
11360
 
@@ -11134,7 +11363,7 @@ function buildLinkChangesForBatch(applied, beforeLinks, adapter) {
11134
11363
  const out = [];
11135
11364
  for (const { op, finalLinkId, rejected } of applied) {
11136
11365
  if (rejected !== null) continue;
11137
- if (op.kind === "create") {
11366
+ if (op.kind === LINK_OPERATION_KIND.CREATE) {
11138
11367
  if (!finalLinkId) continue;
11139
11368
  const after = adapter.getLink(finalLinkId);
11140
11369
  if (!after) continue;
@@ -11165,7 +11394,7 @@ function buildLinkChangesForBatch(applied, beforeLinks, adapter) {
11165
11394
  if (Object.keys(fields2).length > 0) {
11166
11395
  out.push({
11167
11396
  id: String(finalLinkId),
11168
- kind: "updated",
11397
+ kind: ENTITY_CHANGE_KIND.UPDATED,
11169
11398
  fields: fields2,
11170
11399
  after: snapshotToLink(after)
11171
11400
  });
@@ -11174,7 +11403,7 @@ function buildLinkChangesForBatch(applied, beforeLinks, adapter) {
11174
11403
  }
11175
11404
  out.push({
11176
11405
  id: String(finalLinkId),
11177
- kind: "created",
11406
+ kind: ENTITY_CHANGE_KIND.CREATED,
11178
11407
  fields: {
11179
11408
  source: { before: void 0, after: String(after.source) },
11180
11409
  target: { before: void 0, after: String(after.target) },
@@ -11185,12 +11414,12 @@ function buildLinkChangesForBatch(applied, beforeLinks, adapter) {
11185
11414
  });
11186
11415
  continue;
11187
11416
  }
11188
- if (op.kind === "delete") {
11417
+ if (op.kind === LINK_OPERATION_KIND.DELETE) {
11189
11418
  if (adapter.getLink(op.linkId)) continue;
11190
11419
  const beforeLink2 = beforeLinks.get(op.linkId);
11191
11420
  out.push({
11192
11421
  id: String(op.linkId),
11193
- kind: "deleted",
11422
+ kind: ENTITY_CHANGE_KIND.DELETED,
11194
11423
  fields: beforeLink2 ? {
11195
11424
  source: { before: String(beforeLink2.source), after: void 0 },
11196
11425
  target: { before: String(beforeLink2.target), after: void 0 },
@@ -11216,7 +11445,7 @@ function buildLinkChangesForBatch(applied, beforeLinks, adapter) {
11216
11445
  }
11217
11446
  out.push({
11218
11447
  id: String(op.linkId),
11219
- kind: "updated",
11448
+ kind: ENTITY_CHANGE_KIND.UPDATED,
11220
11449
  fields,
11221
11450
  after: snapshotToLink(afterLink)
11222
11451
  });
@@ -11242,7 +11471,7 @@ function diffIncomingLinkLagChanges(beforeLags, adapter, activityId) {
11242
11471
  if (before === void 0 || before === Number(link.lag)) continue;
11243
11472
  out.push({
11244
11473
  id: String(link.id),
11245
- kind: "updated",
11474
+ kind: ENTITY_CHANGE_KIND.UPDATED,
11246
11475
  fields: {
11247
11476
  lag: {
11248
11477
  before,
@@ -11384,6 +11613,16 @@ async function dispatchInlineEdit(action, options, deps) {
11384
11613
  name: e.name,
11385
11614
  properties: e.properties ?? {}
11386
11615
  }));
11616
+ if (pipeline.trackEvent && !(action.column === COLUMN.PROGRESS && Number(parsed2.value) <= 0)) {
11617
+ trackingEvents.unshift({
11618
+ name: pipeline.trackEvent,
11619
+ properties: {
11620
+ activity_name: activitySnap.name,
11621
+ activity_id: activitySnap.id,
11622
+ activity_index: activitySnap.correlativeId
11623
+ }
11624
+ });
11625
+ }
11387
11626
  const constraintWarning = toConstraintWarning(
11388
11627
  action.activityId,
11389
11628
  changes.constraintWarning
@@ -11395,7 +11634,7 @@ async function dispatchInlineEdit(action, options, deps) {
11395
11634
  beforeSnap,
11396
11635
  touchedIds,
11397
11636
  scheduledIds,
11398
- sirDetection: "before-diff",
11637
+ sirDetection: SIR_DETECTION_PHASE.BEFORE_DIFF,
11399
11638
  links: linkChanges,
11400
11639
  trackingEvents,
11401
11640
  ...constraintWarning ? { warnings: [constraintWarning] } : {},
@@ -11405,9 +11644,8 @@ async function dispatchInlineEdit(action, options, deps) {
11405
11644
  }
11406
11645
 
11407
11646
  // src/dispatch/handlers/link.ts
11408
- var LINK_TYPE_VALUES = new Set(Object.values(LINK_TYPE));
11409
11647
  function isValidLinkType(value) {
11410
- return typeof value === "string" && LINK_TYPE_VALUES.has(value);
11648
+ return isLinkType(value);
11411
11649
  }
11412
11650
  function hasOwn(value, property) {
11413
11651
  return Object.hasOwn(value, property);
@@ -11620,7 +11858,7 @@ function pickAutoscheduleTrigger(applied, beforeLinks, adapter) {
11620
11858
  if (operation.rejected !== null) continue;
11621
11859
  const target = autoscheduleTarget(operation.op, beforeLinks, adapter);
11622
11860
  if (target !== null)
11623
- return adapter.hasChildren(target) ? "roots" : String(target);
11861
+ return adapter.hasChildren(target) ? AUTOSCHEDULE_SCOPE.ROOTS : String(target);
11624
11862
  }
11625
11863
  return null;
11626
11864
  }
@@ -11666,7 +11904,13 @@ async function dispatchInlineEditLinks(action, options, deps) {
11666
11904
  return { ok: false, reason: REJECTION_REASON.ACTIVITY_NOT_FOUND };
11667
11905
  }
11668
11906
  const isPredecessors = action.column === COLUMN.CUSTOM_PREDECESSORS;
11669
- const { specs: specsInDays } = parsePredecessorString(action.newValue);
11907
+ const { specs: specsInDays, errors } = parsePredecessorString(
11908
+ action.newValue,
11909
+ { daysPerWeek: sector.hoursPerWeek / sector.hoursPerDay }
11910
+ );
11911
+ if (errors.length > 0) {
11912
+ return { ok: false, reason: REJECTION_REASON.INVALID_VALUE };
11913
+ }
11670
11914
  const specs = specsInDays.map((spec) => ({
11671
11915
  ...spec,
11672
11916
  lag: lagDaysToHours(roundLagDays(spec.lag), sector.hoursPerDay)
@@ -11898,9 +12142,9 @@ function readNumber3(activity, key) {
11898
12142
  var NEW_ACTIVITY_DEFAULTS = Object.freeze({
11899
12143
  proplannerId: null,
11900
12144
  description: "",
11901
- type: "task",
12145
+ type: ACTIVITY_TYPE.TASK,
11902
12146
  progress: 0,
11903
- constraintType: "asap",
12147
+ constraintType: CONSTRAINT_TYPE.ASAP,
11904
12148
  constraintDate: null,
11905
12149
  autoScheduling: true,
11906
12150
  assignedDefaultCalendar: false,
@@ -12053,9 +12297,15 @@ function resolveStartDate(parent, fallback, override) {
12053
12297
  }
12054
12298
 
12055
12299
  // src/creation/parent-mutation-pipeline.ts
12300
+ var PARENT_MUTATION_SOURCE = {
12301
+ CREATE: "create",
12302
+ REPARENT: "reparent"
12303
+ };
12056
12304
  function snapshotOf(parent) {
12057
12305
  const type = parent.type;
12058
- if (type !== "task" && type !== "milestone") return null;
12306
+ if (type !== ACTIVITY_TYPE.TASK && type !== ACTIVITY_TYPE.MILESTONE) {
12307
+ return null;
12308
+ }
12059
12309
  const startDate = parent.startDate;
12060
12310
  const endDate = parent.endDate;
12061
12311
  if (!(startDate instanceof Date) || !(endDate instanceof Date)) return null;
@@ -12088,7 +12338,7 @@ function buildParentMutations(input) {
12088
12338
  }
12089
12339
  if (wasPromotableLeaf) {
12090
12340
  fields.type = PROMOTION_TARGET_TYPE;
12091
- if ((input.promotionSource ?? "create") === "create") {
12341
+ if ((input.promotionSource ?? PARENT_MUTATION_SOURCE.CREATE) === PARENT_MUTATION_SOURCE.CREATE) {
12092
12342
  fields.constraintType = CONSTRAINT_TYPE.ASAP;
12093
12343
  fields.constraintDate = null;
12094
12344
  }
@@ -12189,7 +12439,9 @@ function computeFractionalCidAtIndex(adapter, parentKey, targetIndex, excludeId)
12189
12439
 
12190
12440
  // src/dispatch/creation-overrides.ts
12191
12441
  var PUBLIC_CREATION_OVERRIDE_FIELDS = /* @__PURE__ */ new Set([
12192
- ...[...CREATION_OVERRIDE_FIELDS].filter((field) => field !== "durationHours"),
12442
+ ...[...CREATION_OVERRIDE_FIELDS].filter(
12443
+ (field) => field !== ACTIVITY_PROPERTY.DURATION_HOURS
12444
+ ),
12193
12445
  "durationDays"
12194
12446
  ]);
12195
12447
  function normalizeActivityCreationOverrides(raw, hoursPerDay) {
@@ -12211,7 +12463,7 @@ function normalizeActivityCreationOverrides(raw, hoursPerDay) {
12211
12463
  ok: true,
12212
12464
  value: {
12213
12465
  ...rest,
12214
- ...durationDays === 0 && (rest.type === void 0 || rest.type === "task") ? { type: "milestone" } : {},
12466
+ ...durationDays === 0 && (rest.type === void 0 || rest.type === ACTIVITY_TYPE.TASK) ? { type: ACTIVITY_TYPE.MILESTONE } : {},
12215
12467
  ...durationDays === void 0 ? {} : { durationHours: durationToHours(durationDays, hoursPerDay) }
12216
12468
  }
12217
12469
  };
@@ -12542,7 +12794,7 @@ function buildParentDemotionMutations(input) {
12542
12794
  durationHours: canonicalDuration,
12543
12795
  progress: 0,
12544
12796
  autoScheduling: true,
12545
- constraintType: "asap",
12797
+ constraintType: CONSTRAINT_TYPE.ASAP,
12546
12798
  constraintDate: null,
12547
12799
  hasNewActivities: false,
12548
12800
  ...canonicalEndDateField(
@@ -12694,7 +12946,7 @@ async function dispatchActivityDelete(action, options, deps) {
12694
12946
  },
12695
12947
  {
12696
12948
  action,
12697
- autoscheduleFrom: "roots",
12949
+ autoscheduleFrom: AUTOSCHEDULE_SCOPE.ROOTS,
12698
12950
  recomputeParentsFrom: parentsToCheck,
12699
12951
  now: deps.now,
12700
12952
  options
@@ -12722,7 +12974,7 @@ async function dispatchActivityDelete(action, options, deps) {
12722
12974
  beforeSnap,
12723
12975
  touchedIds,
12724
12976
  scheduledIds,
12725
- sirDetection: "after-diff",
12977
+ sirDetection: SIR_DETECTION_PHASE.AFTER_DIFF,
12726
12978
  links: buildLinkDeletions(beforeLinks),
12727
12979
  trackingEvents: [trackingEvent],
12728
12980
  hoursPerDay: sector.hoursPerDay,
@@ -12761,7 +13013,7 @@ function buildLinkDeletions(beforeLinks) {
12761
13013
  for (const [id, before] of beforeLinks.entries()) {
12762
13014
  out.push({
12763
13015
  id,
12764
- kind: "deleted",
13016
+ kind: ENTITY_CHANGE_KIND.DELETED,
12765
13017
  fields: {
12766
13018
  source: { before: String(before.source), after: void 0 },
12767
13019
  target: { before: String(before.target), after: void 0 },
@@ -12869,7 +13121,7 @@ async function dispatchActivityBatch(action, options, deps) {
12869
13121
  },
12870
13122
  {
12871
13123
  action,
12872
- autoscheduleFrom: action.items.length > 0 || action.links.length > 0 ? "roots" : null,
13124
+ autoscheduleFrom: action.items.length > 0 || action.links.length > 0 ? AUTOSCHEDULE_SCOPE.ROOTS : null,
12873
13125
  recomputeParentsFrom: createdIds,
12874
13126
  now: deps.now,
12875
13127
  options
@@ -12883,7 +13135,7 @@ async function dispatchActivityBatch(action, options, deps) {
12883
13135
  links: buildLinkChangesForBatch(appliedLinks, beforeLinks, deps.adapter),
12884
13136
  hoursPerDay: deps.sector.hoursPerDay,
12885
13137
  correlativeShifts: existingCorrelativeShifts,
12886
- ...action.mode === ACTIVITY_BATCH_MODE.REPLACE ? { sirDetection: "after-diff" } : {}
13138
+ ...action.mode === ACTIVITY_BATCH_MODE.REPLACE ? { sirDetection: SIR_DETECTION_PHASE.AFTER_DIFF } : {}
12887
13139
  });
12888
13140
  return {
12889
13141
  ok: true,
@@ -13242,7 +13494,7 @@ function dispatchSirSync(action, deps) {
13242
13494
  }
13243
13495
  const change = {
13244
13496
  id,
13245
- kind: "updated",
13497
+ kind: ENTITY_CHANGE_KIND.UPDATED,
13246
13498
  fields: { pendingRequestIds: { before, after } },
13247
13499
  after: structuredCloneActivity(updated)
13248
13500
  };
@@ -13418,7 +13670,7 @@ async function dispatchPersistenceAcknowledge(action, deps) {
13418
13670
  );
13419
13671
  activityChanges.push({
13420
13672
  id: assignment.id,
13421
- kind: "updated",
13673
+ kind: ENTITY_CHANGE_KIND.UPDATED,
13422
13674
  fields: {
13423
13675
  proplannerId: {
13424
13676
  before: previousProplannerId,
@@ -13435,7 +13687,7 @@ async function dispatchPersistenceAcknowledge(action, deps) {
13435
13687
  deps.adapter.setLinkProplannerId(assignment.id, assignment.proplannerId);
13436
13688
  linkChanges.push({
13437
13689
  id: assignment.id,
13438
- kind: "updated",
13690
+ kind: ENTITY_CHANGE_KIND.UPDATED,
13439
13691
  fields: {
13440
13692
  proplannerId: {
13441
13693
  before: previousProplannerId,
@@ -13498,7 +13750,7 @@ async function dispatchActivityLookaheadSync(action, options, deps) {
13498
13750
  if (Object.keys(fields).length === 0) continue;
13499
13751
  activities.push({
13500
13752
  id,
13501
- kind: "updated",
13753
+ kind: ENTITY_CHANGE_KIND.UPDATED,
13502
13754
  fields,
13503
13755
  after: {
13504
13756
  ...snapshot,
@@ -13556,6 +13808,285 @@ function hasInvalidPersistedProgress(action) {
13556
13808
  return progress !== void 0 && (action.activityIds.length !== 1 || !Number.isFinite(progress) || progress < 0 || progress > 100);
13557
13809
  }
13558
13810
 
13811
+ // src/dispatch/handlers/activity-lookahead-convert.ts
13812
+ function buildLookaheadConversionPlan(input, deps) {
13813
+ const { adapter } = deps;
13814
+ const requested = new Set(
13815
+ input.conversionRootIds.map((id) => String(id))
13816
+ );
13817
+ if (requested.size === 0) {
13818
+ throw new Error("Conversion requires at least one root");
13819
+ }
13820
+ for (const rootId of requested) validateRequestedRoot(rootId, adapter);
13821
+ const conversionRootIds = adapter.getVisualOrderIds().filter(
13822
+ (activityId) => requested.has(activityId) && !hasAncestorInSet(activityId, requested, adapter)
13823
+ );
13824
+ const branches = conversionRootIds.map(
13825
+ (rootId) => planConversionBranch(rootId, adapter)
13826
+ );
13827
+ const conversionGroups = branches.map(
13828
+ ({ conversionRootId, convertedActivities }) => ({
13829
+ conversionRootId,
13830
+ convertedActivities
13831
+ })
13832
+ );
13833
+ const milestoneMoves = branches.flatMap((branch) => branch.milestoneMoves);
13834
+ const activityIdsToDelete = branches.flatMap(
13835
+ (branch) => branch.activityIdsToDelete
13836
+ );
13837
+ const formerParents = branches.map((branch) => branch.formerParent);
13838
+ const idsToDelete = new Set(activityIdsToDelete);
13839
+ const linkIdsToDelete = collectIncidentLinkIds(idsToDelete, adapter);
13840
+ return {
13841
+ sourceStateRevision: deps.stateRevision,
13842
+ conversionRootIds,
13843
+ conversionGroups,
13844
+ milestoneMoves,
13845
+ activityIdsToDelete,
13846
+ linkIdsToDelete,
13847
+ formerParents
13848
+ };
13849
+ }
13850
+ async function dispatchActivityLookaheadConvert(action, options, deps) {
13851
+ if (action.expectedStateRevision !== deps.stateRevision) {
13852
+ return { ok: false, reason: REJECTION_REASON.STALE_STATE_REVISION };
13853
+ }
13854
+ const plan = buildLookaheadConversionPlan(action, deps);
13855
+ if (!conversionTopologyIsValid(plan, deps.adapter)) {
13856
+ return { ok: false, reason: REJECTION_REASON.HIERARCHY_CYCLE };
13857
+ }
13858
+ const { adapter, scheduler } = deps;
13859
+ scheduler.invalidateAllCaches();
13860
+ const context = await captureConversionMutationContext(plan, adapter);
13861
+ releaseDeletedCustomIds(plan, deps);
13862
+ applyConversionStructure(plan, adapter);
13863
+ applyFormerParentState(plan, context.deletedIds, adapter);
13864
+ const correlativeShifts = recomputeConversionRollups(plan, adapter);
13865
+ foldCorrelativeShifts(
13866
+ adapter,
13867
+ correlativeShifts,
13868
+ context.deletedIds,
13869
+ context.beforeSnap,
13870
+ context.touchedIds
13871
+ );
13872
+ const { scheduledIds } = await runPostMutation(
13873
+ {
13874
+ adapter,
13875
+ scheduler,
13876
+ sector: deps.sector,
13877
+ defaultBaseCalendarId: deps.defaultBaseCalendarId
13878
+ },
13879
+ {
13880
+ action,
13881
+ autoscheduleFrom: "roots",
13882
+ recomputeParentsFrom: context.touchedIds,
13883
+ now: deps.now,
13884
+ options,
13885
+ recomputeParentProgress: true
13886
+ }
13887
+ );
13888
+ const changes = await assembleChangeSet(adapter, {
13889
+ source: action,
13890
+ beforeSnap: context.beforeSnap,
13891
+ touchedIds: context.touchedIds,
13892
+ scheduledIds,
13893
+ sirDetection: "after-diff",
13894
+ links: buildLinkDeletions(context.beforeLinks),
13895
+ hoursPerDay: deps.sector.hoursPerDay,
13896
+ correlativeShifts
13897
+ });
13898
+ return buildConversionResult(plan, context, changes);
13899
+ }
13900
+ function planConversionBranch(rootId, adapter) {
13901
+ const root = requiredActivity(rootId, adapter);
13902
+ const branch = collectDescendantIds([rootId], adapter);
13903
+ branch.delete(rootId);
13904
+ if (branch.size === 0) {
13905
+ throw new Error(`Conversion root ${rootId} has no descendants`);
13906
+ }
13907
+ const descendants = adapter.getVisualOrderIds().filter((activityId) => branch.has(activityId)).map((activityId) => requiredActivity(activityId, adapter));
13908
+ validateFiniteActivity(root);
13909
+ for (const descendant of descendants) validateFiniteActivity(descendant);
13910
+ const convertible = descendants.filter(
13911
+ (activity) => activity.type !== ACTIVITY_TYPE.MILESTONE
13912
+ );
13913
+ const milestones = descendants.filter(
13914
+ (activity) => activity.type === ACTIVITY_TYPE.MILESTONE
13915
+ );
13916
+ const persistedIds = collectPersistedIds(root, convertible);
13917
+ return {
13918
+ conversionRootId: rootId,
13919
+ convertedActivities: convertible.map(
13920
+ (activity) => buildConvertedSnapshot(activity, persistedIds)
13921
+ ),
13922
+ milestoneMoves: buildMilestoneMoves(root, milestones),
13923
+ activityIdsToDelete: convertible.map((activity) => activity.id),
13924
+ formerParent: {
13925
+ activity: structuredCloneActivity(root),
13926
+ hasConvertedActivities: convertible.length > 0
13927
+ }
13928
+ };
13929
+ }
13930
+ function collectPersistedIds(root, converted) {
13931
+ const persistedIds = /* @__PURE__ */ new Map();
13932
+ if (converted.length > 0) persistedIds.set(root.id, persistedIdOf(root));
13933
+ for (const activity of converted) {
13934
+ persistedIds.set(activity.id, persistedIdOf(activity));
13935
+ }
13936
+ return persistedIds;
13937
+ }
13938
+ function buildConvertedSnapshot(activity, persistedIds) {
13939
+ const snapshot = structuredCloneActivity(activity);
13940
+ const parentKey = normalizeParentKey(activity.parentId);
13941
+ const persistedParentId = persistedIds.get(parentKey);
13942
+ snapshot.parentId = persistedParentId === void 0 ? null : String(persistedParentId);
13943
+ return snapshot;
13944
+ }
13945
+ function buildMilestoneMoves(root, milestones) {
13946
+ const moves = [];
13947
+ const parentId = normalizeParentKey(root.parentId);
13948
+ let afterSiblingId = root.id;
13949
+ for (const milestone of milestones) {
13950
+ moves.push({ activityId: milestone.id, parentId, afterSiblingId });
13951
+ afterSiblingId = milestone.id;
13952
+ }
13953
+ return moves;
13954
+ }
13955
+ async function captureConversionMutationContext(plan, adapter) {
13956
+ const deletedIds = new Set(plan.activityIdsToDelete);
13957
+ const touchedIds = /* @__PURE__ */ new Set([
13958
+ ...plan.conversionRootIds,
13959
+ ...plan.activityIdsToDelete,
13960
+ ...plan.milestoneMoves.map(({ activityId }) => activityId),
13961
+ ...plan.milestoneMoves.map(({ parentId }) => parentId).filter((parentId) => parentId !== ROOT_PARENT_ID)
13962
+ ]);
13963
+ return {
13964
+ deletedIds,
13965
+ touchedIds,
13966
+ beforeSnap: await snapshotActivities(adapter, touchedIds),
13967
+ beforeLinks: snapshotLinks(plan.linkIdsToDelete, adapter),
13968
+ viewStateChanges: captureDeletedViewState(adapter, deletedIds)
13969
+ };
13970
+ }
13971
+ function releaseDeletedCustomIds(plan, deps) {
13972
+ for (const activityId of plan.activityIdsToDelete) {
13973
+ const customId = deps.adapter.getActivity(activityId)?.customId;
13974
+ if (customId) deps.customIdTracker.releaseCustomId(customId);
13975
+ }
13976
+ }
13977
+ function applyConversionStructure(plan, adapter) {
13978
+ for (const move of plan.milestoneMoves) {
13979
+ adapter.setActivityFields(move.activityId, {
13980
+ parentId: move.parentId,
13981
+ correlativeId: computeInsertionCorrelativeId(
13982
+ adapter,
13983
+ move.parentId,
13984
+ move.afterSiblingId,
13985
+ void 0
13986
+ )
13987
+ });
13988
+ }
13989
+ for (const linkId of plan.linkIdsToDelete) adapter.removeLink(linkId);
13990
+ for (const activityId of [...plan.activityIdsToDelete].reverse()) {
13991
+ adapter.removeActivity(activityId);
13992
+ }
13993
+ for (const { activity } of plan.formerParents) {
13994
+ adapter.setActivityField(
13995
+ activity.id,
13996
+ ACTIVITY_PROPERTY.TYPE,
13997
+ ACTIVITY_TYPE.TASK
13998
+ );
13999
+ }
14000
+ }
14001
+ function applyFormerParentState(plan, deletedIds, adapter) {
14002
+ for (const { activity, hasConvertedActivities } of plan.formerParents) {
14003
+ const live = requiredActivity(activity.id, adapter);
14004
+ const cleanup = buildParentNewActivitiesCleanup({
14005
+ parent: live,
14006
+ idsRemoved: deletedIds
14007
+ });
14008
+ adapter.setActivityFields(activity.id, {
14009
+ isLookahead: activity.isLookahead || hasConvertedActivities,
14010
+ hasLookaheadTasks: activity.hasLookaheadTasks || hasConvertedActivities,
14011
+ ...cleanup?.fields ?? {}
14012
+ });
14013
+ }
14014
+ }
14015
+ function recomputeConversionRollups(plan, adapter) {
14016
+ for (const { activity } of plan.formerParents) {
14017
+ recomputeRollupCascadesForParent(activity.parentId, adapter);
14018
+ }
14019
+ return recomputeCorrelativeIds(adapter);
14020
+ }
14021
+ function buildConversionResult(plan, context, changes) {
14022
+ const deletedSnapshots = /* @__PURE__ */ new Map();
14023
+ for (const activityId of context.deletedIds) {
14024
+ const snapshot = context.beforeSnap.get(activityId);
14025
+ if (snapshot) deletedSnapshots.set(activityId, snapshot);
14026
+ }
14027
+ return {
14028
+ ok: true,
14029
+ changes: context.viewStateChanges.length === 0 ? changes : { ...changes, viewState: context.viewStateChanges },
14030
+ conversionGroups: plan.conversionGroups.map(
14031
+ ({ conversionRootId, convertedActivities }) => ({
14032
+ conversionRootId,
14033
+ convertedActivities: convertedActivities.map(
14034
+ (activity) => structuredCloneActivity(activity)
14035
+ )
14036
+ })
14037
+ ),
14038
+ __beforeSnap: deletedSnapshots,
14039
+ __beforeLinks: context.beforeLinks
14040
+ };
14041
+ }
14042
+ function validateRequestedRoot(rootId, adapter) {
14043
+ const activity = adapter.getActivity(rootId);
14044
+ if (!activity) throw new Error(`Conversion root ${rootId} was not found`);
14045
+ if (activity.type === ACTIVITY_TYPE.PROJECT && activity.correlativeId === ROOT_PROJECT_CORRELATIVE_ID) {
14046
+ throw new Error(`Conversion root ${rootId} is the visual project root`);
14047
+ }
14048
+ }
14049
+ function requiredActivity(activityId, adapter) {
14050
+ const activity = adapter.getActivity(activityId);
14051
+ if (!activity)
14052
+ throw new Error(`Conversion activity ${activityId} is missing`);
14053
+ return activity;
14054
+ }
14055
+ function persistedIdOf(activity) {
14056
+ if (activity.proplannerId == null) {
14057
+ throw new Error(
14058
+ `Conversion activity ${activity.id} has no persisted identifier`
14059
+ );
14060
+ }
14061
+ return activity.proplannerId;
14062
+ }
14063
+ function validateFiniteActivity(activity) {
14064
+ if (!Number.isFinite(activity.startDate.getTime())) {
14065
+ throw new Error(`Conversion activity ${activity.id} has invalid startDate`);
14066
+ }
14067
+ if (!Number.isFinite(activity.endDate.getTime())) {
14068
+ throw new Error(`Conversion activity ${activity.id} has invalid endDate`);
14069
+ }
14070
+ }
14071
+ function conversionTopologyIsValid(plan, adapter) {
14072
+ const proposedPort = adapter.fork();
14073
+ applyConversionStructure(plan, proposedPort);
14074
+ return validateTopologyCommit({
14075
+ port: adapter,
14076
+ proposedPort,
14077
+ currentLinks: adapter.getAllLinks(),
14078
+ proposedLinks: proposedPort.getAllLinks()
14079
+ }).ok;
14080
+ }
14081
+ function snapshotLinks(linkIds, adapter) {
14082
+ const snapshots = /* @__PURE__ */ new Map();
14083
+ for (const linkId of linkIds) {
14084
+ const link = adapter.getLink(linkId);
14085
+ if (link) snapshots.set(linkId, { ...link });
14086
+ }
14087
+ return snapshots;
14088
+ }
14089
+
13559
14090
  // src/internal/hierarchy/invalid-links.ts
13560
14091
  function collectInvalidLinkIdsForCycle(movedActivityIds, adapter) {
13561
14092
  const moved = /* @__PURE__ */ new Set();
@@ -13708,7 +14239,7 @@ async function dispatchActivityMove(action, options, deps) {
13708
14239
  newChildId: action.activityId,
13709
14240
  getParent: (id) => adapter.getActivity(id) ?? null,
13710
14241
  isCurrentlyLeaf: wasLeaf,
13711
- promotionSource: "reparent"
14242
+ promotionSource: PARENT_MUTATION_SOURCE.REPARENT
13712
14243
  });
13713
14244
  if (promotion) {
13714
14245
  for (const [key, value] of Object.entries(promotion.fields)) {
@@ -13821,7 +14352,7 @@ async function dispatchActivityMove(action, options, deps) {
13821
14352
  beforeSnap,
13822
14353
  touchedIds: touched,
13823
14354
  scheduledIds,
13824
- sirDetection: "before-diff",
14355
+ sirDetection: SIR_DETECTION_PHASE.BEFORE_DIFF,
13825
14356
  trackingEvents: [trackingEvent],
13826
14357
  hoursPerDay: sector.hoursPerDay
13827
14358
  })
@@ -13929,7 +14460,7 @@ async function dispatchActivityIndent(action, options, deps) {
13929
14460
  newChildId: activityId,
13930
14461
  getParent: (id) => adapter.getActivity(id) ?? null,
13931
14462
  isCurrentlyLeaf: wasLeaf,
13932
- promotionSource: "reparent"
14463
+ promotionSource: PARENT_MUTATION_SOURCE.REPARENT
13933
14464
  });
13934
14465
  if (promotion) {
13935
14466
  for (const [key, value] of Object.entries(promotion.fields)) {
@@ -13957,7 +14488,7 @@ async function dispatchActivityIndent(action, options, deps) {
13957
14488
  adapter.setActivityField(
13958
14489
  newParentId,
13959
14490
  ACTIVITY_PROPERTY.CONSTRAINT_TYPE,
13960
- "asap"
14491
+ CONSTRAINT_TYPE.ASAP
13961
14492
  );
13962
14493
  adapter.setActivityField(
13963
14494
  newParentId,
@@ -14233,7 +14764,7 @@ async function dispatchActivityOutdent(action, options, deps) {
14233
14764
  },
14234
14765
  {
14235
14766
  action,
14236
- autoscheduleFrom: succeededIds.length > 0 ? "roots" : null,
14767
+ autoscheduleFrom: succeededIds.length > 0 ? AUTOSCHEDULE_SCOPE.ROOTS : null,
14237
14768
  recomputeParentsFrom: succeededIds,
14238
14769
  now: deps.now,
14239
14770
  options
@@ -14296,7 +14827,7 @@ async function dispatchActivitySetProgress(action, options, deps) {
14296
14827
  }
14297
14828
  const editGate = pipeline.canEdit(activitySnap, ctx.hierarchy);
14298
14829
  if (!editGate.allowed) {
14299
- const declaredButtonOverride = action.origin === "action-button" && (editGate.reason === "has_lookahead_tasks" || editGate.reason === "summary");
14830
+ const declaredButtonOverride = action.origin === ACTIVITY_PROGRESS_ORIGIN.ACTION_BUTTON && (editGate.reason === EDIT_DENIAL_REASON.HAS_LOOKAHEAD_TASKS || editGate.reason === EDIT_DENIAL_REASON.SUMMARY);
14300
14831
  if (!declaredButtonOverride) {
14301
14832
  return {
14302
14833
  ok: false,
@@ -14417,7 +14948,7 @@ async function dispatchDatesBatch(action, options, deps) {
14417
14948
  },
14418
14949
  {
14419
14950
  action,
14420
- autoscheduleFrom: needsAutoSchedule ? "roots" : null,
14951
+ autoscheduleFrom: needsAutoSchedule ? AUTOSCHEDULE_SCOPE.ROOTS : null,
14421
14952
  recomputeParentsFrom: touchedIds,
14422
14953
  now: deps.now,
14423
14954
  options
@@ -14431,7 +14962,7 @@ async function dispatchDatesBatch(action, options, deps) {
14431
14962
  beforeSnap,
14432
14963
  touchedIds,
14433
14964
  scheduledIds,
14434
- sirDetection: "before-diff",
14965
+ sirDetection: SIR_DETECTION_PHASE.BEFORE_DIFF,
14435
14966
  links: linkChanges,
14436
14967
  trackingEvents,
14437
14968
  warnings,
@@ -14578,7 +15109,7 @@ async function dispatchBulkEdit(action, options, deps) {
14578
15109
  }
14579
15110
  const postMutationArgs = {
14580
15111
  action,
14581
- autoscheduleFrom: needsAutoSchedule ? "roots" : null,
15112
+ autoscheduleFrom: needsAutoSchedule ? AUTOSCHEDULE_SCOPE.ROOTS : null,
14582
15113
  recomputeParentsFrom: touchedIds,
14583
15114
  now: deps.now,
14584
15115
  options
@@ -14623,7 +15154,7 @@ async function dispatchBulkEdit(action, options, deps) {
14623
15154
  beforeSnap,
14624
15155
  touchedIds,
14625
15156
  scheduledIds,
14626
- sirDetection: "before-diff",
15157
+ sirDetection: SIR_DETECTION_PHASE.BEFORE_DIFF,
14627
15158
  links: linkChanges,
14628
15159
  trackingEvents,
14629
15160
  warnings,
@@ -14760,6 +15291,51 @@ function mergeBeforeSnapshots2(beforeSnap, ids, deps) {
14760
15291
  }
14761
15292
  }
14762
15293
 
15294
+ // src/shared/load-diagnostics.ts
15295
+ var LOAD_DIAGNOSTIC_SAMPLE_LIMIT = 10;
15296
+ var LOAD_DIAGNOSTIC_CODE = {
15297
+ INVALID_BASELINE_POINT: "invalid_baseline_point",
15298
+ UNKNOWN_CONSTRAINT: "unknown_constraint",
15299
+ ORPHAN_ACTIVITY: "orphan_activity",
15300
+ INVALID_LINK: "invalid_link",
15301
+ DUPLICATE_LINK: "duplicate_link"
15302
+ };
15303
+ var LOAD_DIAGNOSTIC_CODE_ORDER = [
15304
+ LOAD_DIAGNOSTIC_CODE.INVALID_BASELINE_POINT,
15305
+ LOAD_DIAGNOSTIC_CODE.UNKNOWN_CONSTRAINT,
15306
+ LOAD_DIAGNOSTIC_CODE.ORPHAN_ACTIVITY,
15307
+ LOAD_DIAGNOSTIC_CODE.INVALID_LINK,
15308
+ LOAD_DIAGNOSTIC_CODE.DUPLICATE_LINK
15309
+ ];
15310
+ var noopLoadDiagnosticRecorder = () => {
15311
+ };
15312
+ function createLoadDiagnosticsCollector() {
15313
+ const counts = /* @__PURE__ */ new Map();
15314
+ const samples = /* @__PURE__ */ new Map();
15315
+ const record = (code, sampleId) => {
15316
+ counts.set(code, (counts.get(code) ?? 0) + 1);
15317
+ const codeSamples = samples.get(code) ?? [];
15318
+ if (codeSamples.length < LOAD_DIAGNOSTIC_SAMPLE_LIMIT && !codeSamples.includes(sampleId)) {
15319
+ codeSamples.push(sampleId);
15320
+ samples.set(code, codeSamples);
15321
+ }
15322
+ };
15323
+ const snapshot = () => Object.freeze(
15324
+ LOAD_DIAGNOSTIC_CODE_ORDER.flatMap((code) => {
15325
+ const count = counts.get(code);
15326
+ if (count === void 0) return [];
15327
+ return [
15328
+ Object.freeze({
15329
+ code,
15330
+ count,
15331
+ sampleIds: Object.freeze([...samples.get(code) ?? []])
15332
+ })
15333
+ ];
15334
+ })
15335
+ );
15336
+ return { record, snapshot };
15337
+ }
15338
+
14763
15339
  // src/baselines/normalize-baseline-point.ts
14764
15340
  function parseBaselineDate(value) {
14765
15341
  return typeof value === "string" && value.length > 0 ? parseBackendDate(value) : value instanceof Date ? value : null;
@@ -14769,11 +15345,17 @@ function parseFiniteNonNegative(value) {
14769
15345
  if (!Number.isFinite(numeric) || numeric < 0) return null;
14770
15346
  return numeric;
14771
15347
  }
14772
- function normalizeBaselinePoint(point, reporter) {
15348
+ function normalizeBaselinePoint(point, reporter, diagnostic) {
14773
15349
  const durationDays = parseFiniteNonNegative(point.duration);
14774
15350
  const cost = parseFiniteNonNegative(point.cost);
14775
15351
  const workHours = parseFiniteNonNegative(point.hh_work);
14776
15352
  if (durationDays === null || cost === null || workHours === null) {
15353
+ if (diagnostic) {
15354
+ diagnostic.record(
15355
+ LOAD_DIAGNOSTIC_CODE.INVALID_BASELINE_POINT,
15356
+ diagnostic.sampleId
15357
+ );
15358
+ }
14777
15359
  reporter.warn(
14778
15360
  `[baseline] dropping point with non-finite/negative magnitude \u2014 duration=${JSON.stringify(point.duration)}, cost=${JSON.stringify(point.cost)}, hh_work=${JSON.stringify(point.hh_work)}`
14779
15361
  );
@@ -14795,7 +15377,7 @@ function normalizeBaselinePoint(point, reporter) {
14795
15377
  }
14796
15378
 
14797
15379
  // src/baselines/apply-baseline-points.ts
14798
- function applyBaselinePoints(adapter, points, reporter) {
15380
+ function applyBaselinePoints(adapter, points, reporter, recordDiagnostic = noopLoadDiagnosticRecorder) {
14799
15381
  const idByProplanner = /* @__PURE__ */ new Map();
14800
15382
  adapter.forEachActivity((a, id) => {
14801
15383
  const pid = a.proplannerId;
@@ -14804,9 +15386,21 @@ function applyBaselinePoints(adapter, points, reporter) {
14804
15386
  const grouped = /* @__PURE__ */ new Map();
14805
15387
  for (const p of points) {
14806
15388
  const activityId = p.activityId;
14807
- if (typeof activityId !== "number") continue;
15389
+ if (typeof activityId !== "number") {
15390
+ recordDiagnostic(
15391
+ LOAD_DIAGNOSTIC_CODE.INVALID_BASELINE_POINT,
15392
+ String(activityId ?? "unknown")
15393
+ );
15394
+ continue;
15395
+ }
14808
15396
  const coreId = idByProplanner.get(activityId);
14809
- if (coreId === void 0) continue;
15397
+ if (coreId === void 0) {
15398
+ recordDiagnostic(
15399
+ LOAD_DIAGNOSTIC_CODE.INVALID_BASELINE_POINT,
15400
+ String(activityId)
15401
+ );
15402
+ continue;
15403
+ }
14810
15404
  const arr = grouped.get(coreId);
14811
15405
  if (arr) arr.push(p);
14812
15406
  else grouped.set(coreId, [p]);
@@ -14816,7 +15410,12 @@ function applyBaselinePoints(adapter, points, reporter) {
14816
15410
  adapter.setActivityField(
14817
15411
  coreId,
14818
15412
  "baselinePoints",
14819
- group.map((point) => normalizeBaselinePoint(point, reporter)).filter((point) => point !== null)
15413
+ group.map(
15414
+ (point) => normalizeBaselinePoint(point, reporter, {
15415
+ record: recordDiagnostic,
15416
+ sampleId: coreId
15417
+ })
15418
+ ).filter((point) => point !== null)
14820
15419
  );
14821
15420
  changed.push(coreId);
14822
15421
  }
@@ -14861,12 +15460,13 @@ function emitBaselineSnapshotColumns(state) {
14861
15460
  }
14862
15461
 
14863
15462
  // src/baselines/apply-baseline-overlay.ts
14864
- function applyBaselineOverlay(state, points, now, reporter, defaultBaseCalendarId = null) {
15463
+ function applyBaselineOverlay(state, points, now, reporter, defaultBaseCalendarId = null, recordDiagnostic = noopLoadDiagnosticRecorder) {
14865
15464
  const changed = /* @__PURE__ */ new Set();
14866
15465
  for (const id of applyBaselinePoints(
14867
15466
  state,
14868
15467
  points,
14869
- reporter
15468
+ reporter,
15469
+ recordDiagnostic
14870
15470
  )) {
14871
15471
  changed.add(id);
14872
15472
  }
@@ -15105,7 +15705,7 @@ async function dispatchCalendarReconcile(action, options, deps) {
15105
15705
  },
15106
15706
  {
15107
15707
  action,
15108
- autoscheduleFrom: "roots",
15708
+ autoscheduleFrom: AUTOSCHEDULE_SCOPE.ROOTS,
15109
15709
  recomputeParentsFrom: touchedIds,
15110
15710
  now: deps.now,
15111
15711
  options
@@ -15176,7 +15776,7 @@ function dispatchActivityCopy(action, deps) {
15176
15776
  throw new Error(`Selected activity ${id} is missing`);
15177
15777
  return {
15178
15778
  originalId: id,
15179
- originalParentId: activity.parentId ?? "0",
15779
+ originalParentId: activity.parentId ?? ROOT_PARENT_ID,
15180
15780
  overrides: copyOverrides(activity)
15181
15781
  };
15182
15782
  }),
@@ -15185,7 +15785,7 @@ function dispatchActivityCopy(action, deps) {
15185
15785
  ).map((link) => cloneDomainValue(link))
15186
15786
  };
15187
15787
  const selection = dispatchSelectionReplace(
15188
- { kind: "selection-replace", activityIds: [] },
15788
+ { kind: DISPATCH_ACTION_KIND.SELECTION_REPLACE, activityIds: [] },
15189
15789
  { adapter: deps.adapter }
15190
15790
  );
15191
15791
  if (!selection.ok) return selection;
@@ -15247,6 +15847,7 @@ async function dispatchActivityPasteCopied(action, options, deps) {
15247
15847
  const afterSiblingId = mappedParent === void 0 ? previousRootId ?? destination.afterSiblingId : void 0;
15248
15848
  const created = await createActivityCore(
15249
15849
  {
15850
+ kind: DISPATCH_ACTION_KIND.ACTIVITY_CREATE,
15250
15851
  parentId: mappedParent ?? destination.parentId,
15251
15852
  ...afterSiblingId === void 0 ? {} : { afterSiblingId },
15252
15853
  overrides: cloneDomainValue(copied.overrides),
@@ -15280,7 +15881,7 @@ async function dispatchActivityPasteCopied(action, options, deps) {
15280
15881
  const target = originalToNew.get(copiedLink.target);
15281
15882
  if (source === void 0 || target === void 0) return invariantFailure();
15282
15883
  const operation = {
15283
- kind: "create",
15884
+ kind: LINK_OPERATION_KIND.CREATE,
15284
15885
  source,
15285
15886
  target,
15286
15887
  type: copiedLink.type,
@@ -15332,94 +15933,97 @@ async function dispatchActivityPasteCopied(action, options, deps) {
15332
15933
 
15333
15934
  // src/dispatch/dispatch.ts
15334
15935
  async function performDispatch(action, options, deps) {
15335
- if (action.kind === "activity-copy") {
15936
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_COPY) {
15336
15937
  return dispatchActivityCopy(action, {
15337
15938
  adapter: deps.adapter,
15338
15939
  clipboard: deps.activityClipboard
15339
15940
  });
15340
15941
  }
15341
- if (action.kind === "calendar-reconcile") {
15942
+ if (action.kind === DISPATCH_ACTION_KIND.CALENDAR_RECONCILE) {
15342
15943
  return dispatchCalendarReconcile(action, options, deps);
15343
15944
  }
15344
- if (action.kind === "activity-clipboard-clear") {
15945
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_CLIPBOARD_CLEAR) {
15345
15946
  return dispatchActivityClipboardClear(action, deps.activityClipboard);
15346
15947
  }
15347
- if (action.kind === "activity-paste-copied") {
15948
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_PASTE_COPIED) {
15348
15949
  return dispatchActivityPasteCopied(action, options, deps);
15349
15950
  }
15350
- if (action.kind === "activity-batch") {
15951
+ if (action.kind === ACTIVITY_BATCH_ACTION_KIND) {
15351
15952
  return dispatchActivityBatch(action, options, deps);
15352
15953
  }
15353
- if (action.kind === "persistence-acknowledge") {
15954
+ if (action.kind === DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE) {
15354
15955
  return dispatchPersistenceAcknowledge(action, deps);
15355
15956
  }
15356
- if (action.kind === "baseline-apply") {
15957
+ if (action.kind === DISPATCH_ACTION_KIND.BASELINE_APPLY) {
15357
15958
  return dispatchBaselineApply(action, deps);
15358
15959
  }
15359
- if (action.kind === "ponderator-criterion-set") {
15960
+ if (action.kind === DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET) {
15360
15961
  return dispatchPonderatorCriterionSet(action, deps);
15361
15962
  }
15362
- if (action.kind === "status-criteria-set") {
15963
+ if (action.kind === DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET) {
15363
15964
  return dispatchStatusCriteriaSet(action, deps);
15364
15965
  }
15365
- if (action.kind === "link-create" || action.kind === "link-update" || action.kind === "link-delete") {
15966
+ if (action.kind === DISPATCH_ACTION_KIND.LINK_CREATE || action.kind === DISPATCH_ACTION_KIND.LINK_UPDATE || action.kind === DISPATCH_ACTION_KIND.LINK_DELETE) {
15366
15967
  return dispatchLink(action, options, deps);
15367
15968
  }
15368
- if (action.kind === "links-batch") {
15969
+ if (action.kind === DISPATCH_ACTION_KIND.LINKS_BATCH) {
15369
15970
  return dispatchLinksBatch(action, options, deps);
15370
15971
  }
15371
- if (action.kind === "activity-create") {
15972
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_CREATE) {
15372
15973
  return dispatchActivityCreate(action, options, deps);
15373
15974
  }
15374
- if (action.kind === "activity-delete") {
15975
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_DELETE) {
15375
15976
  return dispatchActivityDelete(action, options, deps);
15376
15977
  }
15377
- if (action.kind === "activity-move") {
15978
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_MOVE) {
15378
15979
  return dispatchActivityMove(action, options, deps);
15379
15980
  }
15380
- if (action.kind === "activity-indent") {
15981
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_INDENT) {
15381
15982
  return dispatchActivityIndent(action, options, deps);
15382
15983
  }
15383
- if (action.kind === "activity-outdent") {
15984
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_OUTDENT) {
15384
15985
  return dispatchActivityOutdent(action, options, deps);
15385
15986
  }
15386
- if (action.kind === "activity-set-progress") {
15987
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_SET_PROGRESS) {
15387
15988
  return dispatchActivitySetProgress(action, options, deps);
15388
15989
  }
15389
- if (action.kind === "dates-batch") {
15990
+ if (action.kind === DISPATCH_ACTION_KIND.DATES_BATCH) {
15390
15991
  return dispatchDatesBatch(action, options, deps);
15391
15992
  }
15392
- if (action.kind === "bulk-edit") {
15993
+ if (action.kind === DISPATCH_ACTION_KIND.BULK_EDIT) {
15393
15994
  return dispatchBulkEdit(action, options, deps);
15394
15995
  }
15395
- if (action.kind === "selection-toggle") {
15996
+ if (action.kind === DISPATCH_ACTION_KIND.SELECTION_TOGGLE) {
15396
15997
  return dispatchSelectionToggle(action, selectionDeps(deps));
15397
15998
  }
15398
- if (action.kind === "selection-replace") {
15999
+ if (action.kind === DISPATCH_ACTION_KIND.SELECTION_REPLACE) {
15399
16000
  return dispatchSelectionReplace(action, selectionDeps(deps));
15400
16001
  }
15401
- if (action.kind === "visibility-set") {
16002
+ if (action.kind === DISPATCH_ACTION_KIND.VISIBILITY_SET) {
15402
16003
  return dispatchVisibilitySet(action, selectionDeps(deps));
15403
16004
  }
15404
- if (action.kind === "filter-set") {
16005
+ if (action.kind === DISPATCH_ACTION_KIND.FILTER_SET) {
15405
16006
  return dispatchFilterSet(action, {
15406
16007
  adapter: deps.adapter,
15407
16008
  hoursPerDay: deps.sector.hoursPerDay
15408
16009
  });
15409
16010
  }
15410
- if (action.kind === "sort-set") {
16011
+ if (action.kind === DISPATCH_ACTION_KIND.SORT_SET) {
15411
16012
  return dispatchSortSet(action, { adapter: deps.adapter });
15412
16013
  }
15413
- if (action.kind === "sir-sync") {
16014
+ if (action.kind === DISPATCH_ACTION_KIND.SIR_SYNC) {
15414
16015
  return dispatchSirSync(action, deps);
15415
16016
  }
15416
- if (action.kind === "activity-lookahead-sync") {
16017
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC) {
15417
16018
  return dispatchActivityLookaheadSync(action, options, deps);
15418
16019
  }
15419
- if (action.kind === "inline-edit" && (action.column === COLUMN.CUSTOM_PREDECESSORS || action.column === COLUMN.CUSTOM_SUCESSORS)) {
16020
+ if (action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_CONVERT) {
16021
+ return dispatchActivityLookaheadConvert(action, options, deps);
16022
+ }
16023
+ if (action.kind === DISPATCH_ACTION_KIND.INLINE_EDIT && (action.column === COLUMN.CUSTOM_PREDECESSORS || action.column === COLUMN.CUSTOM_SUCESSORS)) {
15420
16024
  return dispatchInlineEditLinks(action, options, deps);
15421
16025
  }
15422
- if (action.kind !== "inline-edit") {
16026
+ if (action.kind !== DISPATCH_ACTION_KIND.INLINE_EDIT) {
15423
16027
  return assertNever(
15424
16028
  action,
15425
16029
  `[ScheduleCore] dispatch kind "${action.kind}" not supported yet`
@@ -15446,7 +16050,7 @@ function coerceActivityFieldValue(field, value) {
15446
16050
 
15447
16051
  // src/calendar/adapter.ts
15448
16052
  function createWorkCalendarAdapter(instance, options = {}) {
15449
- const defaultUnit = options.defaultUnit ?? "hour";
16053
+ const defaultUnit = options.defaultUnit ?? CALENDAR_UNIT.HOUR;
15450
16054
  return {
15451
16055
  getCalendar(calendarId) {
15452
16056
  const calendar = instance.getCalendar(String(calendarId));
@@ -18250,90 +18854,6 @@ function collectDescendantIdsBFS(adapter, rootId) {
18250
18854
  return result;
18251
18855
  }
18252
18856
 
18253
- // src/internal/state/write-capture.ts
18254
- var WriteCapture = class {
18255
- _journal = null;
18256
- begin() {
18257
- this._journal = {
18258
- dirty: /* @__PURE__ */ new Set(),
18259
- before: /* @__PURE__ */ new Map(),
18260
- ops: [],
18261
- linkFieldCaptured: /* @__PURE__ */ new Set(),
18262
- correlativeBefore: /* @__PURE__ */ new Map(),
18263
- scheduledBefore: /* @__PURE__ */ new Map(),
18264
- progressFallbackBefore: /* @__PURE__ */ new Map()
18265
- };
18266
- }
18267
- peek() {
18268
- return this._journal;
18269
- }
18270
- end() {
18271
- this._journal = null;
18272
- }
18273
- note(key, current) {
18274
- const journal = this._journal;
18275
- if (!journal) return;
18276
- if (!journal.before.has(key))
18277
- journal.before.set(key, cloneCoreActivity(current));
18278
- journal.dirty.add(key);
18279
- }
18280
- noteInsert(activityId) {
18281
- this._journal?.ops.push({ kind: "insert", activityId });
18282
- }
18283
- noteRemove(activityId, current) {
18284
- this._journal?.ops.push({
18285
- kind: "remove",
18286
- activityId,
18287
- before: cloneCoreActivity(current)
18288
- });
18289
- }
18290
- noteLinkAdd(linkId) {
18291
- this._journal?.ops.push({ kind: "link-add", linkId });
18292
- }
18293
- noteLinkRemove(linkId, current) {
18294
- this._journal?.ops.push({
18295
- kind: "link-remove",
18296
- linkId,
18297
- before: cloneLink(current)
18298
- });
18299
- }
18300
- noteCorrelativeBefore(activityId, before) {
18301
- const journal = this._journal;
18302
- if (!journal || journal.correlativeBefore.has(activityId)) return;
18303
- journal.correlativeBefore.set(activityId, before);
18304
- }
18305
- noteScheduledBefore(activityId, current) {
18306
- const journal = this._journal;
18307
- if (!journal) return;
18308
- const beforeImage = cloneCoreActivity(current);
18309
- if (!journal.scheduledBefore.has(activityId)) {
18310
- journal.scheduledBefore.set(activityId, beforeImage);
18311
- }
18312
- if (!journal.before.has(activityId)) {
18313
- journal.before.set(activityId, beforeImage);
18314
- }
18315
- journal.dirty.add(activityId);
18316
- }
18317
- noteLinkField(linkId, current) {
18318
- const journal = this._journal;
18319
- if (!journal || journal.linkFieldCaptured.has(linkId)) return;
18320
- journal.linkFieldCaptured.add(linkId);
18321
- journal.ops.push({
18322
- kind: "link-field",
18323
- linkId,
18324
- before: cloneLink(current)
18325
- });
18326
- }
18327
- noteProgressFallback(activityId, current) {
18328
- const journal = this._journal;
18329
- if (!journal || journal.progressFallbackBefore.has(activityId)) return;
18330
- journal.progressFallbackBefore.set(activityId, current);
18331
- }
18332
- };
18333
- function cloneLink(link) {
18334
- return { ...link };
18335
- }
18336
-
18337
18857
  // src/internal/state/calendar-calculator.ts
18338
18858
  var CalendarCalculator = class {
18339
18859
  _cache = {
@@ -18987,9 +19507,9 @@ var ScheduleState = class _ScheduleState {
18987
19507
  this._reInsertRemovedActivities(ops);
18988
19508
  this._reAddRemovedLinks(ops);
18989
19509
  this._restoreLinkFields(ops);
18990
- this._restoreCorrelatives(correlativeBefore);
18991
19510
  this._restoreActivityFields(scheduledBefore);
18992
19511
  this._restoreActivityFields(before);
19512
+ this._restoreCorrelatives(correlativeBefore);
18993
19513
  this._restoreProgressFallbacks(progressFallbackBefore);
18994
19514
  if (this._viewStateBefore !== null) {
18995
19515
  this._viewState.restore(this._viewStateBefore);
@@ -19020,24 +19540,33 @@ var ScheduleState = class _ScheduleState {
19020
19540
  }
19021
19541
  _undoLinkAdds(ops) {
19022
19542
  for (const op of ops)
19023
- if (op.kind === "link-add") this._detachLink(op.linkId);
19543
+ if (op.kind === WRITE_OPERATION_KIND.LINK_ADD) {
19544
+ this._detachLink(op.linkId);
19545
+ }
19024
19546
  }
19025
19547
  _undoInserts(ops) {
19026
19548
  for (const op of ops)
19027
- if (op.kind === "insert") this._activities.delete(op.activityId);
19549
+ if (op.kind === WRITE_OPERATION_KIND.INSERT) {
19550
+ this._activities.delete(op.activityId);
19551
+ }
19028
19552
  }
19029
19553
  _reInsertRemovedActivities(ops) {
19030
19554
  for (const op of ops)
19031
- if (op.kind === "remove") this._activities.set(op.activityId, op.before);
19555
+ if (op.kind === WRITE_OPERATION_KIND.REMOVE) {
19556
+ this._activities.set(op.activityId, op.before);
19557
+ }
19032
19558
  }
19033
19559
  _reAddRemovedLinks(ops) {
19034
19560
  for (const op of ops)
19035
- if (op.kind === "link-remove") this._attachLink(op.before);
19561
+ if (op.kind === WRITE_OPERATION_KIND.LINK_REMOVE) {
19562
+ this._attachLink(op.before);
19563
+ }
19036
19564
  }
19037
19565
  _restoreLinkFields(ops) {
19038
19566
  for (const op of ops)
19039
- if (op.kind === "link-field" && this._links.has(op.linkId))
19567
+ if (op.kind === WRITE_OPERATION_KIND.LINK_FIELD && this._links.has(op.linkId)) {
19040
19568
  this._links.set(op.linkId, op.before);
19569
+ }
19041
19570
  }
19042
19571
  _restoreActivityFields(before) {
19043
19572
  for (const [id, snapshot] of before) {
@@ -19204,7 +19733,8 @@ function withoutDerivedFields(entry, derivedFields) {
19204
19733
  ([field]) => !derivedFields.has(field)
19205
19734
  )
19206
19735
  );
19207
- if (entry.kind === "updated" && Object.keys(fields).length === 0) return null;
19736
+ if (entry.kind === ENTITY_CHANGE_KIND.UPDATED && Object.keys(fields).length === 0)
19737
+ return null;
19208
19738
  return {
19209
19739
  ...entry,
19210
19740
  ...entry.fields === void 0 ? {} : { fields },
@@ -19217,7 +19747,7 @@ function buildHistoryChangeSet(changes) {
19217
19747
  after: null
19218
19748
  }));
19219
19749
  const linksWithoutAfter = changes.links.map((entry) => withoutDerivedFields(entry, DERIVED_LINK_FIELDS)).filter((entry) => entry !== null);
19220
- const source = changes.source.kind === "activity-batch" ? { ...changes.source, items: [], links: [] } : changes.source;
19750
+ const source = changes.source.kind === ACTIVITY_BATCH_ACTION_KIND ? { ...changes.source, items: [], links: [] } : changes.source;
19221
19751
  return cloneDomainValue({
19222
19752
  ...changes,
19223
19753
  source,
@@ -19249,12 +19779,12 @@ function captureCreatedSnapshots(state, changeSet) {
19249
19779
  const afterSnap = /* @__PURE__ */ new Map();
19250
19780
  const afterLinks = /* @__PURE__ */ new Map();
19251
19781
  for (const ch of changeSet.activities) {
19252
- if (ch.kind !== "created") continue;
19782
+ if (ch.kind !== ENTITY_CHANGE_KIND.CREATED) continue;
19253
19783
  const live = state.getActivity(String(ch.id));
19254
19784
  if (live) afterSnap.set(String(ch.id), structuredCloneActivity(live));
19255
19785
  }
19256
19786
  for (const ch of changeSet.links) {
19257
- if (ch.kind === "deleted") continue;
19787
+ if (ch.kind === ENTITY_CHANGE_KIND.DELETED) continue;
19258
19788
  const live = state.getLink(String(ch.id));
19259
19789
  if (live) afterLinks.set(String(ch.id), { ...live });
19260
19790
  }
@@ -19266,7 +19796,7 @@ function computeCoalesceKey(action) {
19266
19796
  return `inline-edit:${String(action.activityId)}:${action.column}`;
19267
19797
  }
19268
19798
  function isSimpleInlineEntry(e) {
19269
- return e.changeSet.activities.length === 1 && e.changeSet.activities[0]?.kind === "updated" && e.changeSet.links.length === 0 && !e.beforeSnap?.size && !e.afterSnap?.size;
19799
+ return e.changeSet.activities.length === 1 && e.changeSet.activities[0]?.kind === ENTITY_CHANGE_KIND.UPDATED && e.changeSet.links.length === 0 && !e.beforeSnap?.size && !e.afterSnap?.size;
19270
19800
  }
19271
19801
  function canCoalesce(top, next) {
19272
19802
  if (!isSimpleInlineEntry(top) || !isSimpleInlineEntry(next)) return false;
@@ -19295,19 +19825,29 @@ function mergeCoalesced(top, next) {
19295
19825
  };
19296
19826
  return buildUndoEntry(changeSet);
19297
19827
  }
19828
+ var DISPATCH_HISTORY_POLICY = {
19829
+ RECORD: "record",
19830
+ SKIP: "skip",
19831
+ CHECKPOINT_ON_SUCCESS: "checkpoint-on-success"
19832
+ };
19833
+ var CHANGE_SET_SIDE = {
19834
+ BEFORE: "before",
19835
+ AFTER: "after"
19836
+ };
19298
19837
  function getDispatchHistoryPolicy(action) {
19299
19838
  if (action.kind === DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE) {
19300
- return "checkpoint-on-success";
19839
+ return DISPATCH_HISTORY_POLICY.CHECKPOINT_ON_SUCCESS;
19301
19840
  }
19302
19841
  if (action.kind === DISPATCH_ACTION_KIND.SIR_SYNC || action.kind === DISPATCH_ACTION_KIND.CALENDAR_RECONCILE || action.kind === DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_SYNC || action.kind === DISPATCH_ACTION_KIND.BASELINE_APPLY || action.kind === DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET || action.kind === DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET || action.kind === DISPATCH_ACTION_KIND.ACTIVITY_CLIPBOARD_CLEAR || action.kind === DISPATCH_ACTION_KIND.ACTIVITY_COPY || action.kind === DISPATCH_ACTION_KIND.SELECTION_TOGGLE || action.kind === DISPATCH_ACTION_KIND.SELECTION_REPLACE || action.kind === DISPATCH_ACTION_KIND.VISIBILITY_SET || action.kind === DISPATCH_ACTION_KIND.FILTER_SET || action.kind === DISPATCH_ACTION_KIND.SORT_SET) {
19303
- return "skip";
19842
+ return DISPATCH_HISTORY_POLICY.SKIP;
19304
19843
  }
19305
- return "record";
19844
+ return DISPATCH_HISTORY_POLICY.RECORD;
19306
19845
  }
19307
19846
  function needsResync(entry) {
19308
19847
  for (const change of entry.changeSet.activities) {
19309
- if (change.kind === "created" || change.kind === "deleted") return true;
19310
- if (change.kind === "updated" && change.fields && COLUMN.CUSTOM_ID in change.fields)
19848
+ if (change.kind === ENTITY_CHANGE_KIND.CREATED || change.kind === ENTITY_CHANGE_KIND.DELETED)
19849
+ return true;
19850
+ if (change.kind === ENTITY_CHANGE_KIND.UPDATED && change.fields && COLUMN.CUSTOM_ID in change.fields)
19311
19851
  return true;
19312
19852
  }
19313
19853
  return false;
@@ -19317,33 +19857,41 @@ function buildInverseChangeSet(state, entry, side) {
19317
19857
  const links = [];
19318
19858
  for (const change of entry.changeSet.activities) {
19319
19859
  const activityId = String(change.id);
19320
- if (change.kind === "updated") {
19860
+ if (change.kind === ENTITY_CHANGE_KIND.UPDATED) {
19321
19861
  const snapshot = state.getActivity(activityId);
19322
19862
  activities.push({
19323
19863
  id: activityId,
19324
- kind: "updated",
19864
+ kind: ENTITY_CHANGE_KIND.UPDATED,
19325
19865
  fields: historyFields(change.fields, side),
19326
19866
  after: snapshot ? structuredCloneActivity(snapshot) : null
19327
19867
  });
19328
- } else if (change.kind === "deleted") {
19329
- if (side === "before") {
19868
+ } else if (change.kind === ENTITY_CHANGE_KIND.DELETED) {
19869
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19330
19870
  const snapshot = state.getActivity(activityId);
19331
19871
  activities.push({
19332
19872
  id: activityId,
19333
- kind: "created",
19873
+ kind: ENTITY_CHANGE_KIND.CREATED,
19334
19874
  after: snapshot ? structuredCloneActivity(snapshot) : null
19335
19875
  });
19336
19876
  } else {
19337
- activities.push({ id: activityId, kind: "deleted", after: null });
19877
+ activities.push({
19878
+ id: activityId,
19879
+ kind: ENTITY_CHANGE_KIND.DELETED,
19880
+ after: null
19881
+ });
19338
19882
  }
19339
19883
  } else {
19340
- if (side === "before") {
19341
- activities.push({ id: activityId, kind: "deleted", after: null });
19884
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19885
+ activities.push({
19886
+ id: activityId,
19887
+ kind: ENTITY_CHANGE_KIND.DELETED,
19888
+ after: null
19889
+ });
19342
19890
  } else {
19343
19891
  const snapshot = state.getActivity(activityId);
19344
19892
  activities.push({
19345
19893
  id: activityId,
19346
- kind: "created",
19894
+ kind: ENTITY_CHANGE_KIND.CREATED,
19347
19895
  after: snapshot ? structuredCloneActivity(snapshot) : null
19348
19896
  });
19349
19897
  }
@@ -19351,44 +19899,52 @@ function buildInverseChangeSet(state, entry, side) {
19351
19899
  }
19352
19900
  for (const change of entry.changeSet.links) {
19353
19901
  const linkId = String(change.id);
19354
- if (change.kind === "updated") {
19902
+ if (change.kind === ENTITY_CHANGE_KIND.UPDATED) {
19355
19903
  const lk = state.getLink(linkId);
19356
19904
  links.push({
19357
19905
  id: linkId,
19358
- kind: "updated",
19906
+ kind: ENTITY_CHANGE_KIND.UPDATED,
19359
19907
  fields: historyFields(change.fields, side),
19360
19908
  after: lk ? snapshotToLink(lk) : null
19361
19909
  });
19362
- } else if (change.kind === "deleted") {
19363
- if (side === "before") {
19910
+ } else if (change.kind === ENTITY_CHANGE_KIND.DELETED) {
19911
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19364
19912
  const lk = state.getLink(linkId);
19365
19913
  links.push({
19366
19914
  id: linkId,
19367
- kind: "created",
19915
+ kind: ENTITY_CHANGE_KIND.CREATED,
19368
19916
  after: lk ? snapshotToLink(lk) : null
19369
19917
  });
19370
19918
  } else {
19371
- links.push({ id: linkId, kind: "deleted", after: null });
19919
+ links.push({
19920
+ id: linkId,
19921
+ kind: ENTITY_CHANGE_KIND.DELETED,
19922
+ after: null
19923
+ });
19372
19924
  }
19373
19925
  } else {
19374
- if (side === "before") {
19375
- links.push({ id: linkId, kind: "deleted", after: null });
19926
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19927
+ links.push({
19928
+ id: linkId,
19929
+ kind: ENTITY_CHANGE_KIND.DELETED,
19930
+ after: null
19931
+ });
19376
19932
  } else {
19377
19933
  const lk = state.getLink(linkId);
19378
19934
  links.push({
19379
19935
  id: linkId,
19380
- kind: "created",
19936
+ kind: ENTITY_CHANGE_KIND.CREATED,
19381
19937
  after: lk ? snapshotToLink(lk) : null
19382
19938
  });
19383
19939
  }
19384
19940
  }
19385
19941
  }
19386
19942
  const viewState = (entry.changeSet.viewState ?? []).map(
19387
- (change) => side === "before" ? invertViewStateChange(change) : change
19943
+ (change) => side === CHANGE_SET_SIDE.BEFORE ? invertViewStateChange(change) : change
19388
19944
  );
19389
19945
  return {
19390
19946
  source: {
19391
- kind: side === "before" ? CHANGE_SET_SOURCE_KIND.UNDO : CHANGE_SET_SOURCE_KIND.REDO
19947
+ kind: side === CHANGE_SET_SIDE.BEFORE ? CHANGE_SET_SOURCE_KIND.UNDO : CHANGE_SET_SOURCE_KIND.REDO
19392
19948
  },
19393
19949
  activities,
19394
19950
  links,
@@ -19403,7 +19959,7 @@ function historyFields(fields, side) {
19403
19959
  return Object.fromEntries(
19404
19960
  Object.entries(fields).map(([field, values]) => [
19405
19961
  field,
19406
- side === "before" ? {
19962
+ side === CHANGE_SET_SIDE.BEFORE ? {
19407
19963
  before: cloneDomainValue(values.after),
19408
19964
  after: cloneDomainValue(values.before)
19409
19965
  } : {
@@ -19434,26 +19990,26 @@ function changeSetIsSubstantive(cs) {
19434
19990
  return cs.activities.length > 0 || cs.links.length > 0 || (cs.viewState?.length ?? 0) > 0 || (cs.effects?.length ?? 0) > 0;
19435
19991
  }
19436
19992
  function applyUndo(state, entry) {
19437
- applyChangeSetSide(state, entry, "before");
19993
+ applyChangeSetSide(state, entry, CHANGE_SET_SIDE.BEFORE);
19438
19994
  }
19439
19995
  function applyRedo(state, entry) {
19440
- applyChangeSetSide(state, entry, "after");
19996
+ applyChangeSetSide(state, entry, CHANGE_SET_SIDE.AFTER);
19441
19997
  }
19442
19998
  function applyChangeSetSide(state, entry, side) {
19443
19999
  const cs = entry.changeSet;
19444
20000
  for (const ch of cs.activities) {
19445
- if (ch.kind === "updated") {
20001
+ if (ch.kind === ENTITY_CHANGE_KIND.UPDATED) {
19446
20002
  if (!ch.fields) continue;
19447
20003
  for (const [field, fieldValue] of Object.entries(ch.fields)) {
19448
20004
  setActivityFieldDynamic(
19449
20005
  state,
19450
20006
  ch.id,
19451
20007
  field,
19452
- side === "before" ? fieldValue.before : fieldValue.after
20008
+ side === CHANGE_SET_SIDE.BEFORE ? fieldValue.before : fieldValue.after
19453
20009
  );
19454
20010
  }
19455
- } else if (ch.kind === "deleted") {
19456
- if (side === "before") {
20011
+ } else if (ch.kind === ENTITY_CHANGE_KIND.DELETED) {
20012
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19457
20013
  const snap = entry.beforeSnap?.get(String(ch.id));
19458
20014
  if (!snap) {
19459
20015
  throw new Error(
@@ -19465,7 +20021,7 @@ function applyChangeSetSide(state, entry, side) {
19465
20021
  state.removeActivity(String(ch.id));
19466
20022
  }
19467
20023
  } else {
19468
- if (side === "before") {
20024
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19469
20025
  state.removeActivity(String(ch.id));
19470
20026
  } else {
19471
20027
  const snap = entry.afterSnap?.get(String(ch.id));
@@ -19479,13 +20035,13 @@ function applyChangeSetSide(state, entry, side) {
19479
20035
  }
19480
20036
  }
19481
20037
  for (const ch of cs.links) {
19482
- if (ch.kind === "updated") {
20038
+ if (ch.kind === ENTITY_CHANGE_KIND.UPDATED) {
19483
20039
  if (!ch.fields) continue;
19484
20040
  if (Object.hasOwn(ch.fields, "source") || Object.hasOwn(ch.fields, "target")) {
19485
- const snapshot = side === "before" ? entry.beforeLinks?.get(String(ch.id)) : entry.afterLinks?.get(String(ch.id));
20041
+ const snapshot = side === CHANGE_SET_SIDE.BEFORE ? entry.beforeLinks?.get(String(ch.id)) : entry.afterLinks?.get(String(ch.id));
19486
20042
  if (!snapshot) {
19487
20043
  throw new Error(
19488
- `${side === "before" ? "undo" : "redo"}: missing link snapshot for ${ch.id}`
20044
+ `${side === CHANGE_SET_SIDE.BEFORE ? "undo" : "redo"}: missing link snapshot for ${ch.id}`
19489
20045
  );
19490
20046
  }
19491
20047
  state.removeLink(String(ch.id));
@@ -19497,11 +20053,11 @@ function applyChangeSetSide(state, entry, side) {
19497
20053
  state,
19498
20054
  String(ch.id),
19499
20055
  field,
19500
- side === "before" ? fv.before : fv.after
20056
+ side === CHANGE_SET_SIDE.BEFORE ? fv.before : fv.after
19501
20057
  );
19502
20058
  }
19503
- } else if (ch.kind === "deleted") {
19504
- if (side === "before") {
20059
+ } else if (ch.kind === ENTITY_CHANGE_KIND.DELETED) {
20060
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19505
20061
  const lk = entry.beforeLinks?.get(String(ch.id));
19506
20062
  if (!lk) {
19507
20063
  throw new Error(
@@ -19513,7 +20069,7 @@ function applyChangeSetSide(state, entry, side) {
19513
20069
  state.removeLink(String(ch.id));
19514
20070
  }
19515
20071
  } else {
19516
- if (side === "before") {
20072
+ if (side === CHANGE_SET_SIDE.BEFORE) {
19517
20073
  state.removeLink(String(ch.id));
19518
20074
  } else {
19519
20075
  const lk = entry.afterLinks?.get(String(ch.id));
@@ -19530,17 +20086,17 @@ function applyChangeSetSide(state, entry, side) {
19530
20086
  if (change.checked) {
19531
20087
  state.setChecked(
19532
20088
  change.activityId,
19533
- side === "before" ? change.checked.before : change.checked.after
20089
+ side === CHANGE_SET_SIDE.BEFORE ? change.checked.before : change.checked.after
19534
20090
  );
19535
20091
  }
19536
20092
  if (change.visible) {
19537
20093
  state.setVisible(
19538
20094
  change.activityId,
19539
- side === "before" ? change.visible.before : change.visible.after
20095
+ side === CHANGE_SET_SIDE.BEFORE ? change.visible.before : change.visible.after
19540
20096
  );
19541
20097
  }
19542
20098
  }
19543
- const progressFallbacks = side === "before" ? entry.progressFallbackBefore : entry.progressFallbackAfter;
20099
+ const progressFallbacks = side === CHANGE_SET_SIDE.BEFORE ? entry.progressFallbackBefore : entry.progressFallbackAfter;
19544
20100
  for (const [activityId, value] of progressFallbacks ?? []) {
19545
20101
  state.setProgressFallback(activityId, value);
19546
20102
  }
@@ -19677,11 +20233,11 @@ function collectResequencedParents(changes, parentOf) {
19677
20233
  };
19678
20234
  for (const change of changes.activities) {
19679
20235
  const activityId = String(change.id);
19680
- if (change.kind === "created") {
20236
+ if (change.kind === ENTITY_CHANGE_KIND.CREATED) {
19681
20237
  addParentOf(activityId);
19682
20238
  continue;
19683
20239
  }
19684
- if (change.kind === "deleted") {
20240
+ if (change.kind === ENTITY_CHANGE_KIND.DELETED) {
19685
20241
  const deletedFields = change.fields;
19686
20242
  if (deletedFields && "parentId" in deletedFields) {
19687
20243
  touched.add(parentKeyOf2(deletedFields.parentId?.before));
@@ -19744,56 +20300,62 @@ function buildStateSnapshot(activities, links, calendars, baseCalendars = []) {
19744
20300
  };
19745
20301
  }
19746
20302
 
20303
+ // src/boundary/save/field-policy.ts
20304
+ var SAVE_FIELD_POLICY = {
20305
+ TRACKED: "tracked",
20306
+ IGNORED: "ignored"
20307
+ };
20308
+
19747
20309
  // src/boundary/save/activity-changes.ts
19748
20310
  var ACTIVITY_SAVE_FIELD_POLICY = {
19749
- id: "ignored",
19750
- proplannerId: "ignored",
19751
- parentId: "tracked",
19752
- name: "tracked",
19753
- description: "tracked",
19754
- type: "tracked",
19755
- startDate: "tracked",
19756
- endDate: "tracked",
19757
- durationHours: "tracked",
19758
- constraintType: "tracked",
19759
- constraintDate: "tracked",
19760
- autoScheduling: "tracked",
19761
- calendarId: "tracked",
19762
- assignedDefaultCalendar: "ignored",
19763
- dateOrigin: "tracked",
19764
- progress: "tracked",
19765
- cost: "tracked",
19766
- usedCost: "tracked",
19767
- realCost: "tracked",
19768
- workHours: "tracked",
19769
- realWorkHours: "tracked",
19770
- ponderator: "tracked",
19771
- hasCustomPonderator: "tracked",
19772
- correlativeId: "tracked",
19773
- uniqueCorrelativeId: "tracked",
19774
- customId: "tracked",
19775
- subcontractId: "tracked",
19776
- isLookahead: "tracked",
19777
- hasLookaheadTasks: "ignored",
19778
- newActivityIds: "tracked",
19779
- hasNewActivities: "tracked",
19780
- isNewActivity: "ignored",
19781
- pendingRequestIds: "ignored",
19782
- responsableIds: "tracked",
19783
- tagIds: "tracked",
19784
- baselinePoints: "ignored",
19785
- baselineSnapshot: "ignored",
19786
- recursiveDurationHours: "ignored",
19787
- isCritical: "ignored",
19788
- freeSlackHours: "ignored",
19789
- calendarDuration: "ignored",
19790
- expectedProgress: "ignored",
19791
- expectedProgressBaseline: "ignored",
19792
- status: "ignored",
19793
- criticalPath: "ignored"
20311
+ id: SAVE_FIELD_POLICY.IGNORED,
20312
+ proplannerId: SAVE_FIELD_POLICY.IGNORED,
20313
+ parentId: SAVE_FIELD_POLICY.TRACKED,
20314
+ name: SAVE_FIELD_POLICY.TRACKED,
20315
+ description: SAVE_FIELD_POLICY.TRACKED,
20316
+ type: SAVE_FIELD_POLICY.TRACKED,
20317
+ startDate: SAVE_FIELD_POLICY.TRACKED,
20318
+ endDate: SAVE_FIELD_POLICY.TRACKED,
20319
+ durationHours: SAVE_FIELD_POLICY.TRACKED,
20320
+ constraintType: SAVE_FIELD_POLICY.TRACKED,
20321
+ constraintDate: SAVE_FIELD_POLICY.TRACKED,
20322
+ autoScheduling: SAVE_FIELD_POLICY.TRACKED,
20323
+ calendarId: SAVE_FIELD_POLICY.TRACKED,
20324
+ assignedDefaultCalendar: SAVE_FIELD_POLICY.IGNORED,
20325
+ dateOrigin: SAVE_FIELD_POLICY.TRACKED,
20326
+ progress: SAVE_FIELD_POLICY.TRACKED,
20327
+ cost: SAVE_FIELD_POLICY.TRACKED,
20328
+ usedCost: SAVE_FIELD_POLICY.TRACKED,
20329
+ realCost: SAVE_FIELD_POLICY.TRACKED,
20330
+ workHours: SAVE_FIELD_POLICY.TRACKED,
20331
+ realWorkHours: SAVE_FIELD_POLICY.TRACKED,
20332
+ ponderator: SAVE_FIELD_POLICY.TRACKED,
20333
+ hasCustomPonderator: SAVE_FIELD_POLICY.TRACKED,
20334
+ correlativeId: SAVE_FIELD_POLICY.TRACKED,
20335
+ uniqueCorrelativeId: SAVE_FIELD_POLICY.TRACKED,
20336
+ customId: SAVE_FIELD_POLICY.TRACKED,
20337
+ subcontractId: SAVE_FIELD_POLICY.TRACKED,
20338
+ isLookahead: SAVE_FIELD_POLICY.TRACKED,
20339
+ hasLookaheadTasks: SAVE_FIELD_POLICY.IGNORED,
20340
+ newActivityIds: SAVE_FIELD_POLICY.TRACKED,
20341
+ hasNewActivities: SAVE_FIELD_POLICY.TRACKED,
20342
+ isNewActivity: SAVE_FIELD_POLICY.IGNORED,
20343
+ pendingRequestIds: SAVE_FIELD_POLICY.IGNORED,
20344
+ responsableIds: SAVE_FIELD_POLICY.TRACKED,
20345
+ tagIds: SAVE_FIELD_POLICY.TRACKED,
20346
+ baselinePoints: SAVE_FIELD_POLICY.IGNORED,
20347
+ baselineSnapshot: SAVE_FIELD_POLICY.IGNORED,
20348
+ recursiveDurationHours: SAVE_FIELD_POLICY.IGNORED,
20349
+ isCritical: SAVE_FIELD_POLICY.IGNORED,
20350
+ freeSlackHours: SAVE_FIELD_POLICY.IGNORED,
20351
+ calendarDuration: SAVE_FIELD_POLICY.IGNORED,
20352
+ expectedProgress: SAVE_FIELD_POLICY.IGNORED,
20353
+ expectedProgressBaseline: SAVE_FIELD_POLICY.IGNORED,
20354
+ status: SAVE_FIELD_POLICY.IGNORED,
20355
+ criticalPath: SAVE_FIELD_POLICY.IGNORED
19794
20356
  };
19795
20357
  var PERSISTABLE_ACTIVITY_FIELDS = Object.keys(ACTIVITY_SAVE_FIELD_POLICY).filter((field) => {
19796
- return ACTIVITY_SAVE_FIELD_POLICY[field] === "tracked";
20358
+ return ACTIVITY_SAVE_FIELD_POLICY[field] === SAVE_FIELD_POLICY.TRACKED;
19797
20359
  });
19798
20360
  var DATE_FIELDS2 = /* @__PURE__ */ new Set([
19799
20361
  "startDate",
@@ -19852,19 +20414,19 @@ function idArrayEquals(current, saved) {
19852
20414
 
19853
20415
  // src/boundary/save/link-changes.ts
19854
20416
  var LINK_SAVE_FIELD_POLICY = {
19855
- id: "ignored",
19856
- source: "tracked",
19857
- target: "tracked",
19858
- type: "tracked",
19859
- lag: "tracked",
19860
- freeSlackHours: "ignored",
19861
- isCritical: "ignored",
19862
- ganttId: "ignored",
19863
- sectorId: "ignored",
19864
- proplannerId: "ignored"
20417
+ id: SAVE_FIELD_POLICY.IGNORED,
20418
+ source: SAVE_FIELD_POLICY.TRACKED,
20419
+ target: SAVE_FIELD_POLICY.TRACKED,
20420
+ type: SAVE_FIELD_POLICY.TRACKED,
20421
+ lag: SAVE_FIELD_POLICY.TRACKED,
20422
+ freeSlackHours: SAVE_FIELD_POLICY.IGNORED,
20423
+ isCritical: SAVE_FIELD_POLICY.IGNORED,
20424
+ ganttId: SAVE_FIELD_POLICY.IGNORED,
20425
+ sectorId: SAVE_FIELD_POLICY.IGNORED,
20426
+ proplannerId: SAVE_FIELD_POLICY.IGNORED
19865
20427
  };
19866
20428
  var TRACKED_LINK_FIELDS = Object.keys(LINK_SAVE_FIELD_POLICY).filter((field) => {
19867
- return LINK_SAVE_FIELD_POLICY[field] === "tracked";
20429
+ return LINK_SAVE_FIELD_POLICY[field] === SAVE_FIELD_POLICY.TRACKED;
19868
20430
  });
19869
20431
  function linkChangedSince(baseline, current) {
19870
20432
  return TRACKED_LINK_FIELDS.some(
@@ -20225,24 +20787,24 @@ var WORKING_DAY_TRUE_VALUES = /* @__PURE__ */ new Set([
20225
20787
  "true"
20226
20788
  ]);
20227
20789
  var DEFAULT_ACTIVITY_CRETER = ACTIVITY_PONDERATOR_CRITERION.DURATION;
20228
- var DEFAULT_CONSTRAINT_TYPE = "asap";
20790
+ var DEFAULT_CONSTRAINT_TYPE = CONSTRAINT_TYPE.ASAP;
20229
20791
  var CONSTRAINT_LABEL_MAP = {
20230
- ASAP: "asap",
20231
- ALAP: "alap",
20232
- SNET: "snet",
20233
- SNLT: "snlt",
20234
- FNET: "fnet",
20235
- FNLT: "fnlt",
20236
- MSO: "mso",
20237
- MFO: "mfo",
20238
- "AS SOON AS POSSIBLE": "asap",
20239
- "AS LATE AS POSSIBLE": "alap",
20240
- "START NO EARLIER THAN": "snet",
20241
- "START NO LATER THAN": "snlt",
20242
- "FINISH NO EARLIER THAN": "fnet",
20243
- "FINISH NO LATER THAN": "fnlt",
20244
- "MUST START ON": "mso",
20245
- "MUST FINISH ON": "mfo"
20792
+ ASAP: CONSTRAINT_TYPE.ASAP,
20793
+ ALAP: CONSTRAINT_TYPE.ALAP,
20794
+ SNET: CONSTRAINT_TYPE.SNET,
20795
+ SNLT: CONSTRAINT_TYPE.SNLT,
20796
+ FNET: CONSTRAINT_TYPE.FNET,
20797
+ FNLT: CONSTRAINT_TYPE.FNLT,
20798
+ MSO: CONSTRAINT_TYPE.MSO,
20799
+ MFO: CONSTRAINT_TYPE.MFO,
20800
+ "AS SOON AS POSSIBLE": CONSTRAINT_TYPE.ASAP,
20801
+ "AS LATE AS POSSIBLE": CONSTRAINT_TYPE.ALAP,
20802
+ "START NO EARLIER THAN": CONSTRAINT_TYPE.SNET,
20803
+ "START NO LATER THAN": CONSTRAINT_TYPE.SNLT,
20804
+ "FINISH NO EARLIER THAN": CONSTRAINT_TYPE.FNET,
20805
+ "FINISH NO LATER THAN": CONSTRAINT_TYPE.FNLT,
20806
+ "MUST START ON": CONSTRAINT_TYPE.MSO,
20807
+ "MUST FINISH ON": CONSTRAINT_TYPE.MFO
20246
20808
  };
20247
20809
 
20248
20810
  // src/boundary/backend/normalize-activity.ts
@@ -20255,13 +20817,19 @@ function normalizeActivities(rawActivities, context) {
20255
20817
  });
20256
20818
  forceRootProjectToRoot(activities);
20257
20819
  const activityIds = new Set(activities.map((activity) => activity.id));
20258
- reparentOrphansToRoot(activities, activityIds, context.reporter);
20820
+ reparentOrphansToRoot(
20821
+ activities,
20822
+ activityIds,
20823
+ context.reporter,
20824
+ context.recordDiagnostic
20825
+ );
20259
20826
  return { activities, activityIds, hiddenIds };
20260
20827
  }
20261
- function parseConstraintLabel(label, reporter) {
20828
+ function parseConstraintLabel(label, reporter, recordDiagnostic, activityId) {
20262
20829
  if (!label) return null;
20263
20830
  const normalized2 = CONSTRAINT_LABEL_MAP[label.toUpperCase()];
20264
20831
  if (normalized2 === void 0) {
20832
+ recordDiagnostic(LOAD_DIAGNOSTIC_CODE.UNKNOWN_CONSTRAINT, activityId);
20265
20833
  reporter.warn(
20266
20834
  `[parseFromBackend] unknown constraint label "${label}" \u2014 defaulting to "asap"`
20267
20835
  );
@@ -20269,9 +20837,14 @@ function parseConstraintLabel(label, reporter) {
20269
20837
  }
20270
20838
  return normalized2;
20271
20839
  }
20272
- function resolveConstraint(raw, reporter) {
20273
- const constraintType = parseConstraintLabel(raw.constraint, reporter);
20274
- const constraintTakesDate = constraintType !== "asap" && constraintType !== "alap";
20840
+ function resolveConstraint(raw, reporter, recordDiagnostic) {
20841
+ const constraintType = parseConstraintLabel(
20842
+ raw.constraint,
20843
+ reporter,
20844
+ recordDiagnostic,
20845
+ String(raw.unique_id)
20846
+ );
20847
+ const constraintTakesDate = constraintType !== CONSTRAINT_TYPE.ASAP && constraintType !== CONSTRAINT_TYPE.ALAP;
20275
20848
  const constraintDate = constraintTakesDate && raw.constraint_date ? parseBackendDate(raw.constraint_date) : null;
20276
20849
  return { constraintType, constraintDate };
20277
20850
  }
@@ -20326,9 +20899,14 @@ function parseCriticality(raw, reporter) {
20326
20899
  );
20327
20900
  return false;
20328
20901
  }
20329
- function parseBaselinePoints(raw, reporter) {
20902
+ function parseBaselinePoints(raw, reporter, recordDiagnostic, activityId) {
20330
20903
  if (!Array.isArray(raw)) return [];
20331
- return raw.map((point) => normalizeBaselinePoint(point, reporter)).filter((point) => point !== null);
20904
+ return raw.map(
20905
+ (point) => normalizeBaselinePoint(point, reporter, {
20906
+ record: recordDiagnostic,
20907
+ sampleId: activityId
20908
+ })
20909
+ ).filter((point) => point !== null);
20332
20910
  }
20333
20911
  function parseActivity(raw, context) {
20334
20912
  const calendarId = resolveCalendarId2(
@@ -20340,9 +20918,10 @@ function parseActivity(raw, context) {
20340
20918
  const progress = Number(raw.progress);
20341
20919
  const { constraintType, constraintDate } = resolveConstraint(
20342
20920
  raw,
20343
- context.reporter
20921
+ context.reporter,
20922
+ context.recordDiagnostic
20344
20923
  );
20345
- const isMilestone = raw.type === "milestone";
20924
+ const isMilestone = raw.type === ACTIVITY_TYPE.MILESTONE;
20346
20925
  const startDate = parseBackendDate(raw.start_date);
20347
20926
  const endDate = isMilestone ? startDate : parseBackendDate(raw.end_date);
20348
20927
  const durationDays = isMilestone ? 0 : Number(raw.duration);
@@ -20383,7 +20962,12 @@ function parseActivity(raw, context) {
20383
20962
  pendingRequestIds: parseIdList(raw.pendingRequests),
20384
20963
  responsableIds: parseIdList(raw.responsables),
20385
20964
  tagIds: parseIdList(raw.tags),
20386
- baselinePoints: parseBaselinePoints(raw.baseline_points, context.reporter),
20965
+ baselinePoints: parseBaselinePoints(
20966
+ raw.baseline_points,
20967
+ context.reporter,
20968
+ context.recordDiagnostic,
20969
+ String(raw.unique_id)
20970
+ ),
20387
20971
  baselineSnapshot: null,
20388
20972
  recursiveDurationHours: durationToHours(
20389
20973
  Number(raw.sumOfDurationRecursively ?? 0),
@@ -20407,17 +20991,18 @@ function normalizeCustomId(raw) {
20407
20991
  }
20408
20992
  function forceRootProjectToRoot(activities) {
20409
20993
  const rootProject = activities.find(
20410
- (activity) => activity.correlativeId === 0 && activity.type === "project"
20994
+ (activity) => activity.correlativeId === 0 && activity.type === ACTIVITY_TYPE.PROJECT
20411
20995
  );
20412
20996
  if (rootProject) rootProject.parentId = null;
20413
20997
  }
20414
- function reparentOrphansToRoot(activities, ids, reporter) {
20998
+ function reparentOrphansToRoot(activities, ids, reporter, recordDiagnostic) {
20415
20999
  for (const activity of activities) {
20416
21000
  if (activity.parentId === null) continue;
20417
21001
  if (!ids.has(activity.parentId)) {
20418
21002
  reporter.warn(
20419
21003
  `[parseFromBackend] activity "${activity.id}" references unknown parent "${activity.parentId}" \u2014 re-parenting to root (null)`
20420
21004
  );
21005
+ recordDiagnostic(LOAD_DIAGNOSTIC_CODE.ORPHAN_ACTIVITY, activity.id);
20421
21006
  activity.parentId = null;
20422
21007
  }
20423
21008
  }
@@ -20641,14 +21226,11 @@ function isMissingValue(value) {
20641
21226
  }
20642
21227
 
20643
21228
  // src/boundary/backend/normalize-link.ts
20644
- function isLinkTypeCode(value) {
20645
- return value === "0" || value === "1" || value === "2" || value === "3";
20646
- }
20647
21229
  function resolveLinkType(rawType) {
20648
21230
  if (typeof rawType !== "string") return null;
20649
21231
  const fromLabel = parseLinkTypeCode(rawType);
20650
21232
  if (fromLabel) return fromLabel;
20651
- if (isLinkTypeCode(rawType)) return rawType;
21233
+ if (isLinkType(rawType)) return rawType;
20652
21234
  return null;
20653
21235
  }
20654
21236
  function normalizePersistedLinkId(rawId) {
@@ -20667,13 +21249,17 @@ function normalizeLinks(rawLinks, context) {
20667
21249
  parseLink(rawLink, context.knownActivityIds, context.hoursPerDay)
20668
21250
  );
20669
21251
  } catch (parseError2) {
21252
+ context.recordDiagnostic(
21253
+ LOAD_DIAGNOSTIC_CODE.INVALID_LINK,
21254
+ String(rawLink.unique_id ?? rawLink.id)
21255
+ );
20670
21256
  context.reporter.warn(
20671
21257
  "[parseFromBackend] dropping invalid link",
20672
21258
  parseError2
20673
21259
  );
20674
21260
  }
20675
21261
  }
20676
- return dedupeLinksBySignature(parsedLinks);
21262
+ return dedupeLinksBySignature(parsedLinks, context.recordDiagnostic);
20677
21263
  }
20678
21264
  function parseLink(link, activityIds, hoursPerDay) {
20679
21265
  const id = String(link.unique_id ?? link.id);
@@ -20711,12 +21297,19 @@ function parseLink(link, activityIds, hoursPerDay) {
20711
21297
  ...proplannerId === void 0 ? {} : { proplannerId }
20712
21298
  };
20713
21299
  }
20714
- function dedupeLinksBySignature(links) {
21300
+ function dedupeLinksBySignature(links, recordDiagnostic) {
20715
21301
  const bySignature = /* @__PURE__ */ new Map();
20716
21302
  for (const link of links) {
20717
21303
  const signature = `${link.source}-${link.target}-${link.type}`;
20718
21304
  const existing = bySignature.get(signature);
20719
- if (!existing || linkIdAsNumber(link) > linkIdAsNumber(existing)) {
21305
+ if (!existing) {
21306
+ bySignature.set(signature, link);
21307
+ continue;
21308
+ }
21309
+ const incomingWins = linkIdAsNumber(link) > linkIdAsNumber(existing);
21310
+ const discarded = incomingWins ? existing : link;
21311
+ recordDiagnostic(LOAD_DIAGNOSTIC_CODE.DUPLICATE_LINK, discarded.id);
21312
+ if (incomingWins) {
20720
21313
  bySignature.set(signature, link);
20721
21314
  }
20722
21315
  }
@@ -20774,7 +21367,7 @@ function parseSector(sector) {
20774
21367
  }
20775
21368
 
20776
21369
  // src/boundary/backend/parse-from-backend.ts
20777
- function parseFromBackend(input, reporter = noopReporter) {
21370
+ function parseFromBackend(input, reporter = noopReporter, recordDiagnostic = noopLoadDiagnosticRecorder) {
20778
21371
  const sector = parseSector(input.sector);
20779
21372
  const { calendars, baseCalendars, knownCalendarIds, defaultCalendarId } = normalizeCalendars(
20780
21373
  input.calendars,
@@ -20788,13 +21381,15 @@ function parseFromBackend(input, reporter = noopReporter) {
20788
21381
  knownCalendarIds,
20789
21382
  defaultCalendarId,
20790
21383
  hoursPerDay: sector.hoursPerDay,
20791
- reporter
21384
+ reporter,
21385
+ recordDiagnostic
20792
21386
  }
20793
21387
  );
20794
21388
  const links = normalizeLinks(input.links, {
20795
21389
  knownActivityIds: activityIds,
20796
21390
  hoursPerDay: sector.hoursPerDay,
20797
- reporter
21391
+ reporter,
21392
+ recordDiagnostic
20798
21393
  });
20799
21394
  return {
20800
21395
  sector,
@@ -21010,6 +21605,11 @@ function maxSuffixFromArray(suffixes) {
21010
21605
  }
21011
21606
 
21012
21607
  // src/generators/custom-id/generation-strategies.ts
21608
+ var GENERATION_STRATEGY = {
21609
+ PARENT_CONVERSION: "parentConversion",
21610
+ PASTE_REFERENCE: "pasteReference",
21611
+ NO_CONTEXT: "noContext"
21612
+ };
21013
21613
  function parentConversionStrategy(defaultPrefix) {
21014
21614
  return { prefix: defaultPrefix, baseSuffix: null };
21015
21615
  }
@@ -21025,12 +21625,12 @@ function noContextStrategy(defaultPrefix) {
21025
21625
  }
21026
21626
  function selectGenerationStrategy(customId, useActivityCustomIdAsReference) {
21027
21627
  if (isParentConversionCase(customId, useActivityCustomIdAsReference)) {
21028
- return "parentConversion";
21628
+ return GENERATION_STRATEGY.PARENT_CONVERSION;
21029
21629
  }
21030
21630
  if (isPasteOrLineReferenceCase(customId, useActivityCustomIdAsReference)) {
21031
- return "pasteReference";
21631
+ return GENERATION_STRATEGY.PASTE_REFERENCE;
21032
21632
  }
21033
- return "noContext";
21633
+ return GENERATION_STRATEGY.NO_CONTEXT;
21034
21634
  }
21035
21635
 
21036
21636
  // src/generators/custom-id/tracker.ts
@@ -21343,15 +21943,15 @@ var CustomIdTracker = class _CustomIdTracker {
21343
21943
  customId
21344
21944
  );
21345
21945
  let capturedNextSuffix = null;
21346
- if (strategyKey === "parentConversion" && this.prefixMap.has(prefix)) {
21946
+ if (strategyKey === GENERATION_STRATEGY.PARENT_CONVERSION && this.prefixMap.has(prefix)) {
21347
21947
  this._ensureFreshBounds(prefix);
21348
21948
  const currentMax = this.prefixMap.get(prefix).max;
21349
21949
  capturedNextSuffix = addToSuffix(currentMax, this.suffixIncrement);
21350
21950
  }
21351
- if (strategyKey === "parentConversion") {
21951
+ if (strategyKey === GENERATION_STRATEGY.PARENT_CONVERSION) {
21352
21952
  this.releaseCustomId(customId);
21353
21953
  }
21354
- const effectiveBaseSuffix = strategyKey === "parentConversion" && capturedNextSuffix ? capturedNextSuffix : baseSuffix;
21954
+ const effectiveBaseSuffix = strategyKey === GENERATION_STRATEGY.PARENT_CONVERSION && capturedNextSuffix ? capturedNextSuffix : baseSuffix;
21355
21955
  const nextSuffix = this.getNextAvailableSuffix(prefix, effectiveBaseSuffix);
21356
21956
  if (nextSuffix === null) {
21357
21957
  const generatedId2 = this._generateDefaultCustomId();
@@ -21367,9 +21967,9 @@ var CustomIdTracker = class _CustomIdTracker {
21367
21967
  }
21368
21968
  _applyGenerationStrategy(strategyKey, customId) {
21369
21969
  switch (strategyKey) {
21370
- case "parentConversion":
21970
+ case GENERATION_STRATEGY.PARENT_CONVERSION:
21371
21971
  return parentConversionStrategy(this.defaultPrefix);
21372
- case "pasteReference":
21972
+ case GENERATION_STRATEGY.PASTE_REFERENCE:
21373
21973
  return pasteReferenceStrategy(customId, this.suffixIncrement);
21374
21974
  default:
21375
21975
  return noContextStrategy(this.defaultPrefix);
@@ -21485,7 +22085,7 @@ function buildComparator(order, context) {
21485
22085
  function demoteChildlessSummaries(state) {
21486
22086
  const idsToDemote = [];
21487
22087
  state.forEachActivity((activity, activityId) => {
21488
- if (activity.type !== "project") return;
22088
+ if (activity.type !== ACTIVITY_TYPE.PROJECT) return;
21489
22089
  if (state.getChildren(String(activityId)).length === 0) {
21490
22090
  idsToDemote.push(String(activityId));
21491
22091
  }
@@ -21603,7 +22203,7 @@ function normalizeLoadedConstraintDates(state) {
21603
22203
  const type = activity.constraintType;
21604
22204
  if (!type || !activity.constraintDate) return;
21605
22205
  const constraintDate = activity.constraintDate;
21606
- if (activity.type === "milestone" && (constraintDate.getUTCHours() !== 0 || constraintDate.getUTCMinutes() !== 0)) {
22206
+ if (activity.type === ACTIVITY_TYPE.MILESTONE && (constraintDate.getUTCHours() !== 0 || constraintDate.getUTCMinutes() !== 0)) {
21607
22207
  return;
21608
22208
  }
21609
22209
  const calendar = state.calendarReader.getCalendar(
@@ -21619,7 +22219,7 @@ function normalizeLoadedConstraintDates(state) {
21619
22219
  }
21620
22220
  function normalizeMilestoneConstraintDatesForDisplay(state) {
21621
22221
  state.forEachActivity((activity) => {
21622
- if (activity.type !== "milestone") return;
22222
+ if (activity.type !== ACTIVITY_TYPE.MILESTONE) return;
21623
22223
  const type = activity.constraintType;
21624
22224
  if (!type || !activity.constraintDate) return;
21625
22225
  const calendar = state.calendarReader.getCalendar(
@@ -21645,6 +22245,7 @@ function initializeCore(input) {
21645
22245
  const initializedAt = clock?.() ?? null;
21646
22246
  const loadNow = initializedAt ? endOfLocalDay(initializedAt) : null;
21647
22247
  const reporter = input.reporter ?? noopReporter;
22248
+ const loadDiagnostics = createLoadDiagnosticsCollector();
21648
22249
  const parsed2 = parseFromBackend(
21649
22250
  {
21650
22251
  sector: input.sector,
@@ -21653,7 +22254,8 @@ function initializeCore(input) {
21653
22254
  calendars: input.calendars,
21654
22255
  baseCalendars: input.baseCalendars
21655
22256
  },
21656
- reporter
22257
+ reporter,
22258
+ loadDiagnostics.record
21657
22259
  );
21658
22260
  const sector = parsed2.sector;
21659
22261
  sector.statusCriteria = resolveStatusCriteria(input.statusCriteria);
@@ -21693,7 +22295,8 @@ function initializeCore(input) {
21693
22295
  input.baselinePoints,
21694
22296
  loadNow,
21695
22297
  reporter,
21696
- defaultBaseCalendarId
22298
+ defaultBaseCalendarId,
22299
+ loadDiagnostics.record
21697
22300
  );
21698
22301
  }
21699
22302
  const initPromise = runInitialPasses({
@@ -21715,6 +22318,7 @@ function initializeCore(input) {
21715
22318
  baseCalendars,
21716
22319
  clock,
21717
22320
  reporter,
22321
+ loadDiagnostics: loadDiagnostics.snapshot,
21718
22322
  initPromise
21719
22323
  };
21720
22324
  }
@@ -21776,18 +22380,22 @@ function entityChanges(target, source) {
21776
22380
  const before = sourceById.get(id);
21777
22381
  const after = targetById.get(id);
21778
22382
  if (after === void 0) {
21779
- changes.push({ id, kind: "deleted", after: null });
22383
+ changes.push({ id, kind: ENTITY_CHANGE_KIND.DELETED, after: null });
21780
22384
  continue;
21781
22385
  }
21782
22386
  if (before === void 0) {
21783
- changes.push({ id, kind: "created", after: cloneDomainValue(after) });
22387
+ changes.push({
22388
+ id,
22389
+ kind: ENTITY_CHANGE_KIND.CREATED,
22390
+ after: cloneDomainValue(after)
22391
+ });
21784
22392
  continue;
21785
22393
  }
21786
22394
  const fields = changedFields(before, after);
21787
22395
  if (Object.keys(fields).length > 0) {
21788
22396
  changes.push({
21789
22397
  id,
21790
- kind: "updated",
22398
+ kind: ENTITY_CHANGE_KIND.UPDATED,
21791
22399
  fields,
21792
22400
  after: cloneDomainValue(after)
21793
22401
  });
@@ -22002,8 +22610,8 @@ function acknowledgesPersistence(action) {
22002
22610
  }
22003
22611
  function changesRequireFilterProjectionRebuild(changes) {
22004
22612
  for (const change of changes.activities) {
22005
- if (change.kind === "deleted") return true;
22006
- const hasMovedParent = change.kind === "updated" && change.fields !== void 0 && "parentId" in change.fields;
22613
+ if (change.kind === ENTITY_CHANGE_KIND.DELETED) return true;
22614
+ const hasMovedParent = change.kind === ENTITY_CHANGE_KIND.UPDATED && change.fields !== void 0 && "parentId" in change.fields;
22007
22615
  if (hasMovedParent) return true;
22008
22616
  }
22009
22617
  return false;
@@ -22055,6 +22663,7 @@ var ScheduleCore = class _ScheduleCore {
22055
22663
  _undo = new UndoRecorder();
22056
22664
  _opQueue = Promise.resolve();
22057
22665
  _scheduleRevision = 0;
22666
+ _stateRevision = 0;
22058
22667
  _pendingScheduleRevision = 0;
22059
22668
  _criticalPathRevision = -1;
22060
22669
  _activeCriticalPath = null;
@@ -22080,7 +22689,8 @@ var ScheduleCore = class _ScheduleCore {
22080
22689
  ),
22081
22690
  baseCalendars: cloneDomainValue(source.coreRuntime.baseCalendars),
22082
22691
  clock: source.coreRuntime.clock,
22083
- reporter: source.coreRuntime.reporter
22692
+ reporter: source.coreRuntime.reporter,
22693
+ loadDiagnostics: source.coreRuntime.loadDiagnostics
22084
22694
  };
22085
22695
  this._activityClipboard.value = cloneDomainValue(
22086
22696
  source._activityClipboard.value
@@ -22088,6 +22698,7 @@ var ScheduleCore = class _ScheduleCore {
22088
22698
  this._undo = source._undo.fork();
22089
22699
  this._saveTracker = source._saveTracker.fork();
22090
22700
  this._scheduleRevision = source._scheduleRevision;
22701
+ this._stateRevision = source._stateRevision;
22091
22702
  this._pendingScheduleRevision = source._scheduleRevision;
22092
22703
  this._criticalPathRevision = source._criticalPathRevision;
22093
22704
  this._initPromise = Promise.resolve();
@@ -22110,7 +22721,8 @@ var ScheduleCore = class _ScheduleCore {
22110
22721
  initialized.calendars.map((calendar) => [calendar.id, calendar])
22111
22722
  ),
22112
22723
  baseCalendars: initialized.baseCalendars,
22113
- reporter: initialized.reporter
22724
+ reporter: initialized.reporter,
22725
+ loadDiagnostics: initialized.loadDiagnostics
22114
22726
  };
22115
22727
  this._initPromise = initialized.initPromise.then(() => {
22116
22728
  if (this._status === SCHEDULE_CORE_STATUS.DESTROYED) return;
@@ -22175,6 +22787,11 @@ var ScheduleCore = class _ScheduleCore {
22175
22787
  getSector() {
22176
22788
  return cloneDomainValue(this.coreRuntime.sector);
22177
22789
  }
22790
+ /** Returns immutable data-quality diagnostics collected during loading. */
22791
+ getLoadDiagnostics() {
22792
+ this.assertReady();
22793
+ return this.coreRuntime.loadDiagnostics();
22794
+ }
22178
22795
  /**
22179
22796
  * Reads a defensive activity snapshot from a ready schedule.
22180
22797
  *
@@ -22185,6 +22802,17 @@ var ScheduleCore = class _ScheduleCore {
22185
22802
  this.assertReady();
22186
22803
  return readActivity(this.coreRuntime.state, id);
22187
22804
  }
22805
+ /** Returns the canonical progress editability decision without mutation. */
22806
+ getProgressEditability(id) {
22807
+ this.assertReady();
22808
+ const activity = readActivity(this.coreRuntime.state, id);
22809
+ if (!activity) return null;
22810
+ const context = buildPipelineContext(this.coreRuntime.state, {
22811
+ hoursPerDay: this.coreRuntime.sector.hoursPerDay,
22812
+ dateFormat: this.coreRuntime.sector.dateFormat
22813
+ });
22814
+ return progressPipeline.canEdit(activity, context.hierarchy);
22815
+ }
22188
22816
  /**
22189
22817
  * Creates a read-only date prediction bound to the current revision.
22190
22818
  *
@@ -22444,6 +23072,10 @@ var ScheduleCore = class _ScheduleCore {
22444
23072
  getScheduleRevision() {
22445
23073
  return this._scheduleRevision;
22446
23074
  }
23075
+ /** @returns The monotonic canonical-state revision without a readiness guard. */
23076
+ getStateRevision() {
23077
+ return this._stateRevision;
23078
+ }
22447
23079
  /** @returns The undo-history boundary for an external save checkpoint. */
22448
23080
  capturePersistenceHistoryBoundary() {
22449
23081
  this.assertReady();
@@ -22553,6 +23185,21 @@ var ScheduleCore = class _ScheduleCore {
22553
23185
  const admitted = this._beginScheduleMutation(action);
22554
23186
  return this._enqueue(() => this._dispatchInner(action, options, admitted));
22555
23187
  }
23188
+ /** Builds the defensive canonical conversion intent without mutating state. */
23189
+ planLookaheadConversion(input) {
23190
+ this.assertReady();
23191
+ return buildLookaheadConversionPlan(input, {
23192
+ adapter: this.coreRuntime.state,
23193
+ stateRevision: this._stateRevision
23194
+ });
23195
+ }
23196
+ /** Applies one revision-guarded conversion through the serialized dispatcher. */
23197
+ applyLookaheadConversion(input) {
23198
+ return this.dispatch({
23199
+ ...input,
23200
+ kind: DISPATCH_ACTION_KIND.ACTIVITY_LOOKAHEAD_CONVERT
23201
+ });
23202
+ }
22556
23203
  async _dispatchInner(action, options = {}, admitted = false) {
22557
23204
  let changedState = false;
22558
23205
  try {
@@ -22603,6 +23250,7 @@ var ScheduleCore = class _ScheduleCore {
22603
23250
  customIdTracker: this.coreRuntime.customIdTracker,
22604
23251
  reporter: this.coreRuntime.reporter,
22605
23252
  activityClipboard: this._activityClipboard,
23253
+ stateRevision: this._stateRevision,
22606
23254
  defaultBaseCalendarId: this.coreRuntime.baseCalendars.find(
22607
23255
  (calendar) => calendar.baseDefault
22608
23256
  )?.id ?? null,
@@ -22620,7 +23268,7 @@ var ScheduleCore = class _ScheduleCore {
22620
23268
  this.coreRuntime.state.endWriteCapture();
22621
23269
  this.coreRuntime.customIdTracker.commitCustomIdTransaction();
22622
23270
  }
22623
- if (result.ok && historyPolicy === "record" && changeSetIsSubstantive(result.changes)) {
23271
+ if (result.ok && historyPolicy === DISPATCH_HISTORY_POLICY.RECORD && changeSetIsSubstantive(result.changes)) {
22624
23272
  const created = captureCreatedSnapshots(
22625
23273
  this.coreRuntime.state,
22626
23274
  result.changes
@@ -22646,7 +23294,7 @@ var ScheduleCore = class _ScheduleCore {
22646
23294
  );
22647
23295
  }
22648
23296
  if (result.ok) {
22649
- if (historyPolicy === "checkpoint-on-success") {
23297
+ if (historyPolicy === DISPATCH_HISTORY_POLICY.CHECKPOINT_ON_SUCCESS) {
22650
23298
  if (action.kind !== DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE) {
22651
23299
  throw new Error(
22652
23300
  "checkpoint-on-success requires persistence acknowledge"
@@ -22688,7 +23336,9 @@ var ScheduleCore = class _ScheduleCore {
22688
23336
  }
22689
23337
  result = this._withReappliedViewState(action, result);
22690
23338
  if (!result.ok) return { result, changedState: false };
22691
- if (dispatchChangesSchedulingState(action) && changeSetIsSubstantive(result.changes)) {
23339
+ const hasSubstantiveChanges = changeSetIsSubstantive(result.changes);
23340
+ if (hasSubstantiveChanges) this._stateRevision++;
23341
+ if (dispatchChangesSchedulingState(action) && hasSubstantiveChanges) {
22692
23342
  this._recordScheduleMutation(
22693
23343
  options.skipAutoSchedule !== true && options.skipCriticalPath !== true && resolveRunCriticalPath(action)
22694
23344
  );
@@ -22763,7 +23413,7 @@ var ScheduleCore = class _ScheduleCore {
22763
23413
  }
22764
23414
  const affectedParents = new Set(resequencedParents);
22765
23415
  for (const change of changes.activities) {
22766
- if (change.kind === "deleted") {
23416
+ if (change.kind === ENTITY_CHANGE_KIND.DELETED) {
22767
23417
  return { ...changes, order: collectBranchOrder(adapter) };
22768
23418
  }
22769
23419
  const parentId = adapter.getParentId(change.id);
@@ -22957,7 +23607,7 @@ var ScheduleCore = class _ScheduleCore {
22957
23607
  const changes = buildInverseChangeSet(
22958
23608
  this.coreRuntime.state,
22959
23609
  entry,
22960
- "before"
23610
+ CHANGE_SET_SIDE.BEFORE
22961
23611
  );
22962
23612
  this._saveTracker.recordChanges(
22963
23613
  changes.activities,
@@ -23014,7 +23664,7 @@ var ScheduleCore = class _ScheduleCore {
23014
23664
  const changes = buildInverseChangeSet(
23015
23665
  this.coreRuntime.state,
23016
23666
  entry,
23017
- "after"
23667
+ CHANGE_SET_SIDE.AFTER
23018
23668
  );
23019
23669
  this._saveTracker.recordChanges(
23020
23670
  changes.activities,
@@ -23075,6 +23725,7 @@ var ScheduleCore = class _ScheduleCore {
23075
23725
  _rollback(generatorSnapshot) {
23076
23726
  try {
23077
23727
  this.coreRuntime.state.restoreFromCapture();
23728
+ this.coreRuntime.scheduler.invalidateAllCaches();
23078
23729
  this.coreRuntime.customIdTracker.rollbackCustomIdTransaction();
23079
23730
  if (generatorSnapshot) {
23080
23731
  this.coreRuntime.activityIdGenerator.restore(generatorSnapshot[0]);
@@ -23140,6 +23791,7 @@ exports.ACTIVITY_BATCH_MODE = ACTIVITY_BATCH_MODE;
23140
23791
  exports.ACTIVITY_DATE_EDGE = ACTIVITY_DATE_EDGE;
23141
23792
  exports.ACTIVITY_FIELD = ACTIVITY_FIELD;
23142
23793
  exports.ACTIVITY_PONDERATOR_CRITERION = ACTIVITY_PONDERATOR_CRITERION;
23794
+ exports.ACTIVITY_PROGRESS_ORIGIN = ACTIVITY_PROGRESS_ORIGIN;
23143
23795
  exports.ACTIVITY_TYPE = ACTIVITY_TYPE;
23144
23796
  exports.CALENDAR_UNIT = CALENDAR_UNIT;
23145
23797
  exports.CHANGE_SET_SOURCE_KIND = CHANGE_SET_SOURCE_KIND;
@@ -23155,12 +23807,16 @@ exports.DISPATCH_ACTION_KIND = DISPATCH_ACTION_KIND;
23155
23807
  exports.DISPATCH_ACTION_KINDS = DISPATCH_ACTION_KINDS;
23156
23808
  exports.DISPATCH_LINK_OPERATION_KIND = DISPATCH_LINK_OPERATION_KIND;
23157
23809
  exports.DISPATCH_TRACK_EVENT = DISPATCH_TRACK_EVENT;
23810
+ exports.EDIT_ALERT_KEY = EDIT_ALERT_KEY;
23811
+ exports.EDIT_DENIAL_REASON = EDIT_DENIAL_REASON;
23812
+ exports.ENTITY_CHANGE_KIND = ENTITY_CHANGE_KIND;
23158
23813
  exports.FILTER_FIELD = FILTER_FIELD;
23159
23814
  exports.FILTER_LOGIC = FILTER_LOGIC;
23160
23815
  exports.FILTER_OPERATOR = FILTER_OPERATOR;
23161
23816
  exports.FILTER_REJECTION_REASON = FILTER_REJECTION_REASON;
23162
23817
  exports.FILTER_VALUE_KIND = FILTER_VALUE_KIND;
23163
23818
  exports.LINK_BATCH_OPERATION_KIND = LINK_BATCH_OPERATION_KIND;
23819
+ exports.LINK_CODE = LINK_CODE;
23164
23820
  exports.LINK_CODE_TO_TYPE = LINK_CODE_TO_TYPE;
23165
23821
  exports.LINK_REJECTION_REASON = LINK_REJECTION_REASON;
23166
23822
  exports.LINK_RELATIONSHIP = LINK_RELATIONSHIP;