@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.js CHANGED
@@ -3287,6 +3287,84 @@ function roundProgressPerLevel(value) {
3287
3287
  return Number(value.toFixed(2));
3288
3288
  }
3289
3289
 
3290
+ // src/propagations/upward/progress-rollup.ts
3291
+ function recomputeAllProgressRollup(adapter) {
3292
+ for (const parentId of parentsDeepestFirst(adapter)) {
3293
+ rollupParent(parentId, adapter);
3294
+ }
3295
+ }
3296
+ function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
3297
+ for (const parentId of parentIdsDeepestFirst) {
3298
+ rollupParent(parentId, adapter);
3299
+ }
3300
+ }
3301
+ function parentsDeepestFirst(adapter) {
3302
+ const parents = /* @__PURE__ */ new Set();
3303
+ adapter.forEachActivity((_activity, id) => {
3304
+ if (adapter.getChildren(id).length > 0) parents.add(id);
3305
+ });
3306
+ const depthById = /* @__PURE__ */ new Map();
3307
+ for (const id of parents) depthById.set(id, depthOf(id, adapter));
3308
+ return [...parents].sort(
3309
+ (a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
3310
+ );
3311
+ }
3312
+ function depthOf(id, adapter) {
3313
+ let depth = 0;
3314
+ let current = id;
3315
+ while (current && current !== "0") {
3316
+ if (!adapter.getActivity(current)) break;
3317
+ depth += 1;
3318
+ current = adapter.getParentId(current);
3319
+ }
3320
+ return depth;
3321
+ }
3322
+ function rollupParent(parentId, adapter) {
3323
+ const childIds = adapter.getChildren(parentId);
3324
+ if (childIds.length === 0) return;
3325
+ const children = [];
3326
+ for (const childId of childIds) {
3327
+ const child = adapter.getActivity(childId);
3328
+ if (!child) continue;
3329
+ children.push({
3330
+ progress: Number(child.progress ?? 0),
3331
+ ponderator: Number(child.ponderator ?? 0)
3332
+ });
3333
+ }
3334
+ applyWeightedProgressRollup(parentId, children, adapter);
3335
+ }
3336
+ function applyWeightedProgressRollup(parentId, children, adapter) {
3337
+ const parent = adapter.getActivity(parentId);
3338
+ if (!parent) return;
3339
+ const rollup = computeWeightedProgressRollup(children);
3340
+ if (rollup === null) {
3341
+ const fallback = adapter.getProgressFallback(parentId);
3342
+ if (fallback !== null) {
3343
+ adapter.setActivityField(parentId, COLUMN.PROGRESS, fallback);
3344
+ }
3345
+ return;
3346
+ }
3347
+ if (adapter.getProgressFallback(parentId) === null) {
3348
+ adapter.setProgressFallback(parentId, Number(parent.progress ?? 0));
3349
+ }
3350
+ adapter.setActivityField(
3351
+ parentId,
3352
+ COLUMN.PROGRESS,
3353
+ roundProgressPerLevel(rollup)
3354
+ );
3355
+ }
3356
+ function setExplicitSummaryProgressFallbacks(activityId, progress, adapter) {
3357
+ const pending = [activityId];
3358
+ while (pending.length > 0) {
3359
+ const currentId = pending.pop();
3360
+ if (currentId === void 0) continue;
3361
+ const children = adapter.getChildren(currentId);
3362
+ if (children.length === 0) continue;
3363
+ adapter.setProgressFallback(currentId, progress);
3364
+ pending.push(...children);
3365
+ }
3366
+ }
3367
+
3290
3368
  // src/columns/real-work/compute.ts
3291
3369
  function computeLeafRealWork(workHours, progress) {
3292
3370
  return (Number(workHours) || 0) * (Number(progress) || 0) / 100;
@@ -3402,16 +3480,8 @@ function recomputeParentFromChildren(parentId, adapter, progressMode = "freeze-w
3402
3480
  adapter.setActivityField(parentId, "startDate", newStart);
3403
3481
  adapter.setActivityField(parentId, "endDate", newEnd);
3404
3482
  adapter.setActivityField(parentId, "durationHours", durationHours);
3405
- const progressRollup = computeWeightedProgressRollup(
3406
- aggregate.weightedChildren
3407
- );
3408
- const shouldWriteProgress = progressMode !== "skip" && (progressRollup !== null || progressMode === "zero-when-no-contribution");
3409
- if (shouldWriteProgress) {
3410
- adapter.setActivityField(
3411
- parentId,
3412
- "progress",
3413
- roundProgressPerLevel(progressRollup ?? 0)
3414
- );
3483
+ if (progressMode !== "skip") {
3484
+ applyWeightedProgressRollup(parentId, aggregate.weightedChildren, adapter);
3415
3485
  }
3416
3486
  if (recomputeRealWork) {
3417
3487
  adapter.setActivityField(parentId, "realWorkHours", aggregate.realWorkSum);
@@ -3434,10 +3504,10 @@ function collectParentIds(adapter) {
3434
3504
  }
3435
3505
  function computeDepths(ids, adapter) {
3436
3506
  const depths = /* @__PURE__ */ new Map();
3437
- for (const id of ids) depths.set(id, depthOf(id, adapter));
3507
+ for (const id of ids) depths.set(id, depthOf2(id, adapter));
3438
3508
  return depths;
3439
3509
  }
3440
- function depthOf(id, adapter) {
3510
+ function depthOf2(id, adapter) {
3441
3511
  let depth = 0;
3442
3512
  let current = id;
3443
3513
  while (current && !isRootParent(current)) {
@@ -3920,6 +3990,7 @@ function buildAncestorRollupCascade(activity, newValue, hierarchy) {
3920
3990
  const mutations = [];
3921
3991
  for (const id of chain) {
3922
3992
  const rollup = computeWeightedProgress(id, overlay, hierarchy);
3993
+ if (rollup === null) continue;
3923
3994
  overlay.set(id, rollup);
3924
3995
  mutations.push({
3925
3996
  activityId: id,
@@ -3933,7 +4004,8 @@ function computeWeightedProgress(parentId, overlay, hierarchy) {
3933
4004
  progress: overlay.has(child.id) ? overlay.get(child.id) : child.progress,
3934
4005
  ponderator: child.ponderator ?? 0
3935
4006
  }));
3936
- return Number((computeWeightedProgressRollup(children) ?? 0).toFixed(2));
4007
+ const rollup = computeWeightedProgressRollup(children);
4008
+ return rollup === null ? null : Number(rollup.toFixed(2));
3937
4009
  }
3938
4010
  function buildRecursiveTrackingEvents(activity, newValue) {
3939
4011
  return [
@@ -9884,24 +9956,82 @@ function resolveDerivedPasses(action, autoSchedule, options) {
9884
9956
 
9885
9957
  // src/dispatch/shared/post-mutation.ts
9886
9958
  async function runPostMutation(deps, args) {
9887
- const passes = resolvePasses(args);
9959
+ const progressInvalidation = resolveProgressInvalidation(deps.adapter);
9960
+ const passes = resolvePasses(args, progressInvalidation);
9888
9961
  if (passes.has(DERIVED_PASS.AUTOSCHEDULE)) {
9889
9962
  await refreshMutatedParentBounds(deps.adapter, args);
9890
9963
  }
9891
9964
  const schedule = passes.has(DERIVED_PASS.AUTOSCHEDULE) ? await runAutoschedule(deps, args.autoscheduleFrom) : emptySchedule();
9892
- await rollUpParentBounds(deps.adapter, args, schedule.scheduledIds, passes);
9965
+ await rollUpParentBounds(
9966
+ deps.adapter,
9967
+ args,
9968
+ schedule.scheduledIds,
9969
+ passes,
9970
+ progressInvalidation
9971
+ );
9893
9972
  await runDerivedRecomputes(deps, passes, args.now);
9894
9973
  return schedule;
9895
9974
  }
9896
- function resolvePasses(args) {
9975
+ function resolvePasses(args, progressInvalidation) {
9897
9976
  const requested = args.autoscheduleFrom !== null;
9898
9977
  const ran = !args.options.skipAutoSchedule && requested;
9899
9978
  const passes = new Set(
9900
9979
  resolveDerivedPasses(args.action, { ran }, args.options)
9901
9980
  );
9902
- if (args.recomputeParentProgress) passes.add(DERIVED_PASS.PARENT_PROGRESS);
9981
+ if (args.recomputeParentProgress || progressInvalidation.affectedParents.size > 0) {
9982
+ passes.add(DERIVED_PASS.PARENT_PROGRESS);
9983
+ }
9903
9984
  return passes;
9904
9985
  }
9986
+ function resolveProgressInvalidation(adapter) {
9987
+ const affectedParents = /* @__PURE__ */ new Set();
9988
+ const dirtySeeds = /* @__PURE__ */ new Set();
9989
+ const journal = adapter.peekWriteCapture();
9990
+ if (!journal) return { affectedParents, dirtySeeds };
9991
+ const affectParent = (parentId) => {
9992
+ if (parentId === null || isRootParent(parentId)) return;
9993
+ const normalized2 = String(parentId);
9994
+ affectedParents.add(normalized2);
9995
+ const childId = adapter.getChildren(normalized2)[0];
9996
+ if (childId !== void 0) dirtySeeds.add(childId);
9997
+ };
9998
+ collectStructuralProgressInvalidations(adapter, journal.ops, affectParent);
9999
+ collectFieldProgressInvalidations(
10000
+ adapter,
10001
+ journal.before,
10002
+ dirtySeeds,
10003
+ affectParent
10004
+ );
10005
+ return { affectedParents, dirtySeeds };
10006
+ }
10007
+ function collectStructuralProgressInvalidations(adapter, operations, affectParent) {
10008
+ for (const operation of operations) {
10009
+ if (operation.kind === "insert") {
10010
+ const inserted = adapter.getActivity(operation.activityId);
10011
+ if (inserted) affectParent(inserted.parentId);
10012
+ } else if (operation.kind === "remove") {
10013
+ affectParent(operation.before.parentId);
10014
+ }
10015
+ }
10016
+ }
10017
+ function collectFieldProgressInvalidations(adapter, beforeById, dirtySeeds, affectParent) {
10018
+ for (const [activityId, before] of beforeById) {
10019
+ const after = adapter.getActivity(activityId);
10020
+ if (!after) continue;
10021
+ const progressChanged = !Object.is(before.progress, after.progress);
10022
+ const ponderatorChanged = !Object.is(before.ponderator, after.ponderator);
10023
+ const parentChanged = !Object.is(before.parentId, after.parentId);
10024
+ if (progressChanged || ponderatorChanged) {
10025
+ affectParent(after.parentId);
10026
+ dirtySeeds.add(String(activityId));
10027
+ }
10028
+ if (parentChanged) {
10029
+ affectParent(before.parentId);
10030
+ affectParent(after.parentId);
10031
+ dirtySeeds.add(String(activityId));
10032
+ }
10033
+ }
10034
+ }
9905
10035
  async function runAutoschedule(deps, autoscheduleFrom) {
9906
10036
  const options = autoscheduleFrom === "roots" ? {} : { triggerId: autoscheduleFrom };
9907
10037
  const result = await deps.scheduler.schedule(options);
@@ -9929,18 +10059,36 @@ async function refreshMutatedParentBounds(adapter, args) {
9929
10059
  if (mutated.size === 0) return;
9930
10060
  await updateParentBoundsFromChildren(adapter, mutated, false);
9931
10061
  }
9932
- async function rollUpParentBounds(adapter, args, scheduledIds, passes) {
10062
+ async function rollUpParentBounds(adapter, args, scheduledIds, passes, progressInvalidation) {
10063
+ if (passes.has(DERIVED_PASS.PARENT_PROGRESS)) {
10064
+ restoreDemotedProgressFallbacks(
10065
+ adapter,
10066
+ progressInvalidation.affectedParents
10067
+ );
10068
+ }
9933
10069
  const dirty = args.collectDirty ? args.collectDirty(scheduledIds) : collectDirtyForStructural(args.recomputeParentsFrom, scheduledIds);
10070
+ for (const activityId of progressInvalidation.dirtySeeds) {
10071
+ dirty.add(activityId);
10072
+ }
9934
10073
  await updateParentBoundsFromChildren(
9935
10074
  adapter,
9936
10075
  dirty,
9937
10076
  passes.has(DERIVED_PASS.PARENT_PROGRESS),
9938
10077
  {
9939
10078
  recomputeRealWork: passes.has(DERIVED_PASS.REAL_WORK),
9940
- progressMode: args.recomputeParentProgress ? "zero-when-no-contribution" : "freeze-when-no-contribution"
10079
+ progressMode: "freeze-when-no-contribution"
9941
10080
  }
9942
10081
  );
9943
10082
  }
10083
+ function restoreDemotedProgressFallbacks(adapter, affectedParents) {
10084
+ for (const parentId of affectedParents) {
10085
+ if (adapter.hasChildren(parentId)) continue;
10086
+ const fallback = adapter.getProgressFallback(parentId);
10087
+ if (fallback === null) continue;
10088
+ adapter.setActivityField(parentId, "progress", fallback);
10089
+ adapter.setProgressFallback(parentId, null);
10090
+ }
10091
+ }
9944
10092
  async function runDerivedRecomputes(deps, passes, now) {
9945
10093
  if (passes.has(DERIVED_PASS.EXPECTED_PROGRESS) && now !== null) {
9946
10094
  if (hasActiveBaseline(deps.adapter)) {
@@ -11169,7 +11317,6 @@ function buildParentMutations(input) {
11169
11317
  if ((input.promotionSource ?? "create") === "create") {
11170
11318
  fields.constraintType = CONSTRAINT_TYPE.ASAP;
11171
11319
  fields.constraintDate = null;
11172
- fields.progress = 0;
11173
11320
  }
11174
11321
  }
11175
11322
  return {
@@ -12322,60 +12469,6 @@ function dispatchSirSync(action, deps) {
12322
12469
  };
12323
12470
  }
12324
12471
 
12325
- // src/propagations/upward/progress-rollup.ts
12326
- function recomputeAllProgressRollup(adapter) {
12327
- for (const parentId of parentsDeepestFirst(adapter)) {
12328
- rollupParent(parentId, adapter);
12329
- }
12330
- }
12331
- function recomputeProgressRollupForParents(parentIdsDeepestFirst, adapter) {
12332
- for (const parentId of parentIdsDeepestFirst) {
12333
- rollupParent(parentId, adapter);
12334
- }
12335
- }
12336
- function parentsDeepestFirst(adapter) {
12337
- const parents = /* @__PURE__ */ new Set();
12338
- adapter.forEachActivity((_activity, id) => {
12339
- if (adapter.getChildren(id).length > 0) parents.add(id);
12340
- });
12341
- const depthById = /* @__PURE__ */ new Map();
12342
- for (const id of parents) depthById.set(id, depthOf2(id, adapter));
12343
- return [...parents].sort(
12344
- (a, b) => (depthById.get(b) ?? 0) - (depthById.get(a) ?? 0)
12345
- );
12346
- }
12347
- function depthOf2(id, adapter) {
12348
- let depth = 0;
12349
- let current = id;
12350
- while (current && current !== "0") {
12351
- if (!adapter.getActivity(current)) break;
12352
- depth += 1;
12353
- current = adapter.getParentId(current);
12354
- }
12355
- return depth;
12356
- }
12357
- function rollupParent(parentId, adapter) {
12358
- const childIds = adapter.getChildren(parentId);
12359
- if (childIds.length === 0) return;
12360
- const children = [];
12361
- for (const childId of childIds) {
12362
- const child = adapter.getActivity(childId);
12363
- if (!child) continue;
12364
- children.push({
12365
- progress: Number(child.progress ?? 0),
12366
- ponderator: Number(child.ponderator ?? 0)
12367
- });
12368
- }
12369
- const rollup = computeWeightedProgressRollup(children);
12370
- if (rollup !== null) {
12371
- adapter.setActivityField(
12372
- parentId,
12373
- COLUMN.PROGRESS,
12374
- roundProgressPerLevel(rollup)
12375
- );
12376
- }
12377
- }
12378
-
12379
12472
  // src/dispatch/handlers/persistence-acknowledge.ts
12380
12473
  function persistedOwnersOf(entities) {
12381
12474
  const owners = /* @__PURE__ */ new Map();
@@ -13442,6 +13535,11 @@ async function dispatchActivitySetProgress(action, options, deps) {
13442
13535
  const touchedIds = collectTouchedIds(action.activityId, changes);
13443
13536
  const beforeSnap = await snapshotActivities(adapter, touchedIds);
13444
13537
  applyFieldChanges(adapter, action.activityId, changes);
13538
+ setExplicitSummaryProgressFallbacks(
13539
+ action.activityId,
13540
+ action.newValue,
13541
+ adapter
13542
+ );
13445
13543
  runPostProcessorsOnAdapter(
13446
13544
  action.activityId,
13447
13545
  changes.postProcessors ?? [],
@@ -17305,7 +17403,8 @@ var WriteCapture = class {
17305
17403
  ops: [],
17306
17404
  linkFieldCaptured: /* @__PURE__ */ new Set(),
17307
17405
  correlativeBefore: /* @__PURE__ */ new Map(),
17308
- scheduledBefore: /* @__PURE__ */ new Map()
17406
+ scheduledBefore: /* @__PURE__ */ new Map(),
17407
+ progressFallbackBefore: /* @__PURE__ */ new Map()
17309
17408
  };
17310
17409
  }
17311
17410
  peek() {
@@ -17368,6 +17467,11 @@ var WriteCapture = class {
17368
17467
  before: cloneLink(current)
17369
17468
  });
17370
17469
  }
17470
+ noteProgressFallback(activityId, current) {
17471
+ const journal = this._journal;
17472
+ if (!journal || journal.progressFallbackBefore.has(activityId)) return;
17473
+ journal.progressFallbackBefore.set(activityId, current);
17474
+ }
17371
17475
  };
17372
17476
  function cloneLink(link) {
17373
17477
  return { ...link };
@@ -17613,6 +17717,7 @@ var ScheduleState = class _ScheduleState {
17613
17717
  _activities = /* @__PURE__ */ new Map();
17614
17718
  _lastStartDate = /* @__PURE__ */ new Map();
17615
17719
  _promotionSnapshot = /* @__PURE__ */ new Map();
17720
+ _progressFallback = /* @__PURE__ */ new Map();
17616
17721
  _links = /* @__PURE__ */ new Map();
17617
17722
  _outgoing = /* @__PURE__ */ new Map();
17618
17723
  _incoming = /* @__PURE__ */ new Map();
@@ -17673,6 +17778,7 @@ var ScheduleState = class _ScheduleState {
17673
17778
  cloneDomainValue(snapshot)
17674
17779
  ])
17675
17780
  );
17781
+ fork._progressFallback = new Map(this._progressFallback);
17676
17782
  fork._flags = cloneDomainValue(this._flags);
17677
17783
  fork._filterProjection = cloneDomainValue(this._filterProjection);
17678
17784
  return fork;
@@ -17726,6 +17832,17 @@ var ScheduleState = class _ScheduleState {
17726
17832
  this._capturePromotionSnapshotOnce();
17727
17833
  this._promotionSnapshot.set(String(activityId), snapshot);
17728
17834
  }
17835
+ getProgressFallback(activityId) {
17836
+ return this._progressFallback.get(String(activityId)) ?? null;
17837
+ }
17838
+ setProgressFallback(activityId, value) {
17839
+ const key = String(activityId);
17840
+ const current = this._progressFallback.get(key) ?? null;
17841
+ if (Object.is(current, value)) return;
17842
+ this._writeCapture.noteProgressFallback(key, current);
17843
+ if (value === null) this._progressFallback.delete(key);
17844
+ else this._progressFallback.set(key, value);
17845
+ }
17729
17846
  _capturePromotionSnapshotOnce() {
17730
17847
  if (this._writeCapture.peek() === null) return;
17731
17848
  if (this._promotionSnapshotBefore === null) {
@@ -17976,6 +18093,7 @@ var ScheduleState = class _ScheduleState {
17976
18093
  const activity = this.getActivity(activityId);
17977
18094
  if (activity) this._writeCapture.noteRemove(String(activityId), activity);
17978
18095
  const key = String(activityId);
18096
+ this.setProgressFallback(key, null);
17979
18097
  if (this._viewState.isChecked(key) || !this._viewState.isVisible(key)) {
17980
18098
  this._captureViewStateOnce();
17981
18099
  }
@@ -18000,7 +18118,13 @@ var ScheduleState = class _ScheduleState {
18000
18118
  restoreFromCapture() {
18001
18119
  const journal = this._writeCapture.peek();
18002
18120
  if (!journal) return;
18003
- const { ops, before, correlativeBefore, scheduledBefore } = journal;
18121
+ const {
18122
+ ops,
18123
+ before,
18124
+ correlativeBefore,
18125
+ scheduledBefore,
18126
+ progressFallbackBefore
18127
+ } = journal;
18004
18128
  this._undoLinkAdds(ops);
18005
18129
  this._undoInserts(ops);
18006
18130
  this._reInsertRemovedActivities(ops);
@@ -18009,6 +18133,7 @@ var ScheduleState = class _ScheduleState {
18009
18133
  this._restoreCorrelatives(correlativeBefore);
18010
18134
  this._restoreActivityFields(scheduledBefore);
18011
18135
  this._restoreActivityFields(before);
18136
+ this._restoreProgressFallbacks(progressFallbackBefore);
18012
18137
  if (this._viewStateBefore !== null) {
18013
18138
  this._viewState.restore(this._viewStateBefore);
18014
18139
  this._filterProjection = null;
@@ -18024,6 +18149,12 @@ var ScheduleState = class _ScheduleState {
18024
18149
  this._cache.visualOrderIds = null;
18025
18150
  this._hierarchy.markDirty();
18026
18151
  }
18152
+ _restoreProgressFallbacks(before) {
18153
+ for (const [activityId, value] of before) {
18154
+ if (value === null) this._progressFallback.delete(activityId);
18155
+ else this._progressFallback.set(activityId, value);
18156
+ }
18157
+ }
18027
18158
  _restoreCorrelatives(correlativeBefore) {
18028
18159
  for (const [id, before] of correlativeBefore) {
18029
18160
  const live = this._activities.get(id);
@@ -18237,13 +18368,15 @@ function buildHistoryChangeSet(changes) {
18237
18368
  links: linksWithoutAfter
18238
18369
  });
18239
18370
  }
18240
- function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks) {
18371
+ function buildUndoEntry(changeSet, beforeSnap, beforeLinks, afterSnap, afterLinks, progressFallbackBefore, progressFallbackAfter) {
18241
18372
  return {
18242
18373
  changeSet,
18243
18374
  beforeSnap,
18244
18375
  beforeLinks: resetDerivedLinkSnapshots(beforeLinks),
18245
18376
  afterSnap,
18246
- afterLinks: resetDerivedLinkSnapshots(afterLinks)
18377
+ afterLinks: resetDerivedLinkSnapshots(afterLinks),
18378
+ progressFallbackBefore,
18379
+ progressFallbackAfter
18247
18380
  };
18248
18381
  }
18249
18382
  function resetDerivedLinkSnapshots(snapshots) {
@@ -18546,6 +18679,10 @@ function applyChangeSetSide(state, entry, side) {
18546
18679
  );
18547
18680
  }
18548
18681
  }
18682
+ const progressFallbacks = side === "before" ? entry.progressFallbackBefore : entry.progressFallbackAfter;
18683
+ for (const [activityId, value] of progressFallbacks ?? []) {
18684
+ state.setProgressFallback(activityId, value);
18685
+ }
18549
18686
  }
18550
18687
 
18551
18688
  // src/dispatch/undo/undo-recorder.ts
@@ -20437,6 +20574,7 @@ async function runInitialPasses(deps) {
20437
20574
  normalizeLoadedConstraintDates(state);
20438
20575
  recomputeCanonicalRealWork(state);
20439
20576
  if (skipAutoSchedule) {
20577
+ recomputeAllProgressRollup(state);
20440
20578
  if (now) {
20441
20579
  applyExpectedProgressLive(state, now);
20442
20580
  applyStatusPass(state, sector.statusCriteria);
@@ -20448,6 +20586,7 @@ async function runInitialPasses(deps) {
20448
20586
  normalizeMilestoneConstraintDatesForDisplay(state);
20449
20587
  recomputeSkippedLeafEnds(state);
20450
20588
  await updateParentBoundsFromChildren(state, void 0, false);
20589
+ recomputeAllProgressRollup(state);
20451
20590
  if (now) {
20452
20591
  applyExpectedProgressLive(state, now);
20453
20592
  applyStatusPass(state, sector.statusCriteria);
@@ -21282,6 +21421,7 @@ var ScheduleCore = class _ScheduleCore {
21282
21421
  this.coreRuntime.state.beginWriteCapture();
21283
21422
  this.coreRuntime.customIdTracker.beginCustomIdTransaction();
21284
21423
  let result;
21424
+ let progressFallbackBefore;
21285
21425
  try {
21286
21426
  result = await performDispatch(action, options, {
21287
21427
  adapter: this.coreRuntime.state,
@@ -21302,6 +21442,10 @@ var ScheduleCore = class _ScheduleCore {
21302
21442
  )?.id ?? null,
21303
21443
  now: this.coreRuntime.clock ? endOfLocalDay(this.coreRuntime.clock()) : null
21304
21444
  });
21445
+ const fallbackBefore = this.coreRuntime.state.peekWriteCapture()?.progressFallbackBefore;
21446
+ if (fallbackBefore && fallbackBefore.size > 0) {
21447
+ progressFallbackBefore = new Map(fallbackBefore);
21448
+ }
21305
21449
  if (!result.ok) this._rollback(generatorSnapshot);
21306
21450
  } catch (error) {
21307
21451
  this._rollback(generatorSnapshot);
@@ -21315,13 +21459,21 @@ var ScheduleCore = class _ScheduleCore {
21315
21459
  this.coreRuntime.state,
21316
21460
  result.changes
21317
21461
  );
21462
+ const progressFallbackAfter = progressFallbackBefore ? new Map(
21463
+ Array.from(progressFallbackBefore.keys(), (activityId) => [
21464
+ activityId,
21465
+ this.coreRuntime.state.getProgressFallback(activityId)
21466
+ ])
21467
+ ) : void 0;
21318
21468
  this._undo.record(
21319
21469
  buildUndoEntry(
21320
21470
  buildHistoryChangeSet(result.changes),
21321
21471
  result.__beforeSnap,
21322
21472
  result.__beforeLinks,
21323
21473
  created.afterSnap,
21324
- created.afterLinks
21474
+ created.afterLinks,
21475
+ progressFallbackBefore,
21476
+ progressFallbackAfter
21325
21477
  ),
21326
21478
  computeCoalesceKey(action),
21327
21479
  Date.now()