@outbuild-company/schedule-core 1.1.1 → 1.1.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.js CHANGED
@@ -833,49 +833,63 @@ function appendToBucket(index, key, link) {
833
833
  }
834
834
  index.set(key, [link]);
835
835
  }
836
- function filterToChainEndpoints(leaves, adapter, linksByActivity) {
836
+ function filterToChainEndpoints(leaves, adapter, linksByActivity, selectSourceLinks) {
837
837
  if (leaves.length <= 1) return leaves;
838
838
  const leafSet = new Set(leaves.map(String));
839
839
  const keptLeaves = [];
840
840
  for (const leafId of leaves) {
841
- if (!shouldSkipMidChainLeaf(leafId, leafSet, adapter, linksByActivity)) {
841
+ if (!shouldSkipMidChainLeaf(
842
+ leafId,
843
+ leafSet,
844
+ adapter,
845
+ linksByActivity,
846
+ selectSourceLinks
847
+ )) {
842
848
  keptLeaves.push(leafId);
843
849
  }
844
850
  }
845
851
  return keptLeaves.length > 0 ? keptLeaves : leaves;
846
852
  }
847
- function shouldSkipMidChainLeaf(leafId, leafSet, adapter, linksByActivity) {
853
+ function shouldSkipMidChainLeaf(leafId, leafSet, adapter, linksByActivity, selectSourceLinks) {
848
854
  const leafKey = String(leafId);
849
855
  const leafTask = adapter.getActivity(leafId);
850
856
  if (!leafTask) return false;
851
857
  if (leafTask.autoScheduling === false) return false;
852
858
  const linksOnThis = linksByActivity.get(leafKey) ?? [];
853
859
  for (const siblingLink of linksOnThis) {
854
- if (isSelfLink(siblingLink)) continue;
855
- const otherId = otherEndOf(siblingLink, leafKey);
856
- if (!leafSet.has(String(otherId))) continue;
857
- const siblingTask = adapter.getActivity(otherId);
858
- if (!siblingTask) continue;
859
- if (siblingTask.autoScheduling === false) continue;
860
- if (linkConnectsMidChain(siblingLink, leafId, leafTask, otherId, siblingTask)) {
860
+ if (isMidChainConnection(
861
+ siblingLink,
862
+ leafKey,
863
+ leafTask,
864
+ leafSet,
865
+ adapter,
866
+ selectSourceLinks
867
+ ))
861
868
  return true;
862
- }
863
869
  }
864
870
  return false;
865
871
  }
872
+ function isMidChainConnection(link, leafKey, leafTask, leafSet, adapter, selectSourceLinks) {
873
+ if (isSelfLink(link)) return false;
874
+ const relevantDirection = selectSourceLinks ? String(link.source) === leafKey : String(link.target) === leafKey;
875
+ if (!relevantDirection) return false;
876
+ const otherId = otherEndOf(link, leafKey);
877
+ if (!leafSet.has(String(otherId))) return false;
878
+ const siblingTask = adapter.getActivity(otherId);
879
+ return Boolean(
880
+ siblingTask?.autoScheduling !== false && siblingTask && linkConnectsMidChain(link, leafTask, siblingTask)
881
+ );
882
+ }
866
883
  function isSelfLink(link) {
867
884
  return link.source === link.target;
868
885
  }
869
886
  function otherEndOf(link, knownEndKey) {
870
887
  return String(link.source) === knownEndKey ? link.target : link.source;
871
888
  }
872
- function linkConnectsMidChain(link, leafId, leafTask, otherId, siblingTask) {
889
+ function linkConnectsMidChain(link, leafTask, siblingTask) {
873
890
  const lag = link.lag ?? 0;
874
891
  const absLag = Math.abs(lag);
875
- if (link.target === leafId && absLag <= leafTask.durationHours) return true;
876
- if (link.target === otherId && absLag <= siblingTask.durationHours)
877
- return true;
878
- return false;
892
+ return String(link.target) === String(siblingTask.id) && absLag <= siblingTask.durationHours || String(link.target) === String(leafTask.id) && absLag <= leafTask.durationHours;
879
893
  }
880
894
  function expandParentLinks(links, adapter) {
881
895
  const expanded = [];
@@ -884,115 +898,98 @@ function expandParentLinks(links, adapter) {
884
898
  for (const link of links) {
885
899
  const sourceIsSummary = isSummary2(link.source, adapter);
886
900
  const targetIsSummary = isSummary2(link.target, adapter);
887
- if (sourceIsSummary && targetIsSummary) continue;
888
- if (targetIsSummary && isDescendantOf(link.source, link.target, adapter) || sourceIsSummary && isDescendantOf(link.target, link.source, adapter)) {
901
+ if (isInternalSummaryLink(link, sourceIsSummary, targetIsSummary, adapter))
889
902
  continue;
890
- }
891
903
  if (!sourceIsSummary && !targetIsSummary) {
892
904
  expanded.push(link);
893
905
  continue;
894
906
  }
895
- let sourceIds = sourceIsSummary ? getLeafDescendants(link.source, adapter) : [link.source];
896
- let targetIds = targetIsSummary ? getLeafDescendants(link.target, adapter) : [link.target];
897
- if (sourceIsSummary) {
898
- sourceIds = keepBoundDefiningLeaves(sourceIds, false, adapter);
899
- }
900
- if (targetIsSummary) {
901
- const chainEndpoints = filterToChainEndpoints(
902
- targetIds,
903
- adapter,
904
- linksByActivity
905
- );
906
- if (link.type === LINK_TYPE.FINISH_TO_FINISH || link.type === LINK_TYPE.START_TO_FINISH) {
907
- virtualIdCounter = pushOffsetPreservingLinks(
908
- expanded,
909
- sourceIds,
910
- chainEndpoints,
911
- link,
912
- link.target,
913
- adapter,
914
- virtualIdCounter
915
- );
916
- continue;
917
- }
918
- targetIds = keepBoundDefiningLeaves(chainEndpoints, true, adapter);
919
- }
920
- virtualIdCounter = pushExpandedLinks(
907
+ const sourceIds = expandedEndpoints(
908
+ link.source,
909
+ sourceIsSummary,
910
+ adapter,
911
+ linksByActivity,
912
+ true
913
+ );
914
+ const targetIds = expandedEndpoints(
915
+ link.target,
916
+ targetIsSummary,
917
+ adapter,
918
+ linksByActivity,
919
+ false
920
+ );
921
+ virtualIdCounter = pushOffsetPreservingLinks(
921
922
  expanded,
922
923
  sourceIds,
923
924
  targetIds,
924
925
  link,
926
+ adapter,
925
927
  virtualIdCounter
926
928
  );
927
929
  }
928
930
  return expanded;
929
931
  }
930
- function pushOffsetPreservingLinks(expanded, sourceIds, leafIds, originalLink, summaryId, adapter, virtualIdCounter) {
931
- const summary = adapter.getActivity(summaryId);
932
- const summaryStart = summary?.startDate;
933
- const summaryDuration = summary?.durationHours ?? 0;
934
- const userLag = originalLink.lag ?? 0;
932
+ function isInternalSummaryLink(link, sourceIsSummary, targetIsSummary, adapter) {
933
+ return targetIsSummary && isDescendantOf(link.source, link.target, adapter) || sourceIsSummary && isDescendantOf(link.target, link.source, adapter);
934
+ }
935
+ function expandedEndpoints(activityId, summary, adapter, linksByActivity, sourceSide) {
936
+ if (!summary) return [activityId];
937
+ return filterToChainEndpoints(
938
+ getLeafDescendants(activityId, adapter),
939
+ adapter,
940
+ linksByActivity,
941
+ sourceSide
942
+ );
943
+ }
944
+ function pushOffsetPreservingLinks(expanded, sourceIds, leafIds, originalLink, adapter, virtualIdCounter) {
935
945
  const source = adapter.getActivity(originalLink.source);
946
+ const target = adapter.getActivity(originalLink.target);
947
+ const targetStart = target?.startDate;
948
+ const userLag = originalLink.lag ?? 0;
949
+ const sourceEndpointIsStart = originalLink.type === LINK_TYPE.START_TO_START || originalLink.type === LINK_TYPE.START_TO_FINISH;
950
+ const targetEndpointIsFinish = originalLink.type === LINK_TYPE.FINISH_TO_FINISH || originalLink.type === LINK_TYPE.START_TO_FINISH;
951
+ const sourceLag = sourceEndpointIsStart ? -(source?.durationHours ?? 0) : 0;
952
+ const targetLag = targetEndpointIsFinish ? -(target?.durationHours ?? 0) : 0;
936
953
  let counter = virtualIdCounter;
937
954
  for (const srcId of sourceIds) {
938
955
  for (const tgtId of leafIds) {
939
956
  if (String(srcId) === String(tgtId)) continue;
940
- const leaf = adapter.getActivity(tgtId);
941
- const offTarget = summaryStart && leaf && source ? adapter.calculateDuration({
942
- startDate: summaryStart,
943
- endDate: leaf.startDate,
944
- task: source
945
- }) : 0;
946
- expanded.push({
947
- id: `virtual_${originalLink.id}_${counter}`,
948
- source: srcId,
949
- target: tgtId,
950
- type: originalLink.type,
951
- lag: originalLink.lag,
952
- _sourceLag: 0,
953
- _targetLag: -summaryDuration,
954
- _trueLag: userLag + offTarget
955
- });
957
+ expanded.push(
958
+ buildVirtualLink(
959
+ originalLink,
960
+ srcId,
961
+ tgtId,
962
+ counter,
963
+ sourceLag,
964
+ targetLag,
965
+ userLag,
966
+ source,
967
+ targetStart,
968
+ adapter
969
+ )
970
+ );
956
971
  counter += 1;
957
972
  }
958
973
  }
959
974
  return counter;
960
975
  }
961
- function keepBoundDefiningLeaves(leaves, startBound, adapter) {
962
- if (leaves.length <= 1) return leaves;
963
- let best = null;
964
- for (const id of leaves) {
965
- const a = adapter.getActivity(id);
966
- const d = startBound ? a?.startDate : a?.endDate;
967
- if (!d) continue;
968
- const t = d.getTime();
969
- if (best === null) best = t;
970
- else if (startBound ? t < best : t > best) best = t;
971
- }
972
- if (best === null) return leaves;
973
- const kept = leaves.filter((id) => {
974
- const a = adapter.getActivity(id);
975
- const d = startBound ? a?.startDate : a?.endDate;
976
- return d != null && d.getTime() === best;
977
- });
978
- return kept.length > 0 ? kept : leaves;
979
- }
980
- function pushExpandedLinks(expanded, sourceIds, targetIds, originalLink, virtualIdCounter) {
981
- let counter = virtualIdCounter;
982
- for (const srcId of sourceIds) {
983
- for (const tgtId of targetIds) {
984
- if (String(srcId) === String(tgtId)) continue;
985
- expanded.push({
986
- id: `virtual_${originalLink.id}_${counter}`,
987
- source: srcId,
988
- target: tgtId,
989
- type: originalLink.type,
990
- lag: originalLink.lag
991
- });
992
- counter += 1;
993
- }
994
- }
995
- return counter;
976
+ function buildVirtualLink(originalLink, sourceId, targetId, counter, sourceLag, targetLag, userLag, source, targetStart, adapter) {
977
+ const leaf = adapter.getActivity(targetId);
978
+ const offTarget = targetStart && leaf && source ? adapter.calculateDuration({
979
+ startDate: targetStart,
980
+ endDate: leaf.startDate,
981
+ task: source
982
+ }) : 0;
983
+ return {
984
+ id: `virtual_${originalLink.id}_${counter}`,
985
+ source: sourceId,
986
+ target: targetId,
987
+ type: originalLink.type,
988
+ lag: originalLink.lag,
989
+ _sourceLag: sourceLag,
990
+ _targetLag: targetLag,
991
+ _trueLag: userLag + offTarget
992
+ };
996
993
  }
997
994
 
998
995
  // src/autoscheduler/utils/expanded-links-cache.ts
@@ -2258,12 +2255,6 @@ async function updateParentBoundsFromChildren(adapter, dirtyIds, recomputeProgre
2258
2255
  recomputeRealWork: options.recomputeRealWork ?? false
2259
2256
  });
2260
2257
  }
2261
- function recomputeParentBoundsSync(adapter, dirtyIds, recomputeProgress = true) {
2262
- const parents = findAncestorsOfDirty(adapter, dirtyIds);
2263
- for (const parentId of parents) {
2264
- recomputeParentFromChildren(parentId, adapter, recomputeProgress);
2265
- }
2266
- }
2267
2258
  function recomputeSingleParentDisplayBounds(parentId, adapter) {
2268
2259
  recomputeParentFromChildren(parentId, adapter, false);
2269
2260
  }
@@ -3764,6 +3755,7 @@ function buildActivityChanges(adapter, before, touched) {
3764
3755
  }
3765
3756
  const beforeSnap = before.get(id);
3766
3757
  const diff = diffActivity(beforeSnap, afterSnap);
3758
+ if (beforeSnap && Object.keys(diff).length === 0) continue;
3767
3759
  if (!beforeSnap) {
3768
3760
  out.push({
3769
3761
  id,
@@ -3917,6 +3909,77 @@ function computeExpectedProgressLive(rootIds, now, state) {
3917
3909
  for (const activityId of rootIds) visit(activityId);
3918
3910
  return changed;
3919
3911
  }
3912
+ function applyExpectedProgressLive(state, now) {
3913
+ const rootIds = [];
3914
+ state.forEachActivity((activity, activityId) => {
3915
+ if (activity.parentId === null) rootIds.push(activityId);
3916
+ });
3917
+ computeExpectedProgressLive(rootIds, now, state);
3918
+ }
3919
+
3920
+ // src/propagations/shared/get-active-baseline.ts
3921
+ function getActiveBaseline(activity) {
3922
+ const points = activity?.baselinePoints;
3923
+ if (!Array.isArray(points) || points.length === 0) return null;
3924
+ return points.find((point) => point.isActiveVersion) ?? null;
3925
+ }
3926
+
3927
+ // src/columns/expected-progress-base/compute.ts
3928
+ var isProject2 = (a) => a.type === "project";
3929
+ var activeBaselineOf = (a) => getActiveBaseline(a);
3930
+ var leafExpected = (a, now, adapter, defaultBaseCalendarId) => {
3931
+ const base = activeBaselineOf(a);
3932
+ if (!base) return 0;
3933
+ const cal = (base.baseCalendarId != null ? adapter.getBaseCalendar(`${base.baseCalendarId}-base`) : null) ?? (defaultBaseCalendarId ? adapter.getBaseCalendar(defaultBaseCalendarId) : null);
3934
+ if (!cal) return 0;
3935
+ if (!base.startDate || !base.endDate) return 0;
3936
+ return expectedProgressFromBaseline(base.startDate, base.endDate, now, cal);
3937
+ };
3938
+ function computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId = null) {
3939
+ const changed = [];
3940
+ const writeIfChanged = (id, value) => {
3941
+ const a = adapter.getActivity(id);
3942
+ if (!a) return;
3943
+ if (a.expectedProgressBaseline !== value) {
3944
+ adapter.setActivityField(id, "expectedProgressBaseline", value);
3945
+ changed.push(id);
3946
+ }
3947
+ };
3948
+ const visit = (id) => {
3949
+ const a = adapter.getActivity(id);
3950
+ if (!a) return 0;
3951
+ if (!isProject2(a)) {
3952
+ const v2 = leafExpected(a, now, adapter, defaultBaseCalendarId);
3953
+ writeIfChanged(id, v2);
3954
+ return v2;
3955
+ }
3956
+ let acc = 0;
3957
+ for (const childId of adapter.getChildrenIds(id)) {
3958
+ const childBase = visit(childId);
3959
+ const child = adapter.getActivity(childId);
3960
+ const weight = typeof child?.ponderator === "number" ? child.ponderator : 0;
3961
+ acc += childBase * weight;
3962
+ }
3963
+ const v = acc / 100;
3964
+ writeIfChanged(id, v);
3965
+ return v;
3966
+ };
3967
+ for (const id of rootIds) visit(id);
3968
+ return changed;
3969
+ }
3970
+ function runExpectedProgressBase(state, now, defaultBaseCalendarId = null) {
3971
+ const adapter = {
3972
+ getChildrenIds: (parentId) => state.getChildren(String(parentId)).map((childId) => String(childId)),
3973
+ getActivity: (id) => state.getActivity(id),
3974
+ setActivityField: (id, field, value) => setActivityFieldDynamic(state, id, field, value),
3975
+ getBaseCalendar: (engineId) => state.calendarReader.getCalendar(engineId)
3976
+ };
3977
+ const rootIds = [];
3978
+ state.forEachActivity((activity, id) => {
3979
+ if (activity.parentId === null) rootIds.push(id);
3980
+ });
3981
+ return computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId);
3982
+ }
3920
3983
 
3921
3984
  // src/columns/status/compute.ts
3922
3985
  var roundToTwoDecimals = (value) => Math.round(value * 100) / 100;
@@ -3952,594 +4015,290 @@ function applyStatusPass(state, criteria) {
3952
4015
  return changed;
3953
4016
  }
3954
4017
 
3955
- // src/internal/hierarchy/visual-order.ts
3956
- var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
3957
- function getChildrenInVisualOrder(parentId, adapter) {
3958
- const children = collectChildrenSnapshots(parentId, adapter);
3959
- children.sort(byCorrelativeIdThenId);
3960
- return children.map((a) => String(a.id));
3961
- }
3962
- function iterateInVisualOrder(adapter) {
3963
- const result = [];
3964
- const visit = (activity) => {
3965
- result.push(activity);
3966
- const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
3967
- for (const childId of childIds) {
3968
- const child = adapter.getActivity(childId);
3969
- if (child) visit(child);
3970
- }
4018
+ // src/critical-path/legacy/shims/moment.js
4019
+ function moment(input) {
4020
+ const d = input instanceof Date ? new Date(input.getTime()) : input && typeof input === "object" && typeof input.valueOf === "function" ? new Date(input.valueOf()) : new Date(input);
4021
+ const accessor = (getUTC, setUTC) => (value) => {
4022
+ if (value === void 0) return d[getUTC]();
4023
+ d[setUTC](value);
4024
+ return api;
3971
4025
  };
3972
- const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
3973
- for (const rootId of rootIds) {
3974
- const root = adapter.getActivity(rootId);
3975
- if (root) visit(root);
3976
- }
3977
- return result;
4026
+ const api = {
4027
+ __isMomentShim: true,
4028
+ clone: () => moment(d),
4029
+ hours: accessor("getUTCHours", "setUTCHours"),
4030
+ minutes: accessor("getUTCMinutes", "setUTCMinutes"),
4031
+ seconds: accessor("getUTCSeconds", "setUTCSeconds"),
4032
+ milliseconds: accessor("getUTCMilliseconds", "setUTCMilliseconds"),
4033
+ valueOf: () => d.getTime(),
4034
+ toDate: () => new Date(d.getTime()),
4035
+ getTime: () => d.getTime()
4036
+ };
4037
+ return api;
3978
4038
  }
3979
- function findPreviousNonSelectedSibling(taskId, selected, adapter) {
3980
- const activity = adapter.getActivity(taskId);
3981
- if (!activity) return null;
3982
- const parentKey = parentKeyOf(activity);
3983
- const siblings = getChildrenInVisualOrder(parentKey, adapter);
3984
- const idx = siblings.findIndex((id) => String(id) === String(taskId));
3985
- if (idx <= 0) return null;
3986
- for (let i = idx - 1; i >= 0; i--) {
3987
- const candidateId = siblings[i];
3988
- if (candidateId === void 0) continue;
3989
- if (!setHas(selected, candidateId)) return candidateId;
4039
+ moment.isMoment = (x) => Boolean(x) && typeof x === "object" && x.__isMomentShim === true;
4040
+ var moment_default = moment;
4041
+
4042
+ // src/critical-path/legacy/helpers/isValidDate.js
4043
+ function isDate(obj) {
4044
+ if (obj && obj.constructor === Date) {
4045
+ return Boolean(obj.getFullYear && obj.getMonth && obj.getDate);
3990
4046
  }
3991
- return null;
4047
+ return false;
3992
4048
  }
3993
- function visualIndexInParent(taskId, adapter) {
3994
- const activity = adapter.getActivity(taskId);
3995
- if (!activity) return -1;
3996
- const parentKey = parentKeyOf(activity);
3997
- const siblings = getChildrenInVisualOrder(parentKey, adapter);
3998
- return siblings.findIndex((id) => String(id) === String(taskId));
4049
+ function isValidDate2(obj) {
4050
+ return isDate(obj) && !isNaN(obj.getTime());
3999
4051
  }
4000
- function collectChildrenSnapshots(parentId, adapter) {
4001
- const key = String(parentId);
4002
- if (key === "0") {
4003
- return adapter.getAllActivities().filter((a) => a.parentId === null);
4004
- }
4005
- const childIds = adapter.getChildren(parentId);
4006
- const out = [];
4007
- for (const id of childIds) {
4008
- const snap = adapter.getActivity(id);
4009
- if (snap) out.push(snap);
4052
+
4053
+ // src/critical-path/legacy/helpers/addDurationToDate.js
4054
+ function addDurationToDate(activityCalendar, date2, duration, activity) {
4055
+ if (!isValidDate2(new Date(date2))) {
4056
+ throw new Error(
4057
+ `Invalid date argument for calculateEndDate method. Date: ${date2}, Activity: ${JSON.stringify(activity)}`
4058
+ );
4010
4059
  }
4011
- return out;
4012
- }
4013
- function byCorrelativeIdThenId(a, b) {
4014
- const ac = correlativeIdOf(a);
4015
- const bc = correlativeIdOf(b);
4016
- if (ac !== bc) return ac - bc;
4017
- return String(a.id).localeCompare(String(b.id));
4018
- }
4019
- function correlativeIdOf(activity) {
4020
- const raw = activity.correlativeId;
4021
- const n = typeof raw === "number" ? raw : Number(raw);
4022
- return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
4023
- }
4024
- function parentKeyOf(activity) {
4025
- const parentId = activity.parentId;
4026
- if (parentId === null) return "0";
4027
- return parentId;
4028
- }
4029
- function setHas(set, id) {
4030
- if (set.has(id)) return true;
4031
- return set.has(String(id));
4060
+ const dateToCalculate = date2;
4061
+ return activityCalendar.calculateEndDate({
4062
+ start_date: new Date(dateToCalculate),
4063
+ duration,
4064
+ unit: "hour",
4065
+ task: activity
4066
+ });
4032
4067
  }
4033
4068
 
4034
- // src/internal/hierarchy/recompute-correlative-ids.ts
4035
- function recomputeCorrelativeIds(adapter) {
4036
- adapter.invalidateVisualOrderIds?.();
4037
- const roots = [];
4038
- adapter.forEachActivity((activity) => {
4039
- if (isRootParent(activity.parentId)) roots.push(activity);
4069
+ // src/critical-path/legacy/helpers/getNextWorkingHour.js
4070
+ function getNextWorkingHour(activityParams) {
4071
+ if (!isValidDate2(new Date(activityParams.dateBaseToCalculate))) {
4072
+ throw new Error("Invalid date argument for getClosestWorkTime method");
4073
+ }
4074
+ const { dateBaseToCalculate, activityCalendar, direction, activity } = activityParams;
4075
+ const newDate = activityCalendar.$gantt.getClosestWorkTime({
4076
+ date: new Date(dateBaseToCalculate),
4077
+ dir: direction,
4078
+ unit: "hour",
4079
+ task: activity
4040
4080
  });
4041
- roots.sort(byCorrelativeId);
4042
- const stack = [];
4043
- pushInReverseOrder(stack, roots);
4044
- const shifts = [];
4045
- let counter = 0;
4046
- while (stack.length > 0) {
4047
- const activity = stack.pop();
4048
- if (activity.correlativeId !== counter) {
4049
- const before = typeof activity.correlativeId === "number" ? activity.correlativeId : void 0;
4050
- shifts.push({ activityId: String(activity.id), before });
4051
- if (before !== void 0)
4052
- adapter.noteCorrelativeBefore?.(String(activity.id), before);
4053
- setCorrelativeId(activity, counter);
4054
- }
4055
- counter += 1;
4056
- const children = collectChildrenSnapshots(String(activity.id), adapter);
4057
- children.sort(byCorrelativeId);
4058
- pushInReverseOrder(stack, children);
4059
- }
4060
- return shifts;
4061
- }
4062
- function pushInReverseOrder(stack, activities) {
4063
- for (let i = activities.length - 1; i >= 0; i -= 1) {
4064
- stack.push(activities[i]);
4065
- }
4066
- }
4067
- function getCorrelativeId(activity) {
4068
- const raw = activity.correlativeId;
4069
- const n = typeof raw === "number" ? raw : Number(raw);
4070
- return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
4071
- }
4072
- var byCorrelativeId = (a, b) => getCorrelativeId(a) - getCorrelativeId(b);
4073
- function setCorrelativeId(activity, value) {
4074
- activity.correlativeId = value;
4081
+ return newDate;
4075
4082
  }
4076
4083
 
4077
- // src/propagations/upward/recompute-real-work.ts
4078
- function recomputeCanonicalRealWork(state) {
4079
- const rootIds = [];
4080
- const changedIds = [];
4081
- state.forEachActivity((activity, activityId) => {
4082
- if (activity.parentId === null) rootIds.push(String(activityId));
4083
- });
4084
- const visit = (activityId) => {
4085
- const activity = state.getActivity(activityId);
4086
- if (!activity) return 0;
4087
- const childIds = [...state.getChildren(activityId)];
4088
- const realWork = childIds.length === 0 ? computeLeafRealWork(activity.workHours, activity.progress) : childIds.reduce(
4089
- (total, childId) => total + visit(String(childId)),
4090
- 0
4091
- );
4092
- state.setActivityField(
4093
- activityId,
4094
- ACTIVITY_PROPERTY.REAL_WORK_HOURS,
4095
- realWork
4096
- );
4097
- changedIds.push(activityId);
4098
- return realWork;
4084
+ // src/critical-path/legacy/helpers/filters.js
4085
+ var byFirstLevel = (activity) => {
4086
+ if (!activity) return false;
4087
+ return activity["$level"] === 1;
4088
+ };
4089
+ var filterByParentType = (activity) => activity.type === "project";
4090
+ var avoidSubproject = (activity) => activity["$level"] !== 0;
4091
+ var byTaskType = (activity) => activity.type === "task";
4092
+ var byTaskTypeAndMilestone = (activity) => activity.type === "task" || activity.type === "milestone";
4093
+ var filters_default = {
4094
+ byFirstLevel,
4095
+ filterByParentType,
4096
+ avoidSubproject,
4097
+ byTaskType,
4098
+ byTaskTypeAndMilestone
4099
+ };
4100
+
4101
+ // src/critical-path/legacy/constants/constraints.js
4102
+ var CONSTRAINT_TYPES = Object.freeze({
4103
+ MFO: "mfo",
4104
+ MSO: "mso",
4105
+ FNLT: "fnlt",
4106
+ FNET: "fnet",
4107
+ SNET: "snet",
4108
+ SNLT: "snlt",
4109
+ ALAP: "alap",
4110
+ ASAP: "asap"
4111
+ });
4112
+
4113
+ // src/critical-path/legacy/constants/linkTypes.js
4114
+ var LINK_TYPES = Object.freeze({
4115
+ FS: "fs",
4116
+ SS: "ss",
4117
+ FF: "ff",
4118
+ SF: "sf"
4119
+ });
4120
+
4121
+ // src/critical-path/legacy/constants/linkByCode.js
4122
+ function getLinkNameByCode(code) {
4123
+ const linkMap = {
4124
+ 0: "fs",
4125
+ 1: "ss",
4126
+ 2: "ff",
4127
+ 3: "sf"
4099
4128
  };
4100
- for (const rootId of rootIds) visit(rootId);
4101
- return changedIds;
4129
+ return linkMap[Number(code)] || "sf";
4102
4130
  }
4103
4131
 
4104
- // src/init/initial-passes.ts
4105
- async function runInitialPasses(deps) {
4106
- const { state, sector, scheduler, skipAutoSchedule, now } = deps;
4107
- recomputeCorrelativeIds(state);
4108
- if (sector.updateDurationForPrimaveraEndDate) {
4109
- recomputeDurationsFromDates(state);
4110
- }
4111
- normalizeLoadedConstraintDates(state);
4112
- recomputeCanonicalRealWork(state);
4113
- if (skipAutoSchedule) {
4114
- if (now) {
4115
- applyExpectedProgressLive(state, now);
4116
- applyStatusPass(state, sector.statusCriteria);
4132
+ // src/critical-path/legacy/base/identifiers/secondLevelActivities.js
4133
+ function identifySecondLevelActivities(params) {
4134
+ const { gantt, pendingParentsWithNoLinks, calculations, linkProperty } = params;
4135
+ try {
4136
+ const subprojectsWithNoLinks = getSubprojectsWithNoLinks({
4137
+ gantt,
4138
+ pendingParentsWithNoLinks
4139
+ });
4140
+ if (subprojectsWithNoLinks.length === 0) {
4141
+ return /* @__PURE__ */ new Set();
4117
4142
  }
4118
- return;
4119
- }
4120
- const result = await scheduler.schedule({});
4121
- applyResults(state, result);
4122
- normalizeMilestoneConstraintDatesForDisplay(state);
4123
- recomputeSkippedLeafEnds(state);
4124
- await updateParentBoundsFromChildren(state, void 0, false);
4125
- if (now) {
4126
- applyExpectedProgressLive(state, now);
4127
- applyStatusPass(state, sector.statusCriteria);
4143
+ const allChildrenFromParents = getAllChildrenFromParents({
4144
+ gantt,
4145
+ subprojectsWithNoLinks
4146
+ });
4147
+ const childrenThatCanBeCalculated = filterChildrenThatCanBeCalculated({
4148
+ gantt,
4149
+ childrenIds: allChildrenFromParents,
4150
+ linkProperty,
4151
+ getArrayOfLinkedActivities,
4152
+ calculations
4153
+ });
4154
+ return new Set(childrenThatCanBeCalculated.map((activity) => activity.id));
4155
+ } catch (e) {
4156
+ throw e;
4128
4157
  }
4129
4158
  }
4130
- function applyExpectedProgressLive(state, now) {
4131
- const rootIds = [];
4132
- state.forEachActivity((activity, activityId) => {
4133
- if (activity.parentId === null) rootIds.push(activityId);
4134
- });
4135
- computeExpectedProgressLive(rootIds, now, state);
4159
+ function getSubprojectsWithNoLinks(params) {
4160
+ const { gantt, pendingParentsWithNoLinks } = params;
4161
+ return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter((activity) => pendingParentsWithNoLinks.has(activity.id)).map((activity) => activity.id);
4136
4162
  }
4137
- function recomputeSkippedLeafEnds(state) {
4138
- state.forEachActivity((activity) => {
4139
- if (activity.autoScheduling) return;
4140
- if (!activity.startDate || activity.durationHours == null) return;
4141
- if (state.getChildren(activity.id).length > 0) return;
4142
- activity.endDate = state.calculateEndDate({
4143
- startDate: activity.startDate,
4144
- durationHours: activity.durationHours,
4145
- task: activity
4163
+ function getAllChildrenFromParents(params) {
4164
+ const { gantt, subprojectsWithNoLinks } = params;
4165
+ const allChildrenSet = /* @__PURE__ */ new Set();
4166
+ for (const subprojectId of subprojectsWithNoLinks) {
4167
+ const childrenIds = gantt.getChildren(subprojectId);
4168
+ const validChildren = childrenIds.filter((childId) => {
4169
+ const childActivity = gantt.getTask(childId);
4170
+ const isTaskOrMilestone = filters_default.byTaskTypeAndMilestone(childActivity);
4171
+ const hasProgressLessThan100 = Number(childActivity.progress) < 100;
4172
+ return isTaskOrMilestone && hasProgressLessThan100;
4146
4173
  });
4147
- });
4174
+ validChildren.forEach((childId) => allChildrenSet.add(childId));
4175
+ }
4176
+ return [...allChildrenSet];
4148
4177
  }
4149
- function recomputeDurationsFromDates(state) {
4150
- state.forEachActivity((activity) => {
4151
- if (!activity.startDate || !activity.endDate) return;
4152
- activity.durationHours = state.calculateDuration({
4153
- startDate: activity.startDate,
4154
- endDate: activity.endDate,
4155
- task: activity
4178
+ function filterChildrenThatCanBeCalculated(params) {
4179
+ const {
4180
+ gantt,
4181
+ childrenIds,
4182
+ linkProperty,
4183
+ getArrayOfLinkedActivities: getArrayOfLinkedActivities3,
4184
+ calculations
4185
+ } = params;
4186
+ const calculableChildren = [];
4187
+ for (const childId of childrenIds) {
4188
+ const activity = gantt.getTask(childId);
4189
+ const links = activity[linkProperty] || [];
4190
+ const linkedActivities = getArrayOfLinkedActivities3({
4191
+ gantt,
4192
+ links,
4193
+ linkDirection: linkProperty === "$source" ? "target" : "source"
4156
4194
  });
4157
- });
4158
- }
4159
- function normalizeLoadedConstraintDates(state) {
4160
- state.forEachActivity((activity) => {
4161
- const type = activity.constraintType;
4162
- if (!type || !activity.constraintDate) return;
4163
- const constraintDate = activity.constraintDate;
4164
- if (activity.type === "milestone" && (constraintDate.getUTCHours() !== 0 || constraintDate.getUTCMinutes() !== 0)) {
4165
- return;
4166
- }
4167
- const calendar = state.calendarReader.getCalendar(
4168
- String(activity.calendarId)
4169
- );
4170
- if (!calendar) return;
4171
- activity.constraintDate = normalizeConstraintDate(
4172
- activity.constraintDate,
4173
- calendar,
4174
- type
4195
+ const isLinkedWithCalculatedOrSibling = linkedActivities.every(
4196
+ (linkedActivityId) => calculations.has(linkedActivityId)
4175
4197
  );
4176
- });
4198
+ if (isLinkedWithCalculatedOrSibling) {
4199
+ calculableChildren.push(activity);
4200
+ }
4201
+ }
4202
+ return calculableChildren;
4177
4203
  }
4178
- function normalizeMilestoneConstraintDatesForDisplay(state) {
4179
- state.forEachActivity((activity) => {
4180
- if (activity.type !== "milestone") return;
4181
- const type = activity.constraintType;
4182
- if (!type || !activity.constraintDate) return;
4183
- const calendar = state.calendarReader.getCalendar(
4184
- String(activity.calendarId)
4185
- );
4186
- if (!calendar) return;
4187
- activity.constraintDate = normalizeConstraintDate(
4188
- activity.constraintDate,
4189
- calendar,
4190
- type
4191
- );
4192
- });
4204
+ function getArrayOfLinkedActivities(params) {
4205
+ const { gantt, links, linkDirection } = params;
4206
+ const linkedActivityIds = [];
4207
+ for (const linkId of links) {
4208
+ const link = gantt.getLink(linkId);
4209
+ if (!link) {
4210
+ continue;
4211
+ }
4212
+ const linkedActivityId = Number(link[linkDirection]);
4213
+ linkedActivityIds.push(linkedActivityId);
4214
+ }
4215
+ return linkedActivityIds;
4193
4216
  }
4194
4217
 
4195
- // src/propagations/shared/get-active-baseline.ts
4196
- function getActiveBaseline(activity) {
4197
- const points = activity?.baselinePoints;
4198
- if (!Array.isArray(points) || points.length === 0) return null;
4199
- return points.find((point) => point.isActiveVersion) ?? null;
4200
- }
4201
-
4202
- // src/columns/expected-progress-base/compute.ts
4203
- var isProject2 = (a) => a.type === "project";
4204
- var activeBaselineOf = (a) => getActiveBaseline(a);
4205
- var leafExpected = (a, now, adapter, defaultBaseCalendarId) => {
4206
- const base = activeBaselineOf(a);
4207
- if (!base) return 0;
4208
- const cal = (base.baseCalendarId != null ? adapter.getBaseCalendar(`${base.baseCalendarId}-base`) : null) ?? (defaultBaseCalendarId ? adapter.getBaseCalendar(defaultBaseCalendarId) : null);
4209
- if (!cal) return 0;
4210
- if (!base.startDate || !base.endDate) return 0;
4211
- return expectedProgressFromBaseline(base.startDate, base.endDate, now, cal);
4212
- };
4213
- function computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId = null) {
4214
- const changed = [];
4215
- const writeIfChanged = (id, value) => {
4216
- const a = adapter.getActivity(id);
4217
- if (!a) return;
4218
- if (a.expectedProgressBaseline !== value) {
4219
- adapter.setActivityField(id, "expectedProgressBaseline", value);
4220
- changed.push(id);
4221
- }
4222
- };
4223
- const visit = (id) => {
4224
- const a = adapter.getActivity(id);
4225
- if (!a) return 0;
4226
- if (!isProject2(a)) {
4227
- const v2 = leafExpected(a, now, adapter, defaultBaseCalendarId);
4228
- writeIfChanged(id, v2);
4229
- return v2;
4218
+ // src/critical-path/legacy/base/identifiers/initialActivities.js
4219
+ function identifyInitialActivities({ gantt, linkProperty, direction }) {
4220
+ try {
4221
+ const chainStartActivities = getChainStartActivities(gantt, linkProperty);
4222
+ if (direction === "forward") {
4223
+ return {
4224
+ chainStartActivities,
4225
+ activitiesStartChainButChildrenOfLinkedParents: null
4226
+ };
4230
4227
  }
4231
- let acc = 0;
4232
- for (const childId of adapter.getChildrenIds(id)) {
4233
- const childBase = visit(childId);
4234
- const child = adapter.getActivity(childId);
4235
- const weight = typeof child?.ponderator === "number" ? child.ponderator : 0;
4236
- acc += childBase * weight;
4228
+ if (direction === "backward") {
4229
+ return processBackwardActivities(
4230
+ chainStartActivities,
4231
+ gantt,
4232
+ linkProperty
4233
+ );
4237
4234
  }
4238
- const v = acc / 100;
4239
- writeIfChanged(id, v);
4240
- return v;
4241
- };
4242
- for (const id of rootIds) visit(id);
4243
- return changed;
4244
- }
4245
- function runExpectedProgressBase(state, now, defaultBaseCalendarId = null) {
4246
- const adapter = {
4247
- getChildrenIds: (parentId) => state.getChildren(String(parentId)).map((childId) => String(childId)),
4248
- getActivity: (id) => state.getActivity(id),
4249
- setActivityField: (id, field, value) => setActivityFieldDynamic(state, id, field, value),
4250
- getBaseCalendar: (engineId) => state.calendarReader.getCalendar(engineId)
4251
- };
4252
- const rootIds = [];
4253
- state.forEachActivity((activity, id) => {
4254
- if (activity.parentId === null) rootIds.push(id);
4255
- });
4256
- return computeExpectedProgress(rootIds, now, adapter, defaultBaseCalendarId);
4257
- }
4258
-
4259
- // src/critical-path/legacy/shims/moment.js
4260
- function moment(input) {
4261
- const d = input instanceof Date ? new Date(input.getTime()) : input && typeof input === "object" && typeof input.valueOf === "function" ? new Date(input.valueOf()) : new Date(input);
4262
- const accessor = (getUTC, setUTC) => (value) => {
4263
- if (value === void 0) return d[getUTC]();
4264
- d[setUTC](value);
4265
- return api;
4266
- };
4267
- const api = {
4268
- __isMomentShim: true,
4269
- clone: () => moment(d),
4270
- hours: accessor("getUTCHours", "setUTCHours"),
4271
- minutes: accessor("getUTCMinutes", "setUTCMinutes"),
4272
- seconds: accessor("getUTCSeconds", "setUTCSeconds"),
4273
- milliseconds: accessor("getUTCMilliseconds", "setUTCMilliseconds"),
4274
- valueOf: () => d.getTime(),
4275
- toDate: () => new Date(d.getTime()),
4276
- getTime: () => d.getTime()
4277
- };
4278
- return api;
4279
- }
4280
- moment.isMoment = (x) => Boolean(x) && typeof x === "object" && x.__isMomentShim === true;
4281
- var moment_default = moment;
4282
-
4283
- // src/critical-path/legacy/helpers/isValidDate.js
4284
- function isDate(obj) {
4285
- if (obj && obj.constructor === Date) {
4286
- return Boolean(obj.getFullYear && obj.getMonth && obj.getDate);
4235
+ } catch (e) {
4236
+ console.log("Critical Path", e);
4237
+ throw e;
4287
4238
  }
4288
- return false;
4289
- }
4290
- function isValidDate2(obj) {
4291
- return isDate(obj) && !isNaN(obj.getTime());
4292
4239
  }
4293
-
4294
- // src/critical-path/legacy/helpers/addDurationToDate.js
4295
- function addDurationToDate(activityCalendar, date2, duration, activity) {
4296
- if (!isValidDate2(new Date(date2))) {
4297
- throw new Error(
4298
- `Invalid date argument for calculateEndDate method. Date: ${date2}, Activity: ${JSON.stringify(activity)}`
4299
- );
4300
- }
4301
- const dateToCalculate = date2;
4302
- return activityCalendar.calculateEndDate({
4303
- start_date: new Date(dateToCalculate),
4304
- duration,
4305
- unit: "hour",
4306
- task: activity
4307
- });
4240
+ function getChainStartActivities(gantt, linkProperty) {
4241
+ return gantt.getTaskByTime().filter(filters_default.avoidSubproject).filter(filters_default.byTaskTypeAndMilestone).filter((activity) => !activity[linkProperty].length);
4308
4242
  }
4309
-
4310
- // src/critical-path/legacy/helpers/getNextWorkingHour.js
4311
- function getNextWorkingHour(activityParams) {
4312
- if (!isValidDate2(new Date(activityParams.dateBaseToCalculate))) {
4313
- throw new Error("Invalid date argument for getClosestWorkTime method");
4314
- }
4315
- const { dateBaseToCalculate, activityCalendar, direction, activity } = activityParams;
4316
- const newDate = activityCalendar.$gantt.getClosestWorkTime({
4317
- date: new Date(dateBaseToCalculate),
4318
- dir: direction,
4319
- unit: "hour",
4320
- task: activity
4243
+ function processBackwardActivities(chainStartActivities, gantt, linkProperty) {
4244
+ const withoutLinkedParents = [];
4245
+ const activitiesStartChainButChildrenOfLinkedParents = /* @__PURE__ */ new Set();
4246
+ chainStartActivities.forEach((activity) => {
4247
+ const parentId = Number(activity.parent);
4248
+ const parentActivity = gantt.getTask(parentId);
4249
+ if (!parentActivity) return;
4250
+ if (parentActivity[linkProperty].length > 0) {
4251
+ activitiesStartChainButChildrenOfLinkedParents.add(activity.id);
4252
+ } else if (parentActivity.constraint_type !== "fnlt") {
4253
+ withoutLinkedParents.push(activity);
4254
+ }
4321
4255
  });
4322
- return newDate;
4323
- }
4324
-
4325
- // src/critical-path/legacy/helpers/filters.js
4326
- var byFirstLevel = (activity) => {
4327
- if (!activity) return false;
4328
- return activity["$level"] === 1;
4329
- };
4330
- var filterByParentType = (activity) => activity.type === "project";
4331
- var avoidSubproject = (activity) => activity["$level"] !== 0;
4332
- var byTaskType = (activity) => activity.type === "task";
4333
- var byTaskTypeAndMilestone = (activity) => activity.type === "task" || activity.type === "milestone";
4334
- var filters_default = {
4335
- byFirstLevel,
4336
- filterByParentType,
4337
- avoidSubproject,
4338
- byTaskType,
4339
- byTaskTypeAndMilestone
4340
- };
4341
-
4342
- // src/critical-path/legacy/constants/constraints.js
4343
- var CONSTRAINT_TYPES = Object.freeze({
4344
- MFO: "mfo",
4345
- MSO: "mso",
4346
- FNLT: "fnlt",
4347
- FNET: "fnet",
4348
- SNET: "snet",
4349
- SNLT: "snlt",
4350
- ALAP: "alap",
4351
- ASAP: "asap"
4352
- });
4353
-
4354
- // src/critical-path/legacy/constants/linkTypes.js
4355
- var LINK_TYPES = Object.freeze({
4356
- FS: "fs",
4357
- SS: "ss",
4358
- FF: "ff",
4359
- SF: "sf"
4360
- });
4361
-
4362
- // src/critical-path/legacy/constants/linkByCode.js
4363
- function getLinkNameByCode(code) {
4364
- const linkMap = {
4365
- 0: "fs",
4366
- 1: "ss",
4367
- 2: "ff",
4368
- 3: "sf"
4256
+ return {
4257
+ chainStartActivities: withoutLinkedParents,
4258
+ activitiesStartChainButChildrenOfLinkedParents
4369
4259
  };
4370
- return linkMap[Number(code)] || "sf";
4371
4260
  }
4372
4261
 
4373
- // src/critical-path/legacy/base/identifiers/secondLevelActivities.js
4374
- function identifySecondLevelActivities(params) {
4375
- const { gantt, pendingParentsWithNoLinks, calculations, linkProperty } = params;
4262
+ // src/critical-path/legacy/base/identifiers/identifyParentsWithAndWithoutLinks.js
4263
+ function identifyParentsWithAndWithoutLinks({
4264
+ gantt,
4265
+ direction,
4266
+ linkProperty
4267
+ }) {
4376
4268
  try {
4377
- const subprojectsWithNoLinks = getSubprojectsWithNoLinks({
4378
- gantt,
4379
- pendingParentsWithNoLinks
4380
- });
4381
- if (subprojectsWithNoLinks.length === 0) {
4382
- return /* @__PURE__ */ new Set();
4269
+ const allParentActivities = getAllParentActivities(gantt);
4270
+ const parentsWithFullProgress = /* @__PURE__ */ new Set();
4271
+ const pendingParentsWithNoLinks = /* @__PURE__ */ new Set();
4272
+ const pendingParentsWithLinks = /* @__PURE__ */ new Set();
4273
+ if (direction === "backward") {
4274
+ const parentsWithFullProgressArray = getParentsWithFullProgress(allParentActivities);
4275
+ parentsWithFullProgressArray.forEach((activity) => {
4276
+ parentsWithFullProgress.add(activity.id);
4277
+ });
4383
4278
  }
4384
- const allChildrenFromParents = getAllChildrenFromParents({
4385
- gantt,
4386
- subprojectsWithNoLinks
4279
+ const parentsWithNoLinks = getParentsWithNoLinks(
4280
+ allParentActivities,
4281
+ direction,
4282
+ linkProperty
4283
+ );
4284
+ const difference = getDifference(allParentActivities, parentsWithNoLinks);
4285
+ parentsWithNoLinks.forEach((activity) => {
4286
+ pendingParentsWithNoLinks.add(activity.id);
4387
4287
  });
4388
- const childrenThatCanBeCalculated = filterChildrenThatCanBeCalculated({
4389
- gantt,
4390
- childrenIds: allChildrenFromParents,
4391
- linkProperty,
4392
- getArrayOfLinkedActivities,
4393
- calculations
4288
+ difference.forEach((activity) => {
4289
+ pendingParentsWithLinks.add(activity.id);
4394
4290
  });
4395
- return new Set(childrenThatCanBeCalculated.map((activity) => activity.id));
4291
+ return {
4292
+ parentsWithFullProgress,
4293
+ pendingParentsWithNoLinks,
4294
+ pendingParentsWithLinks
4295
+ };
4396
4296
  } catch (e) {
4397
4297
  throw e;
4398
4298
  }
4399
4299
  }
4400
- function getSubprojectsWithNoLinks(params) {
4401
- const { gantt, pendingParentsWithNoLinks } = params;
4402
- return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter((activity) => pendingParentsWithNoLinks.has(activity.id)).map((activity) => activity.id);
4403
- }
4404
- function getAllChildrenFromParents(params) {
4405
- const { gantt, subprojectsWithNoLinks } = params;
4406
- const allChildrenSet = /* @__PURE__ */ new Set();
4407
- for (const subprojectId of subprojectsWithNoLinks) {
4408
- const childrenIds = gantt.getChildren(subprojectId);
4409
- const validChildren = childrenIds.filter((childId) => {
4410
- const childActivity = gantt.getTask(childId);
4411
- const isTaskOrMilestone = filters_default.byTaskTypeAndMilestone(childActivity);
4412
- const hasProgressLessThan100 = Number(childActivity.progress) < 100;
4413
- return isTaskOrMilestone && hasProgressLessThan100;
4414
- });
4415
- validChildren.forEach((childId) => allChildrenSet.add(childId));
4416
- }
4417
- return [...allChildrenSet];
4418
- }
4419
- function filterChildrenThatCanBeCalculated(params) {
4420
- const {
4421
- gantt,
4422
- childrenIds,
4423
- linkProperty,
4424
- getArrayOfLinkedActivities: getArrayOfLinkedActivities3,
4425
- calculations
4426
- } = params;
4427
- const calculableChildren = [];
4428
- for (const childId of childrenIds) {
4429
- const activity = gantt.getTask(childId);
4430
- const links = activity[linkProperty] || [];
4431
- const linkedActivities = getArrayOfLinkedActivities3({
4432
- gantt,
4433
- links,
4434
- linkDirection: linkProperty === "$source" ? "target" : "source"
4435
- });
4436
- const isLinkedWithCalculatedOrSibling = linkedActivities.every(
4437
- (linkedActivityId) => calculations.has(linkedActivityId)
4438
- );
4439
- if (isLinkedWithCalculatedOrSibling) {
4440
- calculableChildren.push(activity);
4441
- }
4442
- }
4443
- return calculableChildren;
4444
- }
4445
- function getArrayOfLinkedActivities(params) {
4446
- const { gantt, links, linkDirection } = params;
4447
- const linkedActivityIds = [];
4448
- for (const linkId of links) {
4449
- const link = gantt.getLink(linkId);
4450
- if (!link) {
4451
- continue;
4452
- }
4453
- const linkedActivityId = Number(link[linkDirection]);
4454
- linkedActivityIds.push(linkedActivityId);
4455
- }
4456
- return linkedActivityIds;
4457
- }
4458
-
4459
- // src/critical-path/legacy/base/identifiers/initialActivities.js
4460
- function identifyInitialActivities({ gantt, linkProperty, direction }) {
4461
- try {
4462
- const chainStartActivities = getChainStartActivities(gantt, linkProperty);
4463
- if (direction === "forward") {
4464
- return {
4465
- chainStartActivities,
4466
- activitiesStartChainButChildrenOfLinkedParents: null
4467
- };
4468
- }
4469
- if (direction === "backward") {
4470
- return processBackwardActivities(
4471
- chainStartActivities,
4472
- gantt,
4473
- linkProperty
4474
- );
4475
- }
4476
- } catch (e) {
4477
- console.log("Critical Path", e);
4478
- throw e;
4479
- }
4480
- }
4481
- function getChainStartActivities(gantt, linkProperty) {
4482
- return gantt.getTaskByTime().filter(filters_default.avoidSubproject).filter(filters_default.byTaskTypeAndMilestone).filter((activity) => !activity[linkProperty].length);
4483
- }
4484
- function processBackwardActivities(chainStartActivities, gantt, linkProperty) {
4485
- const withoutLinkedParents = [];
4486
- const activitiesStartChainButChildrenOfLinkedParents = /* @__PURE__ */ new Set();
4487
- chainStartActivities.forEach((activity) => {
4488
- const parentId = Number(activity.parent);
4489
- const parentActivity = gantt.getTask(parentId);
4490
- if (!parentActivity) return;
4491
- if (parentActivity[linkProperty].length > 0) {
4492
- activitiesStartChainButChildrenOfLinkedParents.add(activity.id);
4493
- } else if (parentActivity.constraint_type !== "fnlt") {
4494
- withoutLinkedParents.push(activity);
4495
- }
4496
- });
4497
- return {
4498
- chainStartActivities: withoutLinkedParents,
4499
- activitiesStartChainButChildrenOfLinkedParents
4500
- };
4501
- }
4502
-
4503
- // src/critical-path/legacy/base/identifiers/identifyParentsWithAndWithoutLinks.js
4504
- function identifyParentsWithAndWithoutLinks({
4505
- gantt,
4506
- direction,
4507
- linkProperty
4508
- }) {
4509
- try {
4510
- const allParentActivities = getAllParentActivities(gantt);
4511
- const parentsWithFullProgress = /* @__PURE__ */ new Set();
4512
- const pendingParentsWithNoLinks = /* @__PURE__ */ new Set();
4513
- const pendingParentsWithLinks = /* @__PURE__ */ new Set();
4514
- if (direction === "backward") {
4515
- const parentsWithFullProgressArray = getParentsWithFullProgress(allParentActivities);
4516
- parentsWithFullProgressArray.forEach((activity) => {
4517
- parentsWithFullProgress.add(activity.id);
4518
- });
4519
- }
4520
- const parentsWithNoLinks = getParentsWithNoLinks(
4521
- allParentActivities,
4522
- direction,
4523
- linkProperty
4524
- );
4525
- const difference = getDifference(allParentActivities, parentsWithNoLinks);
4526
- parentsWithNoLinks.forEach((activity) => {
4527
- pendingParentsWithNoLinks.add(activity.id);
4528
- });
4529
- difference.forEach((activity) => {
4530
- pendingParentsWithLinks.add(activity.id);
4531
- });
4532
- return {
4533
- parentsWithFullProgress,
4534
- pendingParentsWithNoLinks,
4535
- pendingParentsWithLinks
4536
- };
4537
- } catch (e) {
4538
- throw e;
4539
- }
4540
- }
4541
- function getAllParentActivities(gantt) {
4542
- return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter(filters_default.avoidSubproject);
4300
+ function getAllParentActivities(gantt) {
4301
+ return gantt.getTaskByTime().filter(filters_default.filterByParentType).filter(filters_default.avoidSubproject);
4543
4302
  }
4544
4303
  function getParentsWithNoLinks(activities, direction, linkProperty) {
4545
4304
  return activities.filter((activity) => {
@@ -9489,13 +9248,18 @@ var NON_SCHEDULING_INLINE_COLUMNS = /* @__PURE__ */ new Set([
9489
9248
  COLUMN.SUBCONTRACT_ID,
9490
9249
  COLUMN.TAGS
9491
9250
  ]);
9492
- var PROP_ONLY_KINDS = /* @__PURE__ */ new Set([
9251
+ var NON_SCHEDULING_KINDS = /* @__PURE__ */ new Set([
9493
9252
  "selection-toggle",
9494
9253
  "selection-replace",
9495
9254
  "visibility-set",
9496
9255
  "sir-sync",
9497
- "activity-lookahead-sync"
9256
+ "activity-lookahead-sync",
9257
+ "persistence-acknowledge",
9258
+ "baseline-apply",
9259
+ "ponderator-criterion-set",
9260
+ "status-criteria-set"
9498
9261
  ]);
9262
+ var NO_STRUCTURAL_EXEMPTIONS = /* @__PURE__ */ new Set();
9499
9263
  function editsOnlyNonSchedulingColumns(action) {
9500
9264
  if (action.kind === "inline-edit") {
9501
9265
  return NON_SCHEDULING_INLINE_COLUMNS.has(action.column);
@@ -9508,11 +9272,14 @@ function editsOnlyNonSchedulingColumns(action) {
9508
9272
  return false;
9509
9273
  }
9510
9274
  function isSchedulingDispatch(action, structuralStaleKinds) {
9511
- if (PROP_ONLY_KINDS.has(action.kind)) return false;
9275
+ if (NON_SCHEDULING_KINDS.has(action.kind)) return false;
9512
9276
  if (structuralStaleKinds.has(action.kind)) return false;
9513
9277
  if (editsOnlyNonSchedulingColumns(action)) return false;
9514
9278
  return true;
9515
9279
  }
9280
+ function dispatchChangesSchedulingState(action) {
9281
+ return isSchedulingDispatch(action, NO_STRUCTURAL_EXEMPTIONS);
9282
+ }
9516
9283
  function resolveRunCriticalPath(action) {
9517
9284
  return isSchedulingDispatch(
9518
9285
  action,
@@ -10231,26 +9998,21 @@ async function dispatchLinkBatch(operations, source, options, deps, deterministi
10231
9998
  };
10232
9999
  }
10233
10000
  function pickAutoscheduleTrigger(applied, beforeLinks, adapter) {
10234
- for (const a of applied) {
10235
- if (a.rejected !== null) continue;
10236
- if (a.op.kind === "create") {
10237
- return adapter.hasChildren(a.op.target) ? "roots" : String(a.op.target);
10238
- }
10239
- if (a.op.kind === "delete") {
10240
- const snap = beforeLinks.get(a.op.linkId);
10241
- if (snap) {
10242
- return adapter.hasChildren(snap.target) ? "roots" : String(snap.target);
10243
- }
10244
- }
10245
- if (a.op.kind === "update") {
10246
- const link = adapter.getLink(a.op.linkId);
10247
- if (link) {
10248
- return adapter.hasChildren(link.target) ? "roots" : String(link.target);
10249
- }
10250
- }
10001
+ for (const operation of applied) {
10002
+ if (operation.rejected !== null) continue;
10003
+ const target = autoscheduleTarget(operation.op, beforeLinks, adapter);
10004
+ if (target !== null)
10005
+ return adapter.hasChildren(target) ? "roots" : String(target);
10251
10006
  }
10252
10007
  return null;
10253
10008
  }
10009
+ function autoscheduleTarget(operation, beforeLinks, adapter) {
10010
+ if (operation.kind === "create") return operation.target;
10011
+ if (operation.kind === "delete") {
10012
+ return beforeLinks.get(operation.linkId)?.target ?? null;
10013
+ }
10014
+ return adapter.getLink(operation.linkId)?.target ?? null;
10015
+ }
10254
10016
  function toLinkOperation(action, hoursPerDay) {
10255
10017
  if (action.kind === "link-create") {
10256
10018
  return {
@@ -10321,79 +10083,201 @@ var DISPATCH_TRACK_EVENT = {
10321
10083
  ACTIVITY_OUTDENT: "schedule_activity_outdent"
10322
10084
  };
10323
10085
 
10324
- // src/propagations/upward/recompute-hh-cascade.ts
10325
- function recomputeHhCascadeForParent(startParentId, adapter) {
10326
- if (!startParentId || startParentId === "0") return;
10327
- let currentParentId = String(startParentId);
10328
- while (currentParentId !== null) {
10329
- const childIds = adapter.getChildren(currentParentId);
10330
- let hhSum = 0;
10331
- let rwSum = 0;
10086
+ // src/internal/hierarchy/visual-order.ts
10087
+ var NOT_SET_SORT_VALUE = Number.MAX_SAFE_INTEGER;
10088
+ function getChildrenInVisualOrder(parentId, adapter) {
10089
+ const children = collectChildrenSnapshots(parentId, adapter);
10090
+ children.sort(compareActivitiesInVisualOrder);
10091
+ return children.map((a) => String(a.id));
10092
+ }
10093
+ function iterateInVisualOrder(adapter) {
10094
+ const result = [];
10095
+ const visit = (activity) => {
10096
+ result.push(activity);
10097
+ const childIds = getChildrenInVisualOrder(String(activity.id), adapter);
10332
10098
  for (const childId of childIds) {
10333
10099
  const child = adapter.getActivity(childId);
10334
- if (!child) continue;
10335
- const hh = readNumber(child, ACTIVITY_PROPERTY.WORK_HOURS);
10336
- const rw = readChildRealWork(childId, child, hh, adapter);
10337
- hhSum += hh;
10338
- rwSum += rw;
10100
+ if (child) visit(child);
10339
10101
  }
10340
- adapter.setActivityField(
10341
- currentParentId,
10342
- ACTIVITY_PROPERTY.WORK_HOURS,
10343
- hhSum
10344
- );
10345
- adapter.setActivityField(
10346
- currentParentId,
10347
- ACTIVITY_PROPERTY.REAL_WORK_HOURS,
10348
- rwSum
10349
- );
10350
- const parentSnap = adapter.getActivity(currentParentId);
10351
- if (!parentSnap) break;
10352
- const grandParent = parentSnap.parentId;
10353
- if (!grandParent || isRootParent(grandParent)) break;
10354
- currentParentId = grandParent;
10102
+ };
10103
+ const rootIds = getChildrenInVisualOrder(ROOT_PARENT_ID, adapter);
10104
+ for (const rootId of rootIds) {
10105
+ const root = adapter.getActivity(rootId);
10106
+ if (root) visit(root);
10355
10107
  }
10108
+ return result;
10356
10109
  }
10357
- function recomputeHhCascadeForActivity(activityId, adapter) {
10358
- const activity = adapter.getActivity(activityId);
10359
- if (!activity) return;
10360
- const parentId = activity.parentId;
10361
- if (!parentId || isRootParent(parentId)) return;
10362
- recomputeHhCascadeForParent(parentId, adapter);
10363
- }
10364
- function readNumber(activity, key) {
10365
- const v = activity[key];
10366
- if (typeof v === "number" && Number.isFinite(v)) return v;
10367
- return 0;
10110
+ function findPreviousNonSelectedSibling(taskId, selected, adapter) {
10111
+ const activity = adapter.getActivity(taskId);
10112
+ if (!activity) return null;
10113
+ const parentKey = parentKeyOf(activity);
10114
+ const siblings = getChildrenInVisualOrder(parentKey, adapter);
10115
+ const idx = siblings.findIndex((id) => String(id) === String(taskId));
10116
+ if (idx <= 0) return null;
10117
+ for (let i = idx - 1; i >= 0; i--) {
10118
+ const candidateId = siblings[i];
10119
+ if (candidateId === void 0) continue;
10120
+ if (!setHas(selected, candidateId)) return candidateId;
10121
+ }
10122
+ return null;
10368
10123
  }
10369
- function readChildRealWork(childId, child, workHours, adapter) {
10370
- return adapter.hasChildren(childId) ? readNumber(child, ACTIVITY_PROPERTY.REAL_WORK_HOURS) : computeLeafRealWork(
10371
- workHours,
10372
- readNumber(child, ACTIVITY_PROPERTY.PROGRESS)
10373
- );
10124
+ function visualIndexInParent(taskId, adapter) {
10125
+ const activity = adapter.getActivity(taskId);
10126
+ if (!activity) return -1;
10127
+ const parentKey = parentKeyOf(activity);
10128
+ const siblings = getChildrenInVisualOrder(parentKey, adapter);
10129
+ return siblings.findIndex((id) => String(id) === String(taskId));
10374
10130
  }
10375
-
10376
- // src/propagations/upward/recompute-used-cost-cascade.ts
10377
- function recomputeUsedCostCascadeForParent(startParentId, adapter) {
10378
- if (!startParentId || startParentId === "0") return;
10379
- let currentParentId = String(startParentId);
10380
- while (currentParentId !== null) {
10381
- const childIds = adapter.getChildren(currentParentId);
10382
- let sum = 0;
10383
- for (const childId of childIds) {
10384
- const child = adapter.getActivity(childId);
10385
- if (!child) continue;
10386
- sum += readNumber2(child, ACTIVITY_PROPERTY.USED_COST);
10387
- }
10388
- adapter.setActivityField(currentParentId, ACTIVITY_PROPERTY.USED_COST, sum);
10389
- const parentSnap = adapter.getActivity(currentParentId);
10390
- if (!parentSnap) break;
10391
- const grandParent = parentSnap.parentId;
10392
- if (!grandParent || isRootParent(grandParent)) break;
10393
- currentParentId = grandParent;
10131
+ function collectChildrenSnapshots(parentId, adapter) {
10132
+ const key = String(parentId);
10133
+ if (key === "0") {
10134
+ return adapter.getAllActivities().filter((a) => a.parentId === null);
10394
10135
  }
10136
+ const childIds = adapter.getChildren(parentId);
10137
+ const out = [];
10138
+ for (const id of childIds) {
10139
+ const snap = adapter.getActivity(id);
10140
+ if (snap) out.push(snap);
10141
+ }
10142
+ return out;
10395
10143
  }
10396
- function recomputeUsedCostCascadeForActivity(activityId, adapter) {
10144
+ function compareActivitiesInVisualOrder(a, b) {
10145
+ const ac = correlativeIdOf(a);
10146
+ const bc = correlativeIdOf(b);
10147
+ if (ac !== bc) return ac - bc;
10148
+ return String(a.id).localeCompare(String(b.id));
10149
+ }
10150
+ function correlativeIdOf(activity) {
10151
+ const raw = activity.correlativeId;
10152
+ const n = typeof raw === "number" ? raw : Number(raw);
10153
+ return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
10154
+ }
10155
+ function parentKeyOf(activity) {
10156
+ const parentId = activity.parentId;
10157
+ if (parentId === null) return "0";
10158
+ return parentId;
10159
+ }
10160
+ function setHas(set, id) {
10161
+ if (set.has(id)) return true;
10162
+ return set.has(String(id));
10163
+ }
10164
+
10165
+ // src/internal/hierarchy/recompute-correlative-ids.ts
10166
+ function recomputeCorrelativeIds(adapter) {
10167
+ adapter.invalidateVisualOrderIds?.();
10168
+ const roots = [];
10169
+ adapter.forEachActivity((activity) => {
10170
+ if (isRootParent(activity.parentId)) roots.push(activity);
10171
+ });
10172
+ roots.sort(byCorrelativeId);
10173
+ const stack = [];
10174
+ pushInReverseOrder(stack, roots);
10175
+ const shifts = [];
10176
+ let counter = 0;
10177
+ while (stack.length > 0) {
10178
+ const activity = stack.pop();
10179
+ if (activity.correlativeId !== counter) {
10180
+ const before = typeof activity.correlativeId === "number" ? activity.correlativeId : void 0;
10181
+ shifts.push({ activityId: String(activity.id), before });
10182
+ if (before !== void 0)
10183
+ adapter.noteCorrelativeBefore?.(String(activity.id), before);
10184
+ setCorrelativeId(activity, counter);
10185
+ }
10186
+ counter += 1;
10187
+ const children = collectChildrenSnapshots(String(activity.id), adapter);
10188
+ children.sort(byCorrelativeId);
10189
+ pushInReverseOrder(stack, children);
10190
+ }
10191
+ return shifts;
10192
+ }
10193
+ function pushInReverseOrder(stack, activities) {
10194
+ for (let i = activities.length - 1; i >= 0; i -= 1) {
10195
+ stack.push(activities[i]);
10196
+ }
10197
+ }
10198
+ function getCorrelativeId(activity) {
10199
+ const raw = activity.correlativeId;
10200
+ const n = typeof raw === "number" ? raw : Number(raw);
10201
+ return Number.isFinite(n) ? n : NOT_SET_SORT_VALUE;
10202
+ }
10203
+ var byCorrelativeId = (a, b) => getCorrelativeId(a) - getCorrelativeId(b);
10204
+ function setCorrelativeId(activity, value) {
10205
+ activity.correlativeId = value;
10206
+ }
10207
+
10208
+ // src/propagations/upward/recompute-hh-cascade.ts
10209
+ function recomputeHhCascadeForParent(startParentId, adapter) {
10210
+ if (!startParentId || startParentId === "0") return;
10211
+ let currentParentId = String(startParentId);
10212
+ while (currentParentId !== null) {
10213
+ const childIds = adapter.getChildren(currentParentId);
10214
+ let hhSum = 0;
10215
+ let rwSum = 0;
10216
+ for (const childId of childIds) {
10217
+ const child = adapter.getActivity(childId);
10218
+ if (!child) continue;
10219
+ const hh = readNumber(child, ACTIVITY_PROPERTY.WORK_HOURS);
10220
+ const rw = readChildRealWork(childId, child, hh, adapter);
10221
+ hhSum += hh;
10222
+ rwSum += rw;
10223
+ }
10224
+ adapter.setActivityField(
10225
+ currentParentId,
10226
+ ACTIVITY_PROPERTY.WORK_HOURS,
10227
+ hhSum
10228
+ );
10229
+ adapter.setActivityField(
10230
+ currentParentId,
10231
+ ACTIVITY_PROPERTY.REAL_WORK_HOURS,
10232
+ rwSum
10233
+ );
10234
+ const parentSnap = adapter.getActivity(currentParentId);
10235
+ if (!parentSnap) break;
10236
+ const grandParent = parentSnap.parentId;
10237
+ if (!grandParent || isRootParent(grandParent)) break;
10238
+ currentParentId = grandParent;
10239
+ }
10240
+ }
10241
+ function recomputeHhCascadeForActivity(activityId, adapter) {
10242
+ const activity = adapter.getActivity(activityId);
10243
+ if (!activity) return;
10244
+ const parentId = activity.parentId;
10245
+ if (!parentId || isRootParent(parentId)) return;
10246
+ recomputeHhCascadeForParent(parentId, adapter);
10247
+ }
10248
+ function readNumber(activity, key) {
10249
+ const v = activity[key];
10250
+ if (typeof v === "number" && Number.isFinite(v)) return v;
10251
+ return 0;
10252
+ }
10253
+ function readChildRealWork(childId, child, workHours, adapter) {
10254
+ return adapter.hasChildren(childId) ? readNumber(child, ACTIVITY_PROPERTY.REAL_WORK_HOURS) : computeLeafRealWork(
10255
+ workHours,
10256
+ readNumber(child, ACTIVITY_PROPERTY.PROGRESS)
10257
+ );
10258
+ }
10259
+
10260
+ // src/propagations/upward/recompute-used-cost-cascade.ts
10261
+ function recomputeUsedCostCascadeForParent(startParentId, adapter) {
10262
+ if (!startParentId || startParentId === "0") return;
10263
+ let currentParentId = String(startParentId);
10264
+ while (currentParentId !== null) {
10265
+ const childIds = adapter.getChildren(currentParentId);
10266
+ let sum = 0;
10267
+ for (const childId of childIds) {
10268
+ const child = adapter.getActivity(childId);
10269
+ if (!child) continue;
10270
+ sum += readNumber2(child, ACTIVITY_PROPERTY.USED_COST);
10271
+ }
10272
+ adapter.setActivityField(currentParentId, ACTIVITY_PROPERTY.USED_COST, sum);
10273
+ const parentSnap = adapter.getActivity(currentParentId);
10274
+ if (!parentSnap) break;
10275
+ const grandParent = parentSnap.parentId;
10276
+ if (!grandParent || isRootParent(grandParent)) break;
10277
+ currentParentId = grandParent;
10278
+ }
10279
+ }
10280
+ function recomputeUsedCostCascadeForActivity(activityId, adapter) {
10397
10281
  const activity = adapter.getActivity(activityId);
10398
10282
  if (!activity) return;
10399
10283
  const parentId = activity.parentId;
@@ -10871,27 +10755,6 @@ function buildCreateChangeSet(adapter, action, coreResult, scheduledIds, hoursPe
10871
10755
  scheduledBeforeImages: existingScheduledBeforeImages,
10872
10756
  trackingEvents: [trackingEvent]});
10873
10757
  }
10874
- function createActivitySync(action, deps) {
10875
- const result = createActivityCore(action, deps);
10876
- if (!result.ok) {
10877
- return { ok: false, reason: result.reason };
10878
- }
10879
- recomputeParentBoundsSync(deps.adapter, /* @__PURE__ */ new Set([result.newId]));
10880
- const snapshot = deps.adapter.getActivity(result.newId);
10881
- if (!snapshot) {
10882
- throw new Error(
10883
- `[ScheduleCore] createActivity: new activity ${result.newId} missing after commit`
10884
- );
10885
- }
10886
- const changes = buildCreateChangeSet(
10887
- deps.adapter,
10888
- action,
10889
- result,
10890
- [],
10891
- deps.sector.hoursPerDay
10892
- );
10893
- return { ok: true, activity: snapshot, changes };
10894
- }
10895
10758
  async function dispatchActivityCreate(action, options, deps) {
10896
10759
  const { adapter, scheduler, sector } = deps;
10897
10760
  const core = createActivityCore(action, deps);
@@ -12547,17 +12410,524 @@ function mergeBeforeSnapshots2(beforeSnap, ids, deps) {
12547
12410
  for (const candidateId of ids) {
12548
12411
  if (!beforeSnap.has(candidateId)) missing.add(candidateId);
12549
12412
  }
12550
- if (missing.size === 0) return;
12551
- for (const [snappedId, snapshot] of snapshotActivities(
12413
+ if (missing.size === 0) return;
12414
+ for (const [snappedId, snapshot] of snapshotActivities(
12415
+ deps.adapter,
12416
+ missing
12417
+ )) {
12418
+ beforeSnap.set(snappedId, snapshot);
12419
+ }
12420
+ }
12421
+
12422
+ // src/dispatch/handlers/persistence-acknowledge.ts
12423
+ function assertValidAssignment(assignment, entityName, readCurrent, ownerByBackendId, seenIds, seenBackendIds) {
12424
+ const id = String(assignment.id);
12425
+ if (id.length === 0 || seenIds.has(id)) {
12426
+ throw new Error(
12427
+ `persistence-acknowledge: duplicate or empty ${entityName} id "${id}"`
12428
+ );
12429
+ }
12430
+ if (!Number.isSafeInteger(assignment.proplannerId) || assignment.proplannerId <= 0) {
12431
+ throw new Error(
12432
+ `persistence-acknowledge: invalid ${entityName} proplannerId ${String(assignment.proplannerId)}`
12433
+ );
12434
+ }
12435
+ if (seenBackendIds.has(assignment.proplannerId)) {
12436
+ throw new Error(
12437
+ `persistence-acknowledge: duplicate ${entityName} proplannerId ${String(assignment.proplannerId)}`
12438
+ );
12439
+ }
12440
+ const state = readCurrent(id);
12441
+ if (!state.exists) {
12442
+ throw new Error(
12443
+ `persistence-acknowledge: unknown ${entityName} id "${id}"`
12444
+ );
12445
+ }
12446
+ if (state.current !== null && state.current !== assignment.proplannerId) {
12447
+ throw new Error(
12448
+ `persistence-acknowledge: ${entityName} "${id}" already has proplannerId ${String(state.current)}`
12449
+ );
12450
+ }
12451
+ const existingOwner = ownerByBackendId.get(assignment.proplannerId);
12452
+ if (existingOwner !== void 0 && existingOwner !== id) {
12453
+ throw new Error(
12454
+ `persistence-acknowledge: ${entityName} proplannerId ${String(assignment.proplannerId)} already belongs to "${existingOwner}"`
12455
+ );
12456
+ }
12457
+ seenIds.add(id);
12458
+ seenBackendIds.add(assignment.proplannerId);
12459
+ }
12460
+ function assertValidAssignments(assignments, entityName, readCurrent, ownerByBackendId) {
12461
+ const seenIds = /* @__PURE__ */ new Set();
12462
+ const seenBackendIds = /* @__PURE__ */ new Set();
12463
+ for (const assignment of assignments) {
12464
+ assertValidAssignment(
12465
+ assignment,
12466
+ entityName,
12467
+ readCurrent,
12468
+ ownerByBackendId,
12469
+ seenIds,
12470
+ seenBackendIds
12471
+ );
12472
+ }
12473
+ }
12474
+ function dispatchPersistenceAcknowledge(action, deps) {
12475
+ const activities = action.activities ?? [];
12476
+ const links = action.links ?? [];
12477
+ const activityOwnerByBackendId = /* @__PURE__ */ new Map();
12478
+ for (const activity of deps.adapter.getAllActivities()) {
12479
+ if (activity.proplannerId != null) {
12480
+ activityOwnerByBackendId.set(activity.proplannerId, String(activity.id));
12481
+ }
12482
+ }
12483
+ const linkOwnerByBackendId = /* @__PURE__ */ new Map();
12484
+ for (const link of deps.adapter.getAllLinks()) {
12485
+ if (link.proplannerId != null) {
12486
+ linkOwnerByBackendId.set(link.proplannerId, String(link.id));
12487
+ }
12488
+ }
12489
+ assertValidAssignments(
12490
+ activities,
12491
+ "activity",
12492
+ (id) => {
12493
+ const activity = deps.adapter.getActivity(id);
12494
+ return {
12495
+ exists: activity !== null,
12496
+ current: activity?.proplannerId ?? null
12497
+ };
12498
+ },
12499
+ activityOwnerByBackendId
12500
+ );
12501
+ assertValidAssignments(
12502
+ links,
12503
+ "link",
12504
+ (id) => {
12505
+ const link = deps.adapter.getLink(id);
12506
+ return { exists: link !== null, current: link?.proplannerId ?? null };
12507
+ },
12508
+ linkOwnerByBackendId
12509
+ );
12510
+ const activityChanges = [];
12511
+ const linkChanges = [];
12512
+ deps.adapter.batchUpdate(() => {
12513
+ for (const assignment of activities) {
12514
+ const before = deps.adapter.getActivity(assignment.id);
12515
+ if (!before || before.proplannerId === assignment.proplannerId) continue;
12516
+ deps.adapter.setActivityField(
12517
+ assignment.id,
12518
+ "proplannerId",
12519
+ assignment.proplannerId
12520
+ );
12521
+ activityChanges.push({
12522
+ id: assignment.id,
12523
+ kind: "updated",
12524
+ fields: {
12525
+ proplannerId: {
12526
+ before: before.proplannerId,
12527
+ after: assignment.proplannerId
12528
+ }
12529
+ },
12530
+ after: { ...before, proplannerId: assignment.proplannerId }
12531
+ });
12532
+ }
12533
+ for (const assignment of links) {
12534
+ const before = deps.adapter.getLink(assignment.id);
12535
+ if (!before || before.proplannerId === assignment.proplannerId) continue;
12536
+ deps.adapter.setLinkProplannerId(assignment.id, assignment.proplannerId);
12537
+ linkChanges.push({
12538
+ id: assignment.id,
12539
+ kind: "updated",
12540
+ fields: {
12541
+ proplannerId: {
12542
+ before: before.proplannerId,
12543
+ after: assignment.proplannerId
12544
+ }
12545
+ },
12546
+ after: { ...before, proplannerId: assignment.proplannerId }
12547
+ });
12548
+ }
12549
+ });
12550
+ return {
12551
+ ok: true,
12552
+ changes: {
12553
+ source: action,
12554
+ activities: activityChanges,
12555
+ links: linkChanges,
12556
+ calendars: [],
12557
+ trackingEvents: []
12558
+ }
12559
+ };
12560
+ }
12561
+
12562
+ // src/baselines/normalize-baseline-point.ts
12563
+ function parseBaselineDate(value) {
12564
+ return typeof value === "string" && value.length > 0 ? parseBackendDate(value) : value instanceof Date ? value : null;
12565
+ }
12566
+ function parseFiniteNonNegative(value) {
12567
+ const numeric = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : Number.NaN;
12568
+ if (!Number.isFinite(numeric) || numeric < 0) return null;
12569
+ return numeric;
12570
+ }
12571
+ function normalizeBaselinePoint(point, reporter) {
12572
+ const durationDays = parseFiniteNonNegative(point.duration);
12573
+ const cost = parseFiniteNonNegative(point.cost);
12574
+ const workHours = parseFiniteNonNegative(point.hh_work);
12575
+ if (durationDays === null || cost === null || workHours === null) {
12576
+ reporter.warn(
12577
+ `[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)}`
12578
+ );
12579
+ return null;
12580
+ }
12581
+ return {
12582
+ startDate: parseBaselineDate(point.start_date),
12583
+ endDate: parseBaselineDate(point.end_date),
12584
+ durationDays,
12585
+ cost,
12586
+ workHours,
12587
+ versionId: typeof point.sectorbaselineversionId === "number" ? point.sectorbaselineversionId : null,
12588
+ isActiveVersion: Boolean(point.sectorbaselineversion?.active),
12589
+ isVisibleVersion: Boolean(point.sectorbaselineversion?.visible),
12590
+ baseCalendarId: point.baseCalendarId != null ? String(point.baseCalendarId) : null,
12591
+ hoursPerDay: typeof point.hoursPerDay === "number" ? point.hoursPerDay : null,
12592
+ hoursPerWeek: typeof point.hoursPerWeek === "number" ? point.hoursPerWeek : null
12593
+ };
12594
+ }
12595
+
12596
+ // src/baselines/apply-baseline-points.ts
12597
+ function applyBaselinePoints(adapter, points, reporter) {
12598
+ const idByProplanner = /* @__PURE__ */ new Map();
12599
+ adapter.forEachActivity((a, id) => {
12600
+ const pid = a.proplannerId;
12601
+ if (typeof pid === "number") idByProplanner.set(pid, id);
12602
+ });
12603
+ const grouped = /* @__PURE__ */ new Map();
12604
+ for (const p of points) {
12605
+ const activityId = p.activityId;
12606
+ if (typeof activityId !== "number") continue;
12607
+ const coreId = idByProplanner.get(activityId);
12608
+ if (coreId === void 0) continue;
12609
+ const arr = grouped.get(coreId);
12610
+ if (arr) arr.push(p);
12611
+ else grouped.set(coreId, [p]);
12612
+ }
12613
+ const changed = [];
12614
+ for (const [coreId, group] of grouped) {
12615
+ adapter.setActivityField(
12616
+ coreId,
12617
+ "baselinePoints",
12618
+ group.map((point) => normalizeBaselinePoint(point, reporter)).filter((point) => point !== null)
12619
+ );
12620
+ changed.push(coreId);
12621
+ }
12622
+ adapter.forEachActivity((a, id) => {
12623
+ if (grouped.has(id)) return;
12624
+ const existing = a.baselinePoints;
12625
+ if (Array.isArray(existing) && existing.length > 0) {
12626
+ adapter.setActivityField(id, "baselinePoints", []);
12627
+ changed.push(id);
12628
+ }
12629
+ });
12630
+ return changed;
12631
+ }
12632
+
12633
+ // src/baselines/baseline-snapshot.ts
12634
+ function buildBaselineSnapshot(activity) {
12635
+ const active = getActiveBaseline(activity);
12636
+ if (!active) return null;
12637
+ return {
12638
+ startDate: active.startDate,
12639
+ endDate: active.endDate,
12640
+ durationDays: active.durationDays,
12641
+ cost: active.cost,
12642
+ workHours: active.workHours
12643
+ };
12644
+ }
12645
+ function emitBaselineSnapshotColumns(state) {
12646
+ const changed = [];
12647
+ state.forEachActivity((activity, id) => {
12648
+ const snapshot = buildBaselineSnapshot(activity);
12649
+ if (!snapshot) {
12650
+ if (activity.baselineSnapshot !== null) {
12651
+ state.setActivityField(id, "baselineSnapshot", null);
12652
+ changed.push(id);
12653
+ }
12654
+ return;
12655
+ }
12656
+ state.setActivityField(id, "baselineSnapshot", snapshot);
12657
+ changed.push(id);
12658
+ });
12659
+ return changed;
12660
+ }
12661
+
12662
+ // src/baselines/apply-baseline-overlay.ts
12663
+ function applyBaselineOverlay(state, points, now, reporter, defaultBaseCalendarId = null) {
12664
+ const changed = /* @__PURE__ */ new Set();
12665
+ for (const id of applyBaselinePoints(
12666
+ state,
12667
+ points,
12668
+ reporter
12669
+ )) {
12670
+ changed.add(id);
12671
+ }
12672
+ if (now) {
12673
+ for (const id of runExpectedProgressBase(state, now, defaultBaseCalendarId))
12674
+ changed.add(id);
12675
+ }
12676
+ for (const id of emitBaselineSnapshotColumns(state)) changed.add(id);
12677
+ for (const id of emitRealCost(state)) changed.add(id);
12678
+ return [...changed];
12679
+ }
12680
+
12681
+ // src/propagations/downward/recompute-ponderator-for-parent.ts
12682
+ function recomputePonderatorsForParent(parentId, criterion, adapter) {
12683
+ if (!parentId || parentId === "0") return;
12684
+ const childIds = adapter.getChildren(parentId);
12685
+ if (childIds.length === 0) return;
12686
+ const pesoById = /* @__PURE__ */ new Map();
12687
+ let denominator = 0;
12688
+ for (const childId of childIds) {
12689
+ const peso = criterionValue(String(childId), criterion, adapter);
12690
+ pesoById.set(String(childId), peso);
12691
+ denominator += peso;
12692
+ }
12693
+ const relationValue = denominator ? 100 / denominator : 0;
12694
+ for (const childId of childIds) {
12695
+ const child = adapter.getActivity(childId);
12696
+ if (!child) continue;
12697
+ const points = child.baselinePoints;
12698
+ const active = getActiveBaseline(child);
12699
+ if (active) {
12700
+ const peso = pesoById.get(String(childId)) ?? 0;
12701
+ adapter.setActivityField(
12702
+ childId,
12703
+ COLUMN.PONDERATOR,
12704
+ relationValue * peso
12705
+ );
12706
+ } else if (!Array.isArray(points) || points.length === 0) {
12707
+ adapter.setActivityField(childId, COLUMN.PONDERATOR, 0);
12708
+ }
12709
+ }
12710
+ }
12711
+ function criterionValue(childId, criterion, adapter) {
12712
+ const child = adapter.getActivity(childId);
12713
+ if (!child) return 0;
12714
+ const active = getActiveBaseline(child);
12715
+ if (!active) return 0;
12716
+ if (criterion === "COST") return toNumber(active.cost);
12717
+ if (criterion === "HH") return toNumber(active.workHours);
12718
+ const type = child.type;
12719
+ if (type === "project")
12720
+ return sumRecursiveBaselineDurationDays(childId, adapter);
12721
+ if (type === "milestone") return 0;
12722
+ return toNumber(active.durationDays);
12723
+ }
12724
+ function sumRecursiveBaselineDurationDays(activityId, adapter) {
12725
+ let sum = 0;
12726
+ for (const childId of adapter.getChildren(activityId)) {
12727
+ const child = adapter.getActivity(childId);
12728
+ if (!child) continue;
12729
+ const active = getActiveBaseline(child);
12730
+ if (!active) continue;
12731
+ const type = child.type;
12732
+ if (type === "project") {
12733
+ sum += sumRecursiveBaselineDurationDays(String(childId), adapter);
12734
+ } else if (type !== "milestone") {
12735
+ sum += toNumber(active.durationDays);
12736
+ }
12737
+ }
12738
+ return sum;
12739
+ }
12740
+ function toNumber(v) {
12741
+ const n = typeof v === "string" ? parseFloat(v) : v;
12742
+ return typeof n === "number" && Number.isFinite(n) ? n : 0;
12743
+ }
12744
+
12745
+ // src/propagations/downward/recompute-all-ponderators.ts
12746
+ function recomputeAllPonderators(criterion, adapter) {
12747
+ adapter.forEachActivity((_a, id) => {
12748
+ adapter.setActivityField(id, COLUMN.PONDERATOR, 0);
12749
+ });
12750
+ adapter.forEachActivity((_a, id) => {
12751
+ if (adapter.getChildren(id).length > 0) {
12752
+ recomputePonderatorsForParent(String(id), criterion, adapter);
12753
+ }
12754
+ });
12755
+ }
12756
+
12757
+ // src/propagations/upward/progress-rollup.ts
12758
+ function recomputeAllProgressRollup(adapter) {
12759
+ for (const parentId of parentsDeepestFirst(adapter)) {
12760
+ rollupParent(parentId, adapter);
12761
+ }
12762
+ }
12763
+ function parentsDeepestFirst(adapter) {
12764
+ const parents = /* @__PURE__ */ new Set();
12765
+ adapter.forEachActivity((_activity, id) => {
12766
+ if (adapter.getChildren(id).length > 0) parents.add(id);
12767
+ });
12768
+ const depthById = /* @__PURE__ */ new Map();
12769
+ for (const id of parents) depthById.set(id, depthOf2(id, adapter));
12770
+ return [...parents].sort(
12771
+ (a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
12772
+ );
12773
+ }
12774
+ function depthOf2(id, adapter) {
12775
+ let depth = 0;
12776
+ let current = id;
12777
+ while (current && current !== "0") {
12778
+ if (!adapter.getActivity(current)) break;
12779
+ depth += 1;
12780
+ current = adapter.getParentId(current);
12781
+ }
12782
+ return depth;
12783
+ }
12784
+ function rollupParent(parentId, adapter) {
12785
+ const childIds = adapter.getChildren(parentId);
12786
+ if (childIds.length === 0) return;
12787
+ const children = [];
12788
+ for (const childId of childIds) {
12789
+ const child = adapter.getActivity(childId);
12790
+ if (!child) continue;
12791
+ children.push({
12792
+ progress: Number(child.progress ?? 0),
12793
+ ponderator: Number(child.ponderator ?? 0)
12794
+ });
12795
+ }
12796
+ const rollup = computeWeightedProgressRollup(children);
12797
+ if (rollup !== null) {
12798
+ adapter.setActivityField(
12799
+ parentId,
12800
+ COLUMN.PROGRESS,
12801
+ roundProgressPerLevel(rollup)
12802
+ );
12803
+ }
12804
+ }
12805
+
12806
+ // src/dispatch/shared/baseline-weighted-fields.ts
12807
+ function recomputeBaselineWeightedFields(deps, criterion) {
12808
+ recomputeAllPonderators(criterion, deps.adapter);
12809
+ recomputeAllProgressRollup(deps.adapter);
12810
+ if (deps.now) {
12811
+ runExpectedProgressBase(
12812
+ deps.adapter,
12813
+ deps.now,
12814
+ deps.defaultBaseCalendarId ?? null
12815
+ );
12816
+ applyExpectedProgressLive(deps.adapter, deps.now);
12817
+ }
12818
+ emitRealCost(deps.adapter);
12819
+ if (deps.now) applyStatusPass(deps.adapter, deps.sector.statusCriteria);
12820
+ }
12821
+
12822
+ // src/dispatch/handlers/baseline-apply.ts
12823
+ function activeBaselineSignature(deps) {
12824
+ return JSON.stringify(
12825
+ deps.adapter.getAllIds().map((id) => {
12826
+ const point = deps.adapter.getActivity(id)?.baselinePoints.find((candidate) => candidate.isActiveVersion);
12827
+ return point ? [
12828
+ String(id),
12829
+ point.versionId,
12830
+ point.startDate?.getTime() ?? null,
12831
+ point.endDate?.getTime() ?? null,
12832
+ point.durationDays,
12833
+ point.cost,
12834
+ point.workHours,
12835
+ point.baseCalendarId,
12836
+ point.hoursPerDay,
12837
+ point.hoursPerWeek
12838
+ ] : [String(id), null];
12839
+ })
12840
+ );
12841
+ }
12842
+ function dispatchBaselineApply(action, deps) {
12843
+ const beforeSnap = snapshotActivities(
12552
12844
  deps.adapter,
12553
- missing
12554
- )) {
12555
- beforeSnap.set(snappedId, snapshot);
12845
+ new Set(deps.adapter.getAllIds())
12846
+ );
12847
+ const activeBaselineBefore = activeBaselineSignature(deps);
12848
+ const changedIds = applyBaselineOverlay(
12849
+ deps.adapter,
12850
+ action.points,
12851
+ deps.now,
12852
+ deps.reporter,
12853
+ deps.defaultBaseCalendarId ?? null
12854
+ );
12855
+ if (activeBaselineSignature(deps) !== activeBaselineBefore) {
12856
+ recomputeBaselineWeightedFields(
12857
+ deps,
12858
+ deps.sector.activityCreter ?? "DURATION"
12859
+ );
12556
12860
  }
12861
+ return {
12862
+ ok: true,
12863
+ changes: assembleChangeSet(deps.adapter, {
12864
+ source: action,
12865
+ beforeSnap,
12866
+ touchedIds: changedIds,
12867
+ scheduledIds: [],
12868
+ hoursPerDay: deps.sector.hoursPerDay
12869
+ })
12870
+ };
12871
+ }
12872
+
12873
+ // src/dispatch/handlers/ponderator-criterion-set.ts
12874
+ function assertValidCriterion(value) {
12875
+ if (value === "DURATION" || value === "COST" || value === "HH") return;
12876
+ throw new Error(
12877
+ `ponderator-criterion-set: invalid criterion "${String(value)}"`
12878
+ );
12879
+ }
12880
+ function dispatchPonderatorCriterionSet(action, deps) {
12881
+ assertValidCriterion(action.criterion);
12882
+ const allIds = new Set(deps.adapter.getAllIds());
12883
+ const beforeSnap = snapshotActivities(deps.adapter, allIds);
12884
+ recomputeBaselineWeightedFields(deps, action.criterion);
12885
+ deps.sector.activityCreter = action.criterion;
12886
+ return {
12887
+ ok: true,
12888
+ changes: assembleChangeSet(deps.adapter, {
12889
+ source: action,
12890
+ beforeSnap,
12891
+ touchedIds: allIds,
12892
+ scheduledIds: [],
12893
+ hoursPerDay: deps.sector.hoursPerDay
12894
+ })
12895
+ };
12896
+ }
12897
+
12898
+ // src/dispatch/handlers/status-criteria-set.ts
12899
+ function dispatchStatusCriteriaSet(action, deps) {
12900
+ const resolved = resolveStatusCriteria(action.criteria);
12901
+ const allIds = new Set(deps.adapter.getAllIds());
12902
+ const beforeSnap = snapshotActivities(deps.adapter, allIds);
12903
+ const changedIds = applyStatusPass(deps.adapter, resolved);
12904
+ deps.sector.statusCriteria = resolved;
12905
+ return {
12906
+ ok: true,
12907
+ changes: assembleChangeSet(deps.adapter, {
12908
+ source: action,
12909
+ beforeSnap,
12910
+ touchedIds: changedIds,
12911
+ scheduledIds: [],
12912
+ hoursPerDay: deps.sector.hoursPerDay
12913
+ })
12914
+ };
12557
12915
  }
12558
12916
 
12559
12917
  // src/dispatch/dispatch.ts
12560
12918
  async function dispatch(action, options, deps) {
12919
+ if (action.kind === "persistence-acknowledge") {
12920
+ return dispatchPersistenceAcknowledge(action, deps);
12921
+ }
12922
+ if (action.kind === "baseline-apply") {
12923
+ return dispatchBaselineApply(action, deps);
12924
+ }
12925
+ if (action.kind === "ponderator-criterion-set") {
12926
+ return dispatchPonderatorCriterionSet(action, deps);
12927
+ }
12928
+ if (action.kind === "status-criteria-set") {
12929
+ return dispatchStatusCriteriaSet(action, deps);
12930
+ }
12561
12931
  if (action.kind === "link-create" || action.kind === "link-update" || action.kind === "link-delete") {
12562
12932
  return dispatchLink(action, options, deps);
12563
12933
  }
@@ -15721,6 +16091,18 @@ var HierarchyIndex = class {
15721
16091
  arr.push(activity.id);
15722
16092
  this._childrenByParent.set(key, arr);
15723
16093
  }
16094
+ const compareIds = (left, right) => {
16095
+ const leftActivity = this.activities.get(left);
16096
+ const rightActivity = this.activities.get(right);
16097
+ if (!(leftActivity && rightActivity)) {
16098
+ return String(left).localeCompare(String(right));
16099
+ }
16100
+ return compareActivitiesInVisualOrder(leftActivity, rightActivity);
16101
+ };
16102
+ this._roots.sort(compareIds);
16103
+ for (const children of this._childrenByParent.values()) {
16104
+ children.sort(compareIds);
16105
+ }
15724
16106
  }
15725
16107
  };
15726
16108
 
@@ -16160,438 +16542,145 @@ var ScheduleState = class {
16160
16542
  this._viewState.restore(this._viewStateBefore);
16161
16543
  }
16162
16544
  if (this._lastStartDateBefore !== null) {
16163
- this._lastStartDate = this._lastStartDateBefore;
16164
- }
16165
- this._cache.ids = null;
16166
- this._cache.visualOrderIds = null;
16167
- this._hierarchy.markDirty();
16168
- }
16169
- _restoreCorrelatives(correlativeBefore) {
16170
- for (const [id, before] of correlativeBefore) {
16171
- const live = this._activities.get(id);
16172
- if (live) live.correlativeId = before;
16173
- }
16174
- }
16175
- _undoLinkAdds(ops) {
16176
- for (const op of ops)
16177
- if (op.kind === "link-add") this._detachLink(op.linkId);
16178
- }
16179
- _undoInserts(ops) {
16180
- for (const op of ops)
16181
- if (op.kind === "insert") this._activities.delete(op.activityId);
16182
- }
16183
- _reInsertRemovedActivities(ops) {
16184
- for (const op of ops)
16185
- if (op.kind === "remove") this._activities.set(op.activityId, op.before);
16186
- }
16187
- _reAddRemovedLinks(ops) {
16188
- for (const op of ops)
16189
- if (op.kind === "link-remove") this._attachLink(op.before);
16190
- }
16191
- _restoreLinkFields(ops) {
16192
- for (const op of ops)
16193
- if (op.kind === "link-field" && this._links.has(op.linkId))
16194
- this._links.set(op.linkId, op.before);
16195
- }
16196
- _restoreActivityFields(before) {
16197
- for (const [id, snapshot] of before) {
16198
- const live = this._activities.get(id);
16199
- if (live) this._restoreScalarFields(live, snapshot);
16200
- }
16201
- }
16202
- _restoreScalarFields(live, before) {
16203
- for (const key of Object.keys(live)) {
16204
- if (!Object.hasOwn(before, key)) Reflect.deleteProperty(live, key);
16205
- }
16206
- for (const key of Object.keys(before)) {
16207
- Reflect.set(live, key, Reflect.get(before, key));
16208
- }
16209
- }
16210
- _attachLink(link) {
16211
- this._links.set(String(link.id), { ...link });
16212
- this._indexLink(link);
16213
- }
16214
- _detachLink(linkId) {
16215
- const link = this.getLink(linkId);
16216
- if (!link) return;
16217
- this._links.delete(String(linkId));
16218
- this._deindexLink(link);
16219
- }
16220
- };
16221
- var EMPTY_LINK_IDS = [];
16222
- function isMutableLinkField(field) {
16223
- return field === LINK_PROPERTY.LAG || field === LINK_PROPERTY.TYPE;
16224
- }
16225
- function fieldAffectsVisualOrder(field) {
16226
- return field === ACTIVITY_PROPERTY.PARENT || field === ACTIVITY_PROPERTY.CORRELATIVE_ID;
16227
- }
16228
- function detachLinkRef(refs, linkId) {
16229
- return refs.filter((ref) => String(ref) !== String(linkId));
16230
- }
16231
- function pushLinkRef(map, key, linkId) {
16232
- const refs = map.get(key);
16233
- if (refs) refs.push(linkId);
16234
- else map.set(key, [linkId]);
16235
- }
16236
- function buildFlags(snapshot) {
16237
- const rawFlags = snapshot.runtimeFlags ?? {};
16238
- return {
16239
- isPasting: Boolean(rawFlags.isPasting),
16240
- isBulkOperation: Boolean(rawFlags.isBulkOperation),
16241
- dragWithMultiple: Boolean(rawFlags.dragWithMultiple),
16242
- draggingSingleMilestone: Boolean(rawFlags.draggingSingleMilestone),
16243
- creatingActivity: false,
16244
- avoidAutoScheduleBeforeDrag: false,
16245
- maxPerformance: Boolean(rawFlags.maxPerformance),
16246
- allCheckedTaskIds: []
16247
- };
16248
- }
16249
-
16250
- // src/init/read-api.ts
16251
- function readActivity(state, id) {
16252
- return state.getActivity(id);
16253
- }
16254
- function readAllActivities(state) {
16255
- return state.getAllActivities();
16256
- }
16257
- function readAllIds(state) {
16258
- return state.getAllIds().map(String);
16259
- }
16260
- function forEachActivityId(state, visit) {
16261
- state.forEachActivity((_activity, id) => visit(id));
16262
- }
16263
- function readChildren(state, parentId) {
16264
- const childIds = parentId === ROOT_PARENT_ID ? readChildrenIds(state, ROOT_PARENT_ID) : state.getChildren(parentId);
16265
- const out = [];
16266
- for (const id of childIds) {
16267
- const snap = state.getActivity(id);
16268
- if (snap) out.push(snap);
16269
- }
16270
- out.sort((a, b) => (a.correlativeId ?? 0) - (b.correlativeId ?? 0));
16271
- return out;
16272
- }
16273
- function readChildrenIds(state, parentId) {
16274
- const key = parentId;
16275
- if (key === ROOT_PARENT_ID) {
16276
- const roots = [];
16277
- state.forEachActivity((activity, id) => {
16278
- if (isRootParent(activity.parentId)) roots.push(id);
16279
- });
16280
- return roots;
16281
- }
16282
- return [...state.getChildren(key)].map(String);
16283
- }
16284
- function readSelectedActivityIds(state) {
16285
- return state.checkedIds().map(String);
16286
- }
16287
- function readHasChild(state, parentId) {
16288
- return state.getChildren(parentId).length > 0;
16289
- }
16290
- function readLink(state, id) {
16291
- const l = state.getLink(id);
16292
- return l ? snapshotToLink(l) : null;
16293
- }
16294
- function readAllLinks(state) {
16295
- return state.getAllLinks().map((l) => snapshotToLink(l));
16296
- }
16297
-
16298
- // src/propagations/downward/recompute-ponderator-for-parent.ts
16299
- function recomputePonderatorsForParent(parentId, criterion, adapter) {
16300
- if (!parentId || parentId === "0") return;
16301
- const childIds = adapter.getChildren(parentId);
16302
- if (childIds.length === 0) return;
16303
- const pesoById = /* @__PURE__ */ new Map();
16304
- let denominator = 0;
16305
- for (const childId of childIds) {
16306
- const peso = criterionValue(String(childId), criterion, adapter);
16307
- pesoById.set(String(childId), peso);
16308
- denominator += peso;
16309
- }
16310
- const relationValue = denominator ? 100 / denominator : 0;
16311
- for (const childId of childIds) {
16312
- const child = adapter.getActivity(childId);
16313
- if (!child) continue;
16314
- const points = child.baselinePoints;
16315
- const active = getActiveBaseline(child);
16316
- if (active) {
16317
- const peso = pesoById.get(String(childId)) ?? 0;
16318
- adapter.setActivityField(
16319
- childId,
16320
- COLUMN.PONDERATOR,
16321
- relationValue * peso
16322
- );
16323
- } else if (!Array.isArray(points) || points.length === 0) {
16324
- adapter.setActivityField(childId, COLUMN.PONDERATOR, 0);
16325
- }
16326
- }
16327
- }
16328
- function criterionValue(childId, criterion, adapter) {
16329
- const child = adapter.getActivity(childId);
16330
- if (!child) return 0;
16331
- const active = getActiveBaseline(child);
16332
- if (!active) return 0;
16333
- if (criterion === "COST") return toNumber(active.cost);
16334
- if (criterion === "HH") return toNumber(active.workHours);
16335
- const type = child.type;
16336
- if (type === "project")
16337
- return sumRecursiveBaselineDurationDays(childId, adapter);
16338
- if (type === "milestone") return 0;
16339
- return toNumber(active.durationDays);
16340
- }
16341
- function sumRecursiveBaselineDurationDays(activityId, adapter) {
16342
- let sum = 0;
16343
- for (const childId of adapter.getChildren(activityId)) {
16344
- const child = adapter.getActivity(childId);
16345
- if (!child) continue;
16346
- const active = getActiveBaseline(child);
16347
- if (!active) continue;
16348
- const type = child.type;
16349
- if (type === "project") {
16350
- sum += sumRecursiveBaselineDurationDays(String(childId), adapter);
16351
- } else if (type !== "milestone") {
16352
- sum += toNumber(active.durationDays);
16353
- }
16354
- }
16355
- return sum;
16356
- }
16357
- function toNumber(v) {
16358
- const n = typeof v === "string" ? parseFloat(v) : v;
16359
- return typeof n === "number" && Number.isFinite(n) ? n : 0;
16360
- }
16361
-
16362
- // src/propagations/downward/recompute-all-ponderators.ts
16363
- function recomputeAllPonderators(criterion, adapter) {
16364
- adapter.forEachActivity((_a, id) => {
16365
- adapter.setActivityField(id, COLUMN.PONDERATOR, 0);
16366
- });
16367
- adapter.forEachActivity((_a, id) => {
16368
- if (adapter.getChildren(id).length > 0) {
16369
- recomputePonderatorsForParent(String(id), criterion, adapter);
16545
+ this._lastStartDate = this._lastStartDateBefore;
16370
16546
  }
16371
- });
16372
- }
16373
-
16374
- // src/propagations/upward/progress-rollup.ts
16375
- function recomputeAllProgressRollup(adapter) {
16376
- for (const parentId of parentsDeepestFirst(adapter)) {
16377
- rollupParent(parentId, adapter);
16547
+ this._cache.ids = null;
16548
+ this._cache.visualOrderIds = null;
16549
+ this._hierarchy.markDirty();
16378
16550
  }
16379
- }
16380
- function parentsDeepestFirst(adapter) {
16381
- const parents = /* @__PURE__ */ new Set();
16382
- adapter.forEachActivity((_activity, id) => {
16383
- if (adapter.getChildren(id).length > 0) parents.add(id);
16384
- });
16385
- const depthById = /* @__PURE__ */ new Map();
16386
- for (const id of parents) depthById.set(id, depthOf2(id, adapter));
16387
- return [...parents].sort(
16388
- (a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
16389
- );
16390
- }
16391
- function depthOf2(id, adapter) {
16392
- let depth = 0;
16393
- let current = id;
16394
- while (current && current !== "0") {
16395
- if (!adapter.getActivity(current)) break;
16396
- depth += 1;
16397
- current = adapter.getParentId(current);
16551
+ _restoreCorrelatives(correlativeBefore) {
16552
+ for (const [id, before] of correlativeBefore) {
16553
+ const live = this._activities.get(id);
16554
+ if (live) live.correlativeId = before;
16555
+ }
16398
16556
  }
16399
- return depth;
16400
- }
16401
- function rollupParent(parentId, adapter) {
16402
- const childIds = adapter.getChildren(parentId);
16403
- if (childIds.length === 0) return;
16404
- const children = [];
16405
- for (const childId of childIds) {
16406
- const child = adapter.getActivity(childId);
16407
- if (!child) continue;
16408
- children.push({
16409
- progress: Number(child.progress ?? 0),
16410
- ponderator: Number(child.ponderator ?? 0)
16411
- });
16557
+ _undoLinkAdds(ops) {
16558
+ for (const op of ops)
16559
+ if (op.kind === "link-add") this._detachLink(op.linkId);
16412
16560
  }
16413
- const rollup = computeWeightedProgressRollup(children);
16414
- if (rollup !== null) {
16415
- adapter.setActivityField(
16416
- parentId,
16417
- COLUMN.PROGRESS,
16418
- roundProgressPerLevel(rollup)
16419
- );
16561
+ _undoInserts(ops) {
16562
+ for (const op of ops)
16563
+ if (op.kind === "insert") this._activities.delete(op.activityId);
16420
16564
  }
16421
- }
16422
-
16423
- // src/baselines/normalize-baseline-point.ts
16424
- function parseBaselineDate(value) {
16425
- return typeof value === "string" && value.length > 0 ? parseBackendDate(value) : value instanceof Date ? value : null;
16426
- }
16427
- function parseFiniteNonNegative(value) {
16428
- const numeric = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : Number.NaN;
16429
- if (!Number.isFinite(numeric) || numeric < 0) return null;
16430
- return numeric;
16431
- }
16432
- function normalizeBaselinePoint(point, reporter) {
16433
- const durationDays = parseFiniteNonNegative(point.duration);
16434
- const cost = parseFiniteNonNegative(point.cost);
16435
- const workHours = parseFiniteNonNegative(point.hh_work);
16436
- if (durationDays === null || cost === null || workHours === null) {
16437
- reporter.warn(
16438
- `[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)}`
16439
- );
16440
- return null;
16565
+ _reInsertRemovedActivities(ops) {
16566
+ for (const op of ops)
16567
+ if (op.kind === "remove") this._activities.set(op.activityId, op.before);
16441
16568
  }
16442
- return {
16443
- startDate: parseBaselineDate(point.start_date),
16444
- endDate: parseBaselineDate(point.end_date),
16445
- durationDays,
16446
- cost,
16447
- workHours,
16448
- versionId: typeof point.sectorbaselineversionId === "number" ? point.sectorbaselineversionId : null,
16449
- isActiveVersion: Boolean(point.sectorbaselineversion?.active),
16450
- baseCalendarId: point.baseCalendarId != null ? String(point.baseCalendarId) : null,
16451
- hoursPerDay: typeof point.hoursPerDay === "number" ? point.hoursPerDay : null,
16452
- hoursPerWeek: typeof point.hoursPerWeek === "number" ? point.hoursPerWeek : null
16453
- };
16454
- }
16455
-
16456
- // src/baselines/apply-baseline-points.ts
16457
- function applyBaselinePoints(adapter, points, reporter) {
16458
- const idByProplanner = /* @__PURE__ */ new Map();
16459
- adapter.forEachActivity((a, id) => {
16460
- const pid = a.proplannerId;
16461
- if (typeof pid === "number") idByProplanner.set(pid, id);
16462
- });
16463
- const grouped = /* @__PURE__ */ new Map();
16464
- for (const p of points) {
16465
- const activityId = p.activityId;
16466
- if (typeof activityId !== "number") continue;
16467
- const coreId = idByProplanner.get(activityId);
16468
- if (coreId === void 0) continue;
16469
- const arr = grouped.get(coreId);
16470
- if (arr) arr.push(p);
16471
- else grouped.set(coreId, [p]);
16569
+ _reAddRemovedLinks(ops) {
16570
+ for (const op of ops)
16571
+ if (op.kind === "link-remove") this._attachLink(op.before);
16472
16572
  }
16473
- const changed = [];
16474
- for (const [coreId, group] of grouped) {
16475
- adapter.setActivityField(
16476
- coreId,
16477
- "baselinePoints",
16478
- group.map((point) => normalizeBaselinePoint(point, reporter)).filter((point) => point !== null)
16479
- );
16480
- changed.push(coreId);
16573
+ _restoreLinkFields(ops) {
16574
+ for (const op of ops)
16575
+ if (op.kind === "link-field" && this._links.has(op.linkId))
16576
+ this._links.set(op.linkId, op.before);
16481
16577
  }
16482
- adapter.forEachActivity((a, id) => {
16483
- if (grouped.has(id)) return;
16484
- const existing = a.baselinePoints;
16485
- if (Array.isArray(existing) && existing.length > 0) {
16486
- adapter.setActivityField(id, "baselinePoints", []);
16487
- changed.push(id);
16578
+ _restoreActivityFields(before) {
16579
+ for (const [id, snapshot] of before) {
16580
+ const live = this._activities.get(id);
16581
+ if (live) this._restoreScalarFields(live, snapshot);
16488
16582
  }
16489
- });
16490
- return changed;
16583
+ }
16584
+ _restoreScalarFields(live, before) {
16585
+ for (const key of Object.keys(live)) {
16586
+ if (!Object.hasOwn(before, key)) Reflect.deleteProperty(live, key);
16587
+ }
16588
+ for (const key of Object.keys(before)) {
16589
+ Reflect.set(live, key, Reflect.get(before, key));
16590
+ }
16591
+ }
16592
+ _attachLink(link) {
16593
+ this._links.set(String(link.id), { ...link });
16594
+ this._indexLink(link);
16595
+ }
16596
+ _detachLink(linkId) {
16597
+ const link = this.getLink(linkId);
16598
+ if (!link) return;
16599
+ this._links.delete(String(linkId));
16600
+ this._deindexLink(link);
16601
+ }
16602
+ };
16603
+ var EMPTY_LINK_IDS = [];
16604
+ function isMutableLinkField(field) {
16605
+ return field === LINK_PROPERTY.LAG || field === LINK_PROPERTY.TYPE;
16491
16606
  }
16492
-
16493
- // src/baselines/baseline-snapshot.ts
16494
- function buildBaselineSnapshot(activity) {
16495
- const active = getActiveBaseline(activity);
16496
- if (!active) return null;
16607
+ function fieldAffectsVisualOrder(field) {
16608
+ return field === ACTIVITY_PROPERTY.PARENT || field === ACTIVITY_PROPERTY.CORRELATIVE_ID;
16609
+ }
16610
+ function detachLinkRef(refs, linkId) {
16611
+ return refs.filter((ref) => String(ref) !== String(linkId));
16612
+ }
16613
+ function pushLinkRef(map, key, linkId) {
16614
+ const refs = map.get(key);
16615
+ if (refs) refs.push(linkId);
16616
+ else map.set(key, [linkId]);
16617
+ }
16618
+ function buildFlags(snapshot) {
16619
+ const rawFlags = snapshot.runtimeFlags ?? {};
16497
16620
  return {
16498
- startDate: active.startDate,
16499
- endDate: active.endDate,
16500
- durationDays: active.durationDays,
16501
- cost: active.cost,
16502
- workHours: active.workHours
16621
+ isPasting: Boolean(rawFlags.isPasting),
16622
+ isBulkOperation: Boolean(rawFlags.isBulkOperation),
16623
+ dragWithMultiple: Boolean(rawFlags.dragWithMultiple),
16624
+ draggingSingleMilestone: Boolean(rawFlags.draggingSingleMilestone),
16625
+ creatingActivity: false,
16626
+ avoidAutoScheduleBeforeDrag: false,
16627
+ maxPerformance: Boolean(rawFlags.maxPerformance),
16628
+ allCheckedTaskIds: []
16503
16629
  };
16504
16630
  }
16505
- function emitBaselineSnapshotColumns(state) {
16506
- const changed = [];
16507
- state.forEachActivity((activity, id) => {
16508
- const snapshot = buildBaselineSnapshot(activity);
16509
- if (!snapshot) return;
16510
- state.setActivityField(id, "baselineSnapshot", snapshot);
16511
- changed.push(id);
16512
- });
16513
- return changed;
16514
- }
16515
16631
 
16516
- // src/baselines/apply-baseline-overlay.ts
16517
- function applyBaselineOverlay(state, points, now, reporter, defaultBaseCalendarId = null) {
16518
- if (points.length === 0) return [];
16519
- const changed = /* @__PURE__ */ new Set();
16520
- for (const id of applyBaselinePoints(
16521
- state,
16522
- points,
16523
- reporter
16524
- )) {
16525
- changed.add(id);
16526
- }
16527
- if (now) {
16528
- for (const id of runExpectedProgressBase(state, now, defaultBaseCalendarId))
16529
- changed.add(id);
16530
- }
16531
- for (const id of emitBaselineSnapshotColumns(state)) changed.add(id);
16532
- for (const id of emitRealCost(state)) changed.add(id);
16533
- return [...changed];
16632
+ // src/shared/clone-domain-value.ts
16633
+ function cloneDomainValue(value) {
16634
+ return structuredClone(value);
16534
16635
  }
16535
16636
 
16536
- // src/init/recompute-api.ts
16537
- function readPonderator(a) {
16538
- const v = a.ponderator;
16539
- return typeof v === "number" && Number.isFinite(v) ? v : 0;
16637
+ // src/init/read-api.ts
16638
+ function readActivity(state, id) {
16639
+ const activity = state.getActivity(id);
16640
+ return activity ? cloneDomainValue(activity) : null;
16540
16641
  }
16541
- function readProgress(a) {
16542
- const v = a.progress;
16543
- return typeof v === "number" && Number.isFinite(v) ? v : 0;
16642
+ function readAllActivities(state) {
16643
+ return state.getAllActivities().map(cloneDomainValue);
16544
16644
  }
16545
- function recomputeAllPonderators2(state, _hoursPerDay, criterion) {
16546
- const before = /* @__PURE__ */ new Map();
16547
- state.forEachActivity((a, id) => {
16548
- before.set(id, readPonderator(a));
16549
- });
16550
- recomputeAllPonderators(criterion, state);
16551
- const changed = [];
16552
- state.forEachActivity((a, id) => {
16553
- if (readPonderator(a) !== (before.get(id) ?? 0)) {
16554
- changed.push(structuredCloneActivity(a));
16555
- }
16556
- });
16557
- return changed;
16645
+ function readAllIds(state) {
16646
+ return state.getAllIds().map(String);
16558
16647
  }
16559
- function recomputeAllProgressRollup2(state, _hoursPerDay) {
16560
- const before = /* @__PURE__ */ new Map();
16561
- state.forEachActivity((a, id) => {
16562
- before.set(id, readProgress(a));
16563
- });
16564
- recomputeAllProgressRollup(state);
16565
- const changed = [];
16566
- state.forEachActivity((a, id) => {
16567
- if (readProgress(a) !== (before.get(id) ?? 0)) {
16568
- changed.push(structuredCloneActivity(a));
16569
- }
16570
- });
16571
- return changed;
16648
+ function forEachActivityId(state, visit) {
16649
+ state.forEachActivity((_activity, id) => visit(id));
16572
16650
  }
16573
- function applyBaselines(state, _hoursPerDay, points, now, reporter, defaultBaseCalendarId = null) {
16574
- const changedIds = applyBaselineOverlay(
16575
- state,
16576
- points,
16577
- now,
16578
- reporter,
16579
- defaultBaseCalendarId
16580
- );
16581
- const changed = [];
16582
- for (const id of changedIds) {
16651
+ function readChildren(state, parentId) {
16652
+ const childIds = parentId === ROOT_PARENT_ID ? readChildrenIds(state, ROOT_PARENT_ID) : state.getChildren(parentId);
16653
+ const out = [];
16654
+ for (const id of childIds) {
16583
16655
  const snap = state.getActivity(id);
16584
- if (snap) changed.push(structuredCloneActivity(snap));
16656
+ if (snap) out.push(cloneDomainValue(snap));
16657
+ }
16658
+ out.sort((a, b) => (a.correlativeId ?? 0) - (b.correlativeId ?? 0));
16659
+ return out;
16660
+ }
16661
+ function readChildrenIds(state, parentId) {
16662
+ const key = parentId;
16663
+ if (key === ROOT_PARENT_ID) {
16664
+ const roots = [];
16665
+ state.forEachActivity((activity, id) => {
16666
+ if (isRootParent(activity.parentId)) roots.push(id);
16667
+ });
16668
+ return roots;
16585
16669
  }
16586
- return changed;
16670
+ return [...state.getChildren(key)].map(String);
16587
16671
  }
16588
- function recomputeStatus(state, _hoursPerDay, criteria) {
16589
- const changed = [];
16590
- for (const id of applyStatusPass(state, criteria)) {
16591
- const snap = state.getActivity(id);
16592
- if (snap) changed.push(structuredCloneActivity(snap));
16593
- }
16594
- return changed;
16672
+ function readSelectedActivityIds(state) {
16673
+ return state.checkedIds().map(String);
16674
+ }
16675
+ function readHasChild(state, parentId) {
16676
+ return state.getChildren(parentId).length > 0;
16677
+ }
16678
+ function readLink(state, id) {
16679
+ const l = state.getLink(id);
16680
+ return l ? snapshotToLink(l) : null;
16681
+ }
16682
+ function readAllLinks(state) {
16683
+ return state.getAllLinks().map((l) => snapshotToLink(l));
16595
16684
  }
16596
16685
 
16597
16686
  // src/internal/state/project-work-hours.ts
@@ -16701,8 +16790,12 @@ function mergeCoalesced(top, next) {
16701
16790
  };
16702
16791
  return buildUndoEntry(changeSet);
16703
16792
  }
16704
- function isUndoableAction(action) {
16705
- return action.kind !== "sir-sync" && action.kind !== "activity-lookahead-sync";
16793
+ function getDispatchHistoryPolicy(action) {
16794
+ if (action.kind === "persistence-acknowledge") return "clear-on-success";
16795
+ if (action.kind === "sir-sync" || action.kind === "activity-lookahead-sync" || action.kind === "baseline-apply" || action.kind === "ponderator-criterion-set" || action.kind === "status-criteria-set") {
16796
+ return "skip";
16797
+ }
16798
+ return "record";
16706
16799
  }
16707
16800
  function needsResync(entry) {
16708
16801
  for (const change of entry.changeSet.activities) {
@@ -16969,6 +17062,7 @@ var UndoRecorder = class {
16969
17062
  clear() {
16970
17063
  this.undoStack.length = 0;
16971
17064
  this.redoStack.length = 0;
17065
+ this.resetCoalesce();
16972
17066
  }
16973
17067
  };
16974
17068
 
@@ -18337,6 +18431,117 @@ function snapDemotedLeafTiming(state, activityId) {
18337
18431
  state.setActivityField(activityId, ACTIVITY_PROPERTY.END_DATE, end);
18338
18432
  }
18339
18433
 
18434
+ // src/propagations/upward/recompute-real-work.ts
18435
+ function recomputeCanonicalRealWork(state) {
18436
+ const rootIds = [];
18437
+ const changedIds = [];
18438
+ state.forEachActivity((activity, activityId) => {
18439
+ if (activity.parentId === null) rootIds.push(String(activityId));
18440
+ });
18441
+ const visit = (activityId) => {
18442
+ const activity = state.getActivity(activityId);
18443
+ if (!activity) return 0;
18444
+ const childIds = [...state.getChildren(activityId)];
18445
+ const realWork = childIds.length === 0 ? computeLeafRealWork(activity.workHours, activity.progress) : childIds.reduce(
18446
+ (total, childId) => total + visit(String(childId)),
18447
+ 0
18448
+ );
18449
+ state.setActivityField(
18450
+ activityId,
18451
+ ACTIVITY_PROPERTY.REAL_WORK_HOURS,
18452
+ realWork
18453
+ );
18454
+ changedIds.push(activityId);
18455
+ return realWork;
18456
+ };
18457
+ for (const rootId of rootIds) visit(rootId);
18458
+ return changedIds;
18459
+ }
18460
+
18461
+ // src/init/initial-passes.ts
18462
+ async function runInitialPasses(deps) {
18463
+ const { state, sector, scheduler, skipAutoSchedule, now } = deps;
18464
+ recomputeCorrelativeIds(state);
18465
+ if (sector.updateDurationForPrimaveraEndDate) {
18466
+ recomputeDurationsFromDates(state);
18467
+ }
18468
+ normalizeLoadedConstraintDates(state);
18469
+ recomputeCanonicalRealWork(state);
18470
+ if (skipAutoSchedule) {
18471
+ if (now) {
18472
+ applyExpectedProgressLive(state, now);
18473
+ applyStatusPass(state, sector.statusCriteria);
18474
+ }
18475
+ return;
18476
+ }
18477
+ const result = await scheduler.schedule({});
18478
+ applyResults(state, result);
18479
+ normalizeMilestoneConstraintDatesForDisplay(state);
18480
+ recomputeSkippedLeafEnds(state);
18481
+ await updateParentBoundsFromChildren(state, void 0, false);
18482
+ if (now) {
18483
+ applyExpectedProgressLive(state, now);
18484
+ applyStatusPass(state, sector.statusCriteria);
18485
+ }
18486
+ }
18487
+ function recomputeSkippedLeafEnds(state) {
18488
+ state.forEachActivity((activity) => {
18489
+ if (activity.autoScheduling) return;
18490
+ if (!activity.startDate || activity.durationHours == null) return;
18491
+ if (state.getChildren(activity.id).length > 0) return;
18492
+ activity.endDate = state.calculateEndDate({
18493
+ startDate: activity.startDate,
18494
+ durationHours: activity.durationHours,
18495
+ task: activity
18496
+ });
18497
+ });
18498
+ }
18499
+ function recomputeDurationsFromDates(state) {
18500
+ state.forEachActivity((activity) => {
18501
+ if (!activity.startDate || !activity.endDate) return;
18502
+ activity.durationHours = state.calculateDuration({
18503
+ startDate: activity.startDate,
18504
+ endDate: activity.endDate,
18505
+ task: activity
18506
+ });
18507
+ });
18508
+ }
18509
+ function normalizeLoadedConstraintDates(state) {
18510
+ state.forEachActivity((activity) => {
18511
+ const type = activity.constraintType;
18512
+ if (!type || !activity.constraintDate) return;
18513
+ const constraintDate = activity.constraintDate;
18514
+ if (activity.type === "milestone" && (constraintDate.getUTCHours() !== 0 || constraintDate.getUTCMinutes() !== 0)) {
18515
+ return;
18516
+ }
18517
+ const calendar = state.calendarReader.getCalendar(
18518
+ String(activity.calendarId)
18519
+ );
18520
+ if (!calendar) return;
18521
+ activity.constraintDate = normalizeConstraintDate(
18522
+ activity.constraintDate,
18523
+ calendar,
18524
+ type
18525
+ );
18526
+ });
18527
+ }
18528
+ function normalizeMilestoneConstraintDatesForDisplay(state) {
18529
+ state.forEachActivity((activity) => {
18530
+ if (activity.type !== "milestone") return;
18531
+ const type = activity.constraintType;
18532
+ if (!type || !activity.constraintDate) return;
18533
+ const calendar = state.calendarReader.getCalendar(
18534
+ String(activity.calendarId)
18535
+ );
18536
+ if (!calendar) return;
18537
+ activity.constraintDate = normalizeConstraintDate(
18538
+ activity.constraintDate,
18539
+ calendar,
18540
+ type
18541
+ );
18542
+ });
18543
+ }
18544
+
18340
18545
  // src/init/initialize-core.ts
18341
18546
  var SCHEDULE_CORE_STATUS = {
18342
18547
  READY: "ready",
@@ -18424,48 +18629,8 @@ function initializeCore(input) {
18424
18629
  }
18425
18630
 
18426
18631
  // src/init/schedule-core.ts
18427
- function assertValidPersistenceAssignments(assignments, entityName, readCurrent, ownerByBackendId) {
18428
- const seenIds = /* @__PURE__ */ new Set();
18429
- const seenBackendIds = /* @__PURE__ */ new Set();
18430
- for (const assignment of assignments) {
18431
- const id = String(assignment.id);
18432
- if (id.length === 0 || seenIds.has(id)) {
18433
- throw new Error(
18434
- `acknowledgePersistence: duplicate or empty ${entityName} id "${id}"`
18435
- );
18436
- }
18437
- if (!Number.isSafeInteger(assignment.proplannerId) || assignment.proplannerId <= 0 || seenBackendIds.has(assignment.proplannerId)) {
18438
- throw new Error(
18439
- `acknowledgePersistence: invalid or duplicate ${entityName} proplannerId ${String(assignment.proplannerId)}`
18440
- );
18441
- }
18442
- const state = readCurrent(id);
18443
- if (!state.exists) {
18444
- throw new Error(
18445
- `acknowledgePersistence: unknown ${entityName} id "${id}"`
18446
- );
18447
- }
18448
- if (state.current !== null && state.current !== assignment.proplannerId) {
18449
- throw new Error(
18450
- `acknowledgePersistence: ${entityName} "${id}" already has proplannerId ${String(state.current)}`
18451
- );
18452
- }
18453
- const existingOwner = ownerByBackendId.get(assignment.proplannerId);
18454
- if (existingOwner !== void 0 && existingOwner !== id) {
18455
- throw new Error(
18456
- `acknowledgePersistence: ${entityName} proplannerId ${String(assignment.proplannerId)} already belongs to "${existingOwner}"`
18457
- );
18458
- }
18459
- seenIds.add(id);
18460
- seenBackendIds.add(assignment.proplannerId);
18461
- }
18462
- }
18463
18632
  var ScheduleCore = class {
18464
18633
  _status = SCHEDULE_CORE_STATUS.READY;
18465
- /** True while an async dispatch is suspended inside the write-capture window.
18466
- * A sync facade mutation running in that gap would corrupt the in-flight
18467
- * journal, so sync mutators refuse to run while it is set. */
18468
- _dispatchInFlight = false;
18469
18634
  coreRuntime;
18470
18635
  _undo = new UndoRecorder();
18471
18636
  _opQueue = Promise.resolve();
@@ -18516,7 +18681,7 @@ var ScheduleCore = class {
18516
18681
  return this._status;
18517
18682
  }
18518
18683
  getSector() {
18519
- return this.coreRuntime.sector;
18684
+ return cloneDomainValue(this.coreRuntime.sector);
18520
18685
  }
18521
18686
  getActivityView(id) {
18522
18687
  this.assertReady();
@@ -18542,7 +18707,7 @@ var ScheduleCore = class {
18542
18707
  this.assertReady();
18543
18708
  const snapshot = this.coreRuntime.state.getActivity(activityId);
18544
18709
  if (!snapshot) return null;
18545
- return snapshot[property];
18710
+ return cloneDomainValue(snapshot[property]);
18546
18711
  }
18547
18712
  getAllIds() {
18548
18713
  this.assertReady();
@@ -18569,7 +18734,7 @@ var ScheduleCore = class {
18569
18734
  */
18570
18735
  getVisualOrderIds() {
18571
18736
  this.assertReady();
18572
- return this.coreRuntime.state.getVisualOrderIds();
18737
+ return [...this.coreRuntime.state.getVisualOrderIds()];
18573
18738
  }
18574
18739
  hasChild(parentId) {
18575
18740
  this.assertReady();
@@ -18577,15 +18742,21 @@ var ScheduleCore = class {
18577
18742
  }
18578
18743
  getCalendar(id) {
18579
18744
  this.assertReady();
18580
- return this.coreRuntime.calendars.get(id) ?? null;
18745
+ const calendar = this.coreRuntime.calendars.get(id);
18746
+ return calendar ? cloneDomainValue(calendar) : null;
18581
18747
  }
18582
18748
  getAllCalendars() {
18583
18749
  this.assertReady();
18584
- return Array.from(this.coreRuntime.calendars.values());
18750
+ return Array.from(
18751
+ this.coreRuntime.calendars.values(),
18752
+ (calendar) => cloneDomainValue(calendar)
18753
+ );
18585
18754
  }
18586
18755
  getBaseCalendars() {
18587
18756
  this.assertReady();
18588
- return this.coreRuntime.baseCalendars;
18757
+ return this.coreRuntime.baseCalendars.map(
18758
+ (calendar) => cloneDomainValue(calendar)
18759
+ );
18589
18760
  }
18590
18761
  isCustomIdInUse(customId, currentCustomId = null) {
18591
18762
  this.assertReady();
@@ -18602,184 +18773,9 @@ var ScheduleCore = class {
18602
18773
  this.assertReady();
18603
18774
  return this._saveTracker.modifiedLinks(this.getAllLinksView());
18604
18775
  }
18605
- markLinksPersisted() {
18606
- this._saveTracker.snapshotLinks(this.getAllLinksView());
18607
- }
18608
18776
  getModifiedActivities() {
18609
18777
  this.assertReady();
18610
- return this._saveTracker.modifiedActivities(
18611
- this.coreRuntime.state.getAllActivities()
18612
- );
18613
- }
18614
- markActivitiesPersisted() {
18615
- this._saveTracker.snapshotActivities(
18616
- this.coreRuntime.state.getAllActivities()
18617
- );
18618
- }
18619
- /**
18620
- * Reconciles the backend identities returned by a successful schedule save.
18621
- *
18622
- * This is an application-boundary acknowledgement, not an editable schedule
18623
- * gesture: it does not autoschedule, recompute, emit an undo entry, or invent
18624
- * domain changes. Every assignment is validated before the first mutation so
18625
- * a malformed/partial response cannot leave the core half-reconciled. Once
18626
- * applied, the complete live graph becomes the new save-tracker baseline.
18627
- */
18628
- acknowledgePersistence(acknowledgement) {
18629
- this.assertReady();
18630
- const activities = acknowledgement.activities ?? [];
18631
- const links = acknowledgement.links ?? [];
18632
- const activityOwnerByBackendId = /* @__PURE__ */ new Map();
18633
- for (const activity of this.coreRuntime.state.getAllActivities()) {
18634
- if (activity.proplannerId != null) {
18635
- activityOwnerByBackendId.set(
18636
- activity.proplannerId,
18637
- String(activity.id)
18638
- );
18639
- }
18640
- }
18641
- const linkOwnerByBackendId = /* @__PURE__ */ new Map();
18642
- for (const link of this.coreRuntime.state.getAllLinks()) {
18643
- if (link.proplannerId != null) {
18644
- linkOwnerByBackendId.set(link.proplannerId, String(link.id));
18645
- }
18646
- }
18647
- assertValidPersistenceAssignments(
18648
- activities,
18649
- "activity",
18650
- (id) => {
18651
- const activity = this.coreRuntime.state.getActivity(id);
18652
- return {
18653
- exists: activity !== null,
18654
- current: activity?.proplannerId ?? null
18655
- };
18656
- },
18657
- activityOwnerByBackendId
18658
- );
18659
- assertValidPersistenceAssignments(
18660
- links,
18661
- "link",
18662
- (id) => {
18663
- const link = this.coreRuntime.state.getLink(id);
18664
- return {
18665
- exists: link !== null,
18666
- current: link?.proplannerId ?? null
18667
- };
18668
- },
18669
- linkOwnerByBackendId
18670
- );
18671
- this.coreRuntime.state.batchUpdate(() => {
18672
- for (const assignment of activities) {
18673
- this.coreRuntime.state.setActivityField(
18674
- assignment.id,
18675
- "proplannerId",
18676
- assignment.proplannerId
18677
- );
18678
- }
18679
- for (const assignment of links) {
18680
- this.coreRuntime.state.setLinkProplannerId(
18681
- assignment.id,
18682
- assignment.proplannerId
18683
- );
18684
- }
18685
- });
18686
- this.markActivitiesPersisted();
18687
- this.markLinksPersisted();
18688
- }
18689
- applyBaselines(points) {
18690
- this.assertReady();
18691
- const now = this.coreRuntime.clock ? endOfLocalDay(this.coreRuntime.clock()) : null;
18692
- const defaultBaseCalendarId = this.coreRuntime.baseCalendars.find((calendar) => calendar.baseDefault)?.id ?? null;
18693
- return applyBaselines(
18694
- this.coreRuntime.state,
18695
- this.coreRuntime.sector.hoursPerDay,
18696
- points,
18697
- now,
18698
- this.coreRuntime.reporter,
18699
- defaultBaseCalendarId
18700
- );
18701
- }
18702
- /**
18703
- * Whole-tree ponderator recompute (zeroes, then redistributes 100 within
18704
- * each parent from its children's active baselines, weighted by `criterion`).
18705
- * Returns the activities whose `ponderator` changed, for a prop-only repaint.
18706
- * The base rollup (`applyBaselines`) depends on fresh ponderators, so callers
18707
- * run this before it on a criterion change or baseline save.
18708
- */
18709
- recomputeAllPonderators(criterion) {
18710
- this.assertReady();
18711
- return recomputeAllPonderators2(
18712
- this.coreRuntime.state,
18713
- this.coreRuntime.sector.hoursPerDay,
18714
- criterion
18715
- );
18716
- }
18717
- /**
18718
- * Recompute the weighted-progress rollup of every parent, bottom-up.
18719
- * Returns the activities whose `progress` changed, for a prop-only repaint.
18720
- */
18721
- recomputeAllProgressRollup() {
18722
- this.assertReady();
18723
- return recomputeAllProgressRollup2(
18724
- this.coreRuntime.state,
18725
- this.coreRuntime.sector.hoursPerDay
18726
- );
18727
- }
18728
- /**
18729
- * Set the project's status criterion (the Baseline↔Actual toggle) and
18730
- * recompute every activity's `status` against it. Stores the criterion so
18731
- * future dispatches keep deriving status with it. Returns the activities
18732
- * whose `status` changed, for a prop-only repaint.
18733
- */
18734
- setStatusCriteria(criteria) {
18735
- this.assertReady();
18736
- const resolved = resolveStatusCriteria(criteria);
18737
- this.coreRuntime.sector.statusCriteria = resolved;
18738
- return recomputeStatus(
18739
- this.coreRuntime.state,
18740
- this.coreRuntime.sector.hoursPerDay,
18741
- resolved
18742
- );
18743
- }
18744
- allocateActivityId() {
18745
- this.assertReady();
18746
- return this.coreRuntime.activityIdGenerator.next();
18747
- }
18748
- createActivity(input) {
18749
- this.assertReady();
18750
- if (this._dispatchInFlight) {
18751
- throw new Error(
18752
- "[ScheduleCore] createActivity called during an in-flight dispatch"
18753
- );
18754
- }
18755
- const action = { kind: "activity-create", ...input };
18756
- this.coreRuntime.state.beginWriteCapture();
18757
- this.coreRuntime.customIdTracker.beginCustomIdTransaction();
18758
- let result;
18759
- try {
18760
- result = createActivitySync(action, {
18761
- adapter: this.coreRuntime.state,
18762
- scheduler: this.coreRuntime.scheduler,
18763
- sector: this.coreRuntime.sector,
18764
- calendars: this.coreRuntime.calendars,
18765
- activityIdGen: this.coreRuntime.activityIdGenerator,
18766
- uidGen: this.coreRuntime.uniqueCorrelativeIdGenerator,
18767
- customIdTracker: this.coreRuntime.customIdTracker
18768
- });
18769
- if (!result.ok) this._rollback();
18770
- } catch (error) {
18771
- this._rollback();
18772
- throw error;
18773
- } finally {
18774
- this.coreRuntime.state.endWriteCapture();
18775
- this.coreRuntime.customIdTracker.commitCustomIdTransaction();
18776
- }
18777
- if (!result.ok) return result;
18778
- return {
18779
- ok: true,
18780
- activity: result.activity,
18781
- changes: result.changes
18782
- };
18778
+ return this._saveTracker.modifiedActivities(this.coreRuntime.state.getAllActivities()).map(cloneDomainValue);
18783
18779
  }
18784
18780
  _enqueue(work) {
18785
18781
  const workPromise = this._opQueue.then(work, work);
@@ -18799,10 +18795,9 @@ var ScheduleCore = class {
18799
18795
  dateFormat: this.coreRuntime.sector.dateFormat,
18800
18796
  inputUnit: options.inputUnit ?? "days"
18801
18797
  });
18802
- const undoable = isUndoableAction(action);
18798
+ const historyPolicy = getDispatchHistoryPolicy(action);
18803
18799
  this.coreRuntime.state.beginWriteCapture();
18804
18800
  this.coreRuntime.customIdTracker.beginCustomIdTransaction();
18805
- this._dispatchInFlight = true;
18806
18801
  let result;
18807
18802
  try {
18808
18803
  result = await dispatch(action, options, {
@@ -18815,6 +18810,7 @@ var ScheduleCore = class {
18815
18810
  linkIdGen: this.coreRuntime.linkIdGenerator,
18816
18811
  uidGen: this.coreRuntime.uniqueCorrelativeIdGenerator,
18817
18812
  customIdTracker: this.coreRuntime.customIdTracker,
18813
+ reporter: this.coreRuntime.reporter,
18818
18814
  defaultBaseCalendarId: this.coreRuntime.baseCalendars.find(
18819
18815
  (calendar) => calendar.baseDefault
18820
18816
  )?.id ?? null,
@@ -18825,11 +18821,10 @@ var ScheduleCore = class {
18825
18821
  this._rollback();
18826
18822
  throw error;
18827
18823
  } finally {
18828
- this._dispatchInFlight = false;
18829
18824
  this.coreRuntime.state.endWriteCapture();
18830
18825
  this.coreRuntime.customIdTracker.commitCustomIdTransaction();
18831
18826
  }
18832
- if (result.ok && undoable && changeSetIsSubstantive(result.changes)) {
18827
+ if (result.ok && historyPolicy === "record" && changeSetIsSubstantive(result.changes)) {
18833
18828
  const created = captureCreatedSnapshots(
18834
18829
  this.coreRuntime.state,
18835
18830
  result.changes
@@ -18846,11 +18841,18 @@ var ScheduleCore = class {
18846
18841
  Date.now()
18847
18842
  );
18848
18843
  }
18844
+ if (result.ok && historyPolicy === "clear-on-success") {
18845
+ this._saveTracker.snapshotActivities(
18846
+ this.coreRuntime.state.getAllActivities()
18847
+ );
18848
+ this._saveTracker.snapshotLinks(this.getAllLinksView());
18849
+ this._undo.clear();
18850
+ }
18849
18851
  if (!result.ok) return result;
18850
- if (changeSetIsSubstantive(result.changes)) {
18852
+ if (dispatchChangesSchedulingState(action) && changeSetIsSubstantive(result.changes)) {
18851
18853
  this._recordScheduleMutation(options.skipCriticalPath !== true);
18852
18854
  }
18853
- return { ...result, changes: result.changes };
18855
+ return cloneDomainValue(result);
18854
18856
  }
18855
18857
  /**
18856
18858
  * Starts or joins the Critical Path calculation for the current schedule
@@ -18983,12 +18985,42 @@ var ScheduleCore = class {
18983
18985
  }
18984
18986
  return { changes };
18985
18987
  }
18988
+ /**
18989
+ * Undo/Redo restores the user's historical mutation while retaining current
18990
+ * non-historical truth (for example a refreshed baseline). Re-derive every
18991
+ * value that depends on both so the restored model is immediately coherent.
18992
+ */
18993
+ _recomputeAfterHistoryRestore() {
18994
+ const state = this.coreRuntime.state;
18995
+ recomputeAllProgressRollup(state);
18996
+ recomputeCanonicalRealWork(state);
18997
+ emitRealCost(state);
18998
+ if (this.coreRuntime.clock) {
18999
+ const now = endOfLocalDay(this.coreRuntime.clock());
19000
+ applyExpectedProgressLive(state, now);
19001
+ let hasActiveBaseline = false;
19002
+ state.forEachActivity((activity) => {
19003
+ hasActiveBaseline ||= getActiveBaseline(activity) !== null;
19004
+ });
19005
+ if (hasActiveBaseline) {
19006
+ runExpectedProgressBase(
19007
+ state,
19008
+ now,
19009
+ this.coreRuntime.baseCalendars.find(
19010
+ (calendar) => calendar.baseDefault
19011
+ )?.id ?? null
19012
+ );
19013
+ }
19014
+ applyStatusPass(state, this.coreRuntime.sector.statusCriteria);
19015
+ }
19016
+ }
18986
19017
  undo() {
18987
19018
  const operation = this._enqueue(async () => {
18988
19019
  this.assertReady();
18989
19020
  const entry = this._undo.takeUndo();
18990
19021
  if (!entry) return null;
18991
19022
  applyUndo(this.coreRuntime.state, entry);
19023
+ this._recomputeAfterHistoryRestore();
18992
19024
  this._recordScheduleMutation(false);
18993
19025
  if (needsResync(entry)) this._resyncCustomIdTrackerFromModel();
18994
19026
  this._undo.pushRedo(entry);
@@ -19016,6 +19048,7 @@ var ScheduleCore = class {
19016
19048
  const entry = this._undo.takeRedo();
19017
19049
  if (!entry) return null;
19018
19050
  applyRedo(this.coreRuntime.state, entry);
19051
+ this._recomputeAfterHistoryRestore();
19019
19052
  this._recordScheduleMutation(false);
19020
19053
  if (needsResync(entry)) this._resyncCustomIdTrackerFromModel();
19021
19054
  this._undo.pushUndo(entry);
@@ -19037,15 +19070,20 @@ var ScheduleCore = class {
19037
19070
  );
19038
19071
  return operation;
19039
19072
  }
19040
- clearHistory() {
19041
- this._undo.clear();
19042
- }
19043
19073
  canUndo() {
19044
19074
  return this._undo.canUndo();
19045
19075
  }
19046
19076
  canRedo() {
19047
19077
  return this._undo.canRedo();
19048
19078
  }
19079
+ /**
19080
+ * Establishes a new persistence boundary without mutating schedule state.
19081
+ * Completed saves call this synchronously so neither prior undo entries nor
19082
+ * their redo branch can cross the persisted boundary.
19083
+ */
19084
+ clearHistory() {
19085
+ this._undo.clear();
19086
+ }
19049
19087
  undoDepth() {
19050
19088
  return this._undo.undoDepth();
19051
19089
  }
@@ -19131,6 +19169,10 @@ var DEFAULT_HOURS_PER_DAY = 8;
19131
19169
 
19132
19170
  // src/dispatch/action-kinds.ts
19133
19171
  var DISPATCH_ACTION_KIND = {
19172
+ PERSISTENCE_ACKNOWLEDGE: "persistence-acknowledge",
19173
+ BASELINE_APPLY: "baseline-apply",
19174
+ PONDERATOR_CRITERION_SET: "ponderator-criterion-set",
19175
+ STATUS_CRITERIA_SET: "status-criteria-set",
19134
19176
  INLINE_EDIT: "inline-edit",
19135
19177
  DATES_BATCH: "dates-batch",
19136
19178
  BULK_EDIT: "bulk-edit",
@@ -19152,6 +19194,10 @@ var DISPATCH_ACTION_KIND = {
19152
19194
  ACTIVITY_LOOKAHEAD_SYNC: "activity-lookahead-sync"
19153
19195
  };
19154
19196
  var KIND_CATALOG_COVERS_UNION = {
19197
+ [DISPATCH_ACTION_KIND.PERSISTENCE_ACKNOWLEDGE]: true,
19198
+ [DISPATCH_ACTION_KIND.BASELINE_APPLY]: true,
19199
+ [DISPATCH_ACTION_KIND.PONDERATOR_CRITERION_SET]: true,
19200
+ [DISPATCH_ACTION_KIND.STATUS_CRITERIA_SET]: true,
19155
19201
  [DISPATCH_ACTION_KIND.INLINE_EDIT]: true,
19156
19202
  [DISPATCH_ACTION_KIND.DATES_BATCH]: true,
19157
19203
  [DISPATCH_ACTION_KIND.BULK_EDIT]: true,
@@ -19182,6 +19228,6 @@ var CREATION_KIND = {
19182
19228
  ROOT: "root"
19183
19229
  };
19184
19230
 
19185
- export { ACTIVITY_TYPE, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE2 as CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, NEW_ACTIVITY_DEFAULTS, REJECTION_REASON, ROOT_PARENT_ID, ScheduleCore, WORK_TIME_DIRECTION, applyBaselinePoints, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, recomputeAllPonderators, recomputeAllProgressRollup, willRunCriticalPath, yieldToBrowser };
19231
+ export { ACTIVITY_TYPE, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE2 as CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, NEW_ACTIVITY_DEFAULTS, REJECTION_REASON, ROOT_PARENT_ID, ScheduleCore, WORK_TIME_DIRECTION, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };
19186
19232
  //# sourceMappingURL=index.js.map
19187
19233
  //# sourceMappingURL=index.js.map