@outbuild-company/schedule-core 1.9.1 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3289,6 +3289,84 @@ function roundProgressPerLevel(value) {
3289
3289
  return Number(value.toFixed(2));
3290
3290
  }
3291
3291
 
3292
+ // src/propagations/upward/progress-rollup.ts
3293
+ function recomputeAllProgressRollup(adapter) {
3294
+ for (const parentId of parentsDeepestFirst(adapter)) {
3295
+ rollupParent(parentId, adapter);
3296
+ }
3297
+ }
3298
+ function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
3299
+ for (const parentId of parentIdsDeepestFirst) {
3300
+ rollupParent(parentId, adapter);
3301
+ }
3302
+ }
3303
+ function parentsDeepestFirst(adapter) {
3304
+ const parents = /* @__PURE__ */ new Set();
3305
+ adapter.forEachActivity((_activity, id) => {
3306
+ if (adapter.getChildren(id).length > 0) parents.add(id);
3307
+ });
3308
+ const depthById = /* @__PURE__ */ new Map();
3309
+ for (const id of parents) depthById.set(id, depthOf(id, adapter));
3310
+ return [...parents].sort(
3311
+ (a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
3312
+ );
3313
+ }
3314
+ function depthOf(id, adapter) {
3315
+ let depth = 0;
3316
+ let current = id;
3317
+ while (current && current !== "0") {
3318
+ if (!adapter.getActivity(current)) break;
3319
+ depth += 1;
3320
+ current = adapter.getParentId(current);
3321
+ }
3322
+ return depth;
3323
+ }
3324
+ function rollupParent(parentId, adapter) {
3325
+ const childIds = adapter.getChildren(parentId);
3326
+ if (childIds.length === 0) return;
3327
+ const children = [];
3328
+ for (const childId of childIds) {
3329
+ const child = adapter.getActivity(childId);
3330
+ if (!child) continue;
3331
+ children.push({
3332
+ progress: Number(child.progress ?? 0),
3333
+ ponderator: Number(child.ponderator ?? 0)
3334
+ });
3335
+ }
3336
+ applyWeightedProgressRollup(parentId, children, adapter);
3337
+ }
3338
+ function applyWeightedProgressRollup(parentId, children, adapter) {
3339
+ const parent = adapter.getActivity(parentId);
3340
+ if (!parent) return;
3341
+ const rollup = computeWeightedProgressRollup(children);
3342
+ if (rollup === null) {
3343
+ const fallback = adapter.getProgressFallback(parentId);
3344
+ if (fallback !== null) {
3345
+ adapter.setActivityField(parentId, COLUMN.PROGRESS, fallback);
3346
+ }
3347
+ return;
3348
+ }
3349
+ if (adapter.getProgressFallback(parentId) === null) {
3350
+ adapter.setProgressFallback(parentId, Number(parent.progress ?? 0));
3351
+ }
3352
+ adapter.setActivityField(
3353
+ parentId,
3354
+ COLUMN.PROGRESS,
3355
+ roundProgressPerLevel(rollup)
3356
+ );
3357
+ }
3358
+ function setExplicitSummaryProgressFallbacks(activityId, progress, adapter) {
3359
+ const pending = [activityId];
3360
+ while (pending.length > 0) {
3361
+ const currentId = pending.pop();
3362
+ if (currentId === void 0) continue;
3363
+ const children = adapter.getChildren(currentId);
3364
+ if (children.length === 0) continue;
3365
+ adapter.setProgressFallback(currentId, progress);
3366
+ pending.push(...children);
3367
+ }
3368
+ }
3369
+
3292
3370
  // src/columns/real-work/compute.ts
3293
3371
  function computeLeafRealWork(workHours, progress) {
3294
3372
  return (Number(workHours) || 0) * (Number(progress) || 0) / 100;
@@ -3404,16 +3482,8 @@ function recomputeParentFromChildren(parentId, adapter, progressMode = "freeze-w
3404
3482
  adapter.setActivityField(parentId, "startDate", newStart);
3405
3483
  adapter.setActivityField(parentId, "endDate", newEnd);
3406
3484
  adapter.setActivityField(parentId, "durationHours", durationHours);
3407
- const progressRollup = computeWeightedProgressRollup(
3408
- aggregate.weightedChildren
3409
- );
3410
- const shouldWriteProgress = progressMode !== "skip" && (progressRollup !== null || progressMode === "zero-when-no-contribution");
3411
- if (shouldWriteProgress) {
3412
- adapter.setActivityField(
3413
- parentId,
3414
- "progress",
3415
- roundProgressPerLevel(progressRollup ?? 0)
3416
- );
3485
+ if (progressMode !== "skip") {
3486
+ applyWeightedProgressRollup(parentId, aggregate.weightedChildren, adapter);
3417
3487
  }
3418
3488
  if (recomputeRealWork) {
3419
3489
  adapter.setActivityField(parentId, "realWorkHours", aggregate.realWorkSum);
@@ -3436,10 +3506,10 @@ function collectParentIds(adapter) {
3436
3506
  }
3437
3507
  function computeDepths(ids, adapter) {
3438
3508
  const depths = /* @__PURE__ */ new Map();
3439
- for (const id of ids) depths.set(id, depthOf(id, adapter));
3509
+ for (const id of ids) depths.set(id, depthOf2(id, adapter));
3440
3510
  return depths;
3441
3511
  }
3442
- function depthOf(id, adapter) {
3512
+ function depthOf2(id, adapter) {
3443
3513
  let depth = 0;
3444
3514
  let current = id;
3445
3515
  while (current && !isRootParent(current)) {
@@ -3922,6 +3992,7 @@ function buildAncestorRollupCascade(activity, newValue, hierarchy) {
3922
3992
  const mutations = [];
3923
3993
  for (const id of chain) {
3924
3994
  const rollup = computeWeightedProgress(id, overlay, hierarchy);
3995
+ if (rollup === null) continue;
3925
3996
  overlay.set(id, rollup);
3926
3997
  mutations.push({
3927
3998
  activityId: id,
@@ -3935,7 +4006,8 @@ function computeWeightedProgress(parentId, overlay, hierarchy) {
3935
4006
  progress: overlay.has(child.id) ? overlay.get(child.id) : child.progress,
3936
4007
  ponderator: child.ponderator ?? 0
3937
4008
  }));
3938
- return Number((computeWeightedProgressRollup(children) ?? 0).toFixed(2));
4009
+ const rollup = computeWeightedProgressRollup(children);
4010
+ return rollup === null ? null : Number(rollup.toFixed(2));
3939
4011
  }
3940
4012
  function buildRecursiveTrackingEvents(activity, newValue) {
3941
4013
  return [
@@ -9886,24 +9958,82 @@ function resolveDerivedPasses(action, autoSchedule, options) {
9886
9958
 
9887
9959
  // src/dispatch/shared/post-mutation.ts
9888
9960
  async function runPostMutation(deps, args) {
9889
- const passes = resolvePasses(args);
9961
+ const progressInvalidation = resolveProgressInvalidation(deps.adapter);
9962
+ const passes = resolvePasses(args, progressInvalidation);
9890
9963
  if (passes.has(DERIVED_PASS.AUTOSCHEDULE)) {
9891
9964
  await refreshMutatedParentBounds(deps.adapter, args);
9892
9965
  }
9893
9966
  const schedule = passes.has(DERIVED_PASS.AUTOSCHEDULE) ? await runAutoschedule(deps, args.autoscheduleFrom) : emptySchedule();
9894
- await rollUpParentBounds(deps.adapter, args, schedule.scheduledIds, passes);
9967
+ await rollUpParentBounds(
9968
+ deps.adapter,
9969
+ args,
9970
+ schedule.scheduledIds,
9971
+ passes,
9972
+ progressInvalidation
9973
+ );
9895
9974
  await runDerivedRecomputes(deps, passes, args.now);
9896
9975
  return schedule;
9897
9976
  }
9898
- function resolvePasses(args) {
9977
+ function resolvePasses(args, progressInvalidation) {
9899
9978
  const requested = args.autoscheduleFrom !== null;
9900
9979
  const ran = !args.options.skipAutoSchedule && requested;
9901
9980
  const passes = new Set(
9902
9981
  resolveDerivedPasses(args.action, { ran }, args.options)
9903
9982
  );
9904
- if (args.recomputeParentProgress) passes.add(DERIVED_PASS.PARENT_PROGRESS);
9983
+ if (args.recomputeParentProgress || progressInvalidation.affectedParents.size > 0) {
9984
+ passes.add(DERIVED_PASS.PARENT_PROGRESS);
9985
+ }
9905
9986
  return passes;
9906
9987
  }
9988
+ function resolveProgressInvalidation(adapter) {
9989
+ const affectedParents = /* @__PURE__ */ new Set();
9990
+ const dirtySeeds = /* @__PURE__ */ new Set();
9991
+ const journal = adapter.peekWriteCapture();
9992
+ if (!journal) return { affectedParents, dirtySeeds };
9993
+ const affectParent = (parentId) => {
9994
+ if (parentId === null || isRootParent(parentId)) return;
9995
+ const normalized2 = String(parentId);
9996
+ affectedParents.add(normalized2);
9997
+ const childId = adapter.getChildren(normalized2)[0];
9998
+ if (childId !== void 0) dirtySeeds.add(childId);
9999
+ };
10000
+ collectStructuralProgressInvalidations(adapter, journal.ops, affectParent);
10001
+ collectFieldProgressInvalidations(
10002
+ adapter,
10003
+ journal.before,
10004
+ dirtySeeds,
10005
+ affectParent
10006
+ );
10007
+ return { affectedParents, dirtySeeds };
10008
+ }
10009
+ function collectStructuralProgressInvalidations(adapter, operations, affectParent) {
10010
+ for (const operation of operations) {
10011
+ if (operation.kind === "insert") {
10012
+ const inserted = adapter.getActivity(operation.activityId);
10013
+ if (inserted) affectParent(inserted.parentId);
10014
+ } else if (operation.kind === "remove") {
10015
+ affectParent(operation.before.parentId);
10016
+ }
10017
+ }
10018
+ }
10019
+ function collectFieldProgressInvalidations(adapter, beforeById, dirtySeeds, affectParent) {
10020
+ for (const [activityId, before] of beforeById) {
10021
+ const after = adapter.getActivity(activityId);
10022
+ if (!after) continue;
10023
+ const progressChanged = !Object.is(before.progress, after.progress);
10024
+ const ponderatorChanged = !Object.is(before.ponderator, after.ponderator);
10025
+ const parentChanged = !Object.is(before.parentId, after.parentId);
10026
+ if (progressChanged || ponderatorChanged) {
10027
+ affectParent(after.parentId);
10028
+ dirtySeeds.add(String(activityId));
10029
+ }
10030
+ if (parentChanged) {
10031
+ affectParent(before.parentId);
10032
+ affectParent(after.parentId);
10033
+ dirtySeeds.add(String(activityId));
10034
+ }
10035
+ }
10036
+ }
9907
10037
  async function runAutoschedule(deps, autoscheduleFrom) {
9908
10038
  const options = autoscheduleFrom === "roots" ? {} : { triggerId: autoscheduleFrom };
9909
10039
  const result = await deps.scheduler.schedule(options);
@@ -9931,18 +10061,36 @@ async function refreshMutatedParentBounds(adapter, args) {
9931
10061
  if (mutated.size === 0) return;
9932
10062
  await updateParentBoundsFromChildren(adapter, mutated, false);
9933
10063
  }
9934
- async function rollUpParentBounds(adapter, args, scheduledIds, passes) {
10064
+ async function rollUpParentBounds(adapter, args, scheduledIds, passes, progressInvalidation) {
10065
+ if (passes.has(DERIVED_PASS.PARENT_PROGRESS)) {
10066
+ restoreDemotedProgressFallbacks(
10067
+ adapter,
10068
+ progressInvalidation.affectedParents
10069
+ );
10070
+ }
9935
10071
  const dirty = args.collectDirty ? args.collectDirty(scheduledIds) : collectDirtyForStructural(args.recomputeParentsFrom, scheduledIds);
10072
+ for (const activityId of progressInvalidation.dirtySeeds) {
10073
+ dirty.add(activityId);
10074
+ }
9936
10075
  await updateParentBoundsFromChildren(
9937
10076
  adapter,
9938
10077
  dirty,
9939
10078
  passes.has(DERIVED_PASS.PARENT_PROGRESS),
9940
10079
  {
9941
10080
  recomputeRealWork: passes.has(DERIVED_PASS.REAL_WORK),
9942
- progressMode: args.recomputeParentProgress ? "zero-when-no-contribution" : "freeze-when-no-contribution"
10081
+ progressMode: "freeze-when-no-contribution"
9943
10082
  }
9944
10083
  );
9945
10084
  }
10085
+ function restoreDemotedProgressFallbacks(adapter, affectedParents) {
10086
+ for (const parentId of affectedParents) {
10087
+ if (adapter.hasChildren(parentId)) continue;
10088
+ const fallback = adapter.getProgressFallback(parentId);
10089
+ if (fallback === null) continue;
10090
+ adapter.setActivityField(parentId, "progress", fallback);
10091
+ adapter.setProgressFallback(parentId, null);
10092
+ }
10093
+ }
9946
10094
  async function runDerivedRecomputes(deps, passes, now) {
9947
10095
  if (passes.has(DERIVED_PASS.EXPECTED_PROGRESS) && now !== null) {
9948
10096
  if (hasActiveBaseline(deps.adapter)) {
@@ -11171,7 +11319,6 @@ function buildParentMutations(input) {
11171
11319
  if ((input.promotionSource ?? "create") === "create") {
11172
11320
  fields.constraintType = CONSTRAINT_TYPE.ASAP;
11173
11321
  fields.constraintDate = null;
11174
- fields.progress = 0;
11175
11322
  }
11176
11323
  }
11177
11324
  return {
@@ -12324,60 +12471,6 @@ function dispatchSirSync(action, deps) {
12324
12471
  };
12325
12472
  }
12326
12473
 
12327
- // src/propagations/upward/progress-rollup.ts
12328
- function recomputeAllProgressRollup(adapter) {
12329
- for (const parentId of parentsDeepestFirst(adapter)) {
12330
- rollupParent(parentId, adapter);
12331
- }
12332
- }
12333
- function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
12334
- for (const parentId of parentIdsDeepestFirst) {
12335
- rollupParent(parentId, adapter);
12336
- }
12337
- }
12338
- function parentsDeepestFirst(adapter) {
12339
- const parents = /* @__PURE__ */ new Set();
12340
- adapter.forEachActivity((_activity, id) => {
12341
- if (adapter.getChildren(id).length > 0) parents.add(id);
12342
- });
12343
- const depthById = /* @__PURE__ */ new Map();
12344
- for (const id of parents) depthById.set(id, depthOf2(id, adapter));
12345
- return [...parents].sort(
12346
- (a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
12347
- );
12348
- }
12349
- function depthOf2(id, adapter) {
12350
- let depth = 0;
12351
- let current = id;
12352
- while (current && current !== "0") {
12353
- if (!adapter.getActivity(current)) break;
12354
- depth += 1;
12355
- current = adapter.getParentId(current);
12356
- }
12357
- return depth;
12358
- }
12359
- function rollupParent(parentId, adapter) {
12360
- const childIds = adapter.getChildren(parentId);
12361
- if (childIds.length === 0) return;
12362
- const children = [];
12363
- for (const childId of childIds) {
12364
- const child = adapter.getActivity(childId);
12365
- if (!child) continue;
12366
- children.push({
12367
- progress: Number(child.progress ?? 0),
12368
- ponderator: Number(child.ponderator ?? 0)
12369
- });
12370
- }
12371
- const rollup = computeWeightedProgressRollup(children);
12372
- if (rollup !== null) {
12373
- adapter.setActivityField(
12374
- parentId,
12375
- COLUMN.PROGRESS,
12376
- roundProgressPerLevel(rollup)
12377
- );
12378
- }
12379
- }
12380
-
12381
12474
  // src/dispatch/handlers/persistence-acknowledge.ts
12382
12475
  function persistedOwnersOf(entities) {
12383
12476
  const owners = /* @__PURE__ */ new Map();
@@ -13444,6 +13537,11 @@ async function dispatchActivitySetProgress(action, options, deps) {
13444
13537
  const touchedIds = collectTouchedIds(action.activityId, changes);
13445
13538
  const beforeSnap = await snapshotActivities(adapter, touchedIds);
13446
13539
  applyFieldChanges(adapter, action.activityId, changes);
13540
+ setExplicitSummaryProgressFallbacks(
13541
+ action.activityId,
13542
+ action.newValue,
13543
+ adapter
13544
+ );
13447
13545
  runPostProcessorsOnAdapter(
13448
13546
  action.activityId,
13449
13547
  changes.postProcessors ?? [],
@@ -17307,7 +17405,8 @@ var WriteCapture = class {
17307
17405
  ops: [],
17308
17406
  linkFieldCaptured: /* @__PURE__ */ new Set(),
17309
17407
  correlativeBefore: /* @__PURE__ */ new Map(),
17310
- scheduledBefore: /* @__PURE__ */ new Map()
17408
+ scheduledBefore: /* @__PURE__ */ new Map(),
17409
+ progressFallbackBefore: /* @__PURE__ */ new Map()
17311
17410
  };
17312
17411
  }
17313
17412
  peek() {
@@ -17370,6 +17469,11 @@ var WriteCapture = class {
17370
17469
  before: cloneLink(current)
17371
17470
  });
17372
17471
  }
17472
+ noteProgressFallback(activityId, current) {
17473
+ const journal = this._journal;
17474
+ if (!journal || journal.progressFallbackBefore.has(activityId)) return;
17475
+ journal.progressFallbackBefore.set(activityId, current);
17476
+ }
17373
17477
  };
17374
17478
  function cloneLink(link) {
17375
17479
  return { ...link };
@@ -17615,6 +17719,7 @@ var ScheduleState = class _ScheduleState {
17615
17719
  _activities = /* @__PURE__ */ new Map();
17616
17720
  _lastStartDate = /* @__PURE__ */ new Map();
17617
17721
  _promotionSnapshot = /* @__PURE__ */ new Map();
17722
+ _progressFallback = /* @__PURE__ */ new Map();
17618
17723
  _links = /* @__PURE__ */ new Map();
17619
17724
  _outgoing = /* @__PURE__ */ new Map();
17620
17725
  _incoming = /* @__PURE__ */ new Map();
@@ -17675,6 +17780,7 @@ var ScheduleState = class _ScheduleState {
17675
17780
  cloneDomainValue(snapshot)
17676
17781
  ])
17677
17782
  );
17783
+ fork._progressFallback = new Map(this._progressFallback);
17678
17784
  fork._flags = cloneDomainValue(this._flags);
17679
17785
  fork._filterProjection = cloneDomainValue(this._filterProjection);
17680
17786
  return fork;
@@ -17728,6 +17834,17 @@ var ScheduleState = class _ScheduleState {
17728
17834
  this._capturePromotionSnapshotOnce();
17729
17835
  this._promotionSnapshot.set(String(activityId), snapshot);
17730
17836
  }
17837
+ getProgressFallback(activityId) {
17838
+ return this._progressFallback.get(String(activityId)) ?? null;
17839
+ }
17840
+ setProgressFallback(activityId, value) {
17841
+ const key = String(activityId);
17842
+ const current = this._progressFallback.get(key) ?? null;
17843
+ if (Object.is(current, value)) return;
17844
+ this._writeCapture.noteProgressFallback(key, current);
17845
+ if (value === null) this._progressFallback.delete(key);
17846
+ else this._progressFallback.set(key, value);
17847
+ }
17731
17848
  _capturePromotionSnapshotOnce() {
17732
17849
  if (this._writeCapture.peek() === null) return;
17733
17850
  if (this._promotionSnapshotBefore === null) {
@@ -17978,6 +18095,7 @@ var ScheduleState = class _ScheduleState {
17978
18095
  const activity = this.getActivity(activityId);
17979
18096
  if (activity) this._writeCapture.noteRemove(String(activityId), activity);
17980
18097
  const key = String(activityId);
18098
+ this.setProgressFallback(key, null);
17981
18099
  if (this._viewState.isChecked(key) || !this._viewState.isVisible(key)) {
17982
18100
  this._captureViewStateOnce();
17983
18101
  }
@@ -18002,7 +18120,13 @@ var ScheduleState = class _ScheduleState {
18002
18120
  restoreFromCapture() {
18003
18121
  const journal = this._writeCapture.peek();
18004
18122
  if (!journal) return;
18005
- const { ops, before, correlativeBefore, scheduledBefore } = journal;
18123
+ const {
18124
+ ops,
18125
+ before,
18126
+ correlativeBefore,
18127
+ scheduledBefore,
18128
+ progressFallbackBefore
18129
+ } = journal;
18006
18130
  this._undoLinkAdds(ops);
18007
18131
  this._undoInserts(ops);
18008
18132
  this._reInsertRemovedActivities(ops);
@@ -18011,6 +18135,7 @@ var ScheduleState = class _ScheduleState {
18011
18135
  this._restoreCorrelatives(correlativeBefore);
18012
18136
  this._restoreActivityFields(scheduledBefore);
18013
18137
  this._restoreActivityFields(before);
18138
+ this._restoreProgressFallbacks(progressFallbackBefore);
18014
18139
  if (this._viewStateBefore !== null) {
18015
18140
  this._viewState.restore(this._viewStateBefore);
18016
18141
  this._filterProjection = null;
@@ -18026,6 +18151,12 @@ var ScheduleState = class _ScheduleState {
18026
18151
  this._cache.visualOrderIds = null;
18027
18152
  this._hierarchy.markDirty();
18028
18153
  }
18154
+ _restoreProgressFallbacks(before) {
18155
+ for (const [activityId, value] of before) {
18156
+ if (value === null) this._progressFallback.delete(activityId);
18157
+ else this._progressFallback.set(activityId, value);
18158
+ }
18159
+ }
18029
18160
  _restoreCorrelatives(correlativeBefore) {
18030
18161
  for (const [id, before] of correlativeBefore) {
18031
18162
  const live = this._activities.get(id);
@@ -18239,13 +18370,15 @@ function buildHistoryChangeSet(changes) {
18239
18370
  links: linksWithoutAfter
18240
18371
  });
18241
18372
  }
18242
- function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks) {
18373
+ function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks, progressFallbackBefore, progressFallbackAfter) {
18243
18374
  return {
18244
18375
  changeSet,
18245
18376
  beforeSnap,
18246
18377
  beforeLinks: resetDerivedLinkSnapshots(beforeLinks),
18247
18378
  afterSnap,
18248
- afterLinks: resetDerivedLinkSnapshots(afterLinks)
18379
+ afterLinks: resetDerivedLinkSnapshots(afterLinks),
18380
+ progressFallbackBefore,
18381
+ progressFallbackAfter
18249
18382
  };
18250
18383
  }
18251
18384
  function resetDerivedLinkSnapshots(snapshots) {
@@ -18548,6 +18681,10 @@ function applyChangeSetSide(state, entry, side) {
18548
18681
  );
18549
18682
  }
18550
18683
  }
18684
+ const progressFallbacks = side === "before" ? entry.progressFallbackBefore : entry.progressFallbackAfter;
18685
+ for (const [activityId, value] of progressFallbacks ?? []) {
18686
+ state.setProgressFallback(activityId, value);
18687
+ }
18551
18688
  }
18552
18689
 
18553
18690
  // src/dispatch/undo/undo-recorder.ts
@@ -20439,6 +20576,7 @@ async function runInitialPasses(deps) {
20439
20576
  normalizeLoadedConstraintDates(state);
20440
20577
  recomputeCanonicalRealWork(state);
20441
20578
  if (skipAutoSchedule) {
20579
+ recomputeAllProgressRollup(state);
20442
20580
  if (now) {
20443
20581
  applyExpectedProgressLive(state, now);
20444
20582
  applyStatusPass(state, sector.statusCriteria);
@@ -20450,6 +20588,7 @@ async function runInitialPasses(deps) {
20450
20588
  normalizeMilestoneConstraintDatesForDisplay(state);
20451
20589
  recomputeSkippedLeafEnds(state);
20452
20590
  await updateParentBoundsFromChildren(state, void 0, false);
20591
+ recomputeAllProgressRollup(state);
20453
20592
  if (now) {
20454
20593
  applyExpectedProgressLive(state, now);
20455
20594
  applyStatusPass(state, sector.statusCriteria);
@@ -21284,6 +21423,7 @@ var ScheduleCore = class _ScheduleCore {
21284
21423
  this.coreRuntime.state.beginWriteCapture();
21285
21424
  this.coreRuntime.customIdTracker.beginCustomIdTransaction();
21286
21425
  let result;
21426
+ let progressFallbackBefore;
21287
21427
  try {
21288
21428
  result = await performDispatch(action, options, {
21289
21429
  adapter: this.coreRuntime.state,
@@ -21304,6 +21444,10 @@ var ScheduleCore = class _ScheduleCore {
21304
21444
  )?.id ?? null,
21305
21445
  now: this.coreRuntime.clock ? endOfLocalDay(this.coreRuntime.clock()) : null
21306
21446
  });
21447
+ const fallbackBefore = this.coreRuntime.state.peekWriteCapture()?.progressFallbackBefore;
21448
+ if (fallbackBefore && fallbackBefore.size > 0) {
21449
+ progressFallbackBefore = new Map(fallbackBefore);
21450
+ }
21307
21451
  if (!result.ok) this._rollback(generatorSnapshot);
21308
21452
  } catch (error) {
21309
21453
  this._rollback(generatorSnapshot);
@@ -21317,13 +21461,21 @@ var ScheduleCore = class _ScheduleCore {
21317
21461
  this.coreRuntime.state,
21318
21462
  result.changes
21319
21463
  );
21464
+ const progressFallbackAfter = progressFallbackBefore ? new Map(
21465
+ Array.from(progressFallbackBefore.keys(), (activityId) => [
21466
+ activityId,
21467
+ this.coreRuntime.state.getProgressFallback(activityId)
21468
+ ])
21469
+ ) : void 0;
21320
21470
  this._undo.record(
21321
21471
  buildUndoEntry(
21322
21472
  buildHistoryChangeSet(result.changes),
21323
21473
  result.__beforeSnap,
21324
21474
  result.__beforeLinks,
21325
21475
  created.afterSnap,
21326
- created.afterLinks
21476
+ created.afterLinks,
21477
+ progressFallbackBefore,
21478
+ progressFallbackAfter
21327
21479
  ),
21328
21480
  computeCoalesceKey(action),
21329
21481
  Date.now()