@outbuild-company/schedule-core 1.9.0 → 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/README.md +18 -71
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +395 -725
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -167
- package/dist/index.d.ts +0 -167
- package/dist/index.js +395 -725
- package/dist/index.js.map +1 -1
- package/package.json +2 -9
package/dist/index.d.cts
CHANGED
|
@@ -134,13 +134,6 @@ interface CoreActivity {
|
|
|
134
134
|
recursiveDurationHours: number;
|
|
135
135
|
isCritical: boolean;
|
|
136
136
|
freeSlackHours: number | null;
|
|
137
|
-
/**
|
|
138
|
-
* Días de calendario crudos entre start y end (incluye no laborables). Es una
|
|
139
|
-
* columna del grid, así que la posee el core (decisión del owner 2026-08-03):
|
|
140
|
-
* estado derivado que el core mantiene al nacer la actividad y al escribir
|
|
141
|
-
* start/end/type (`internal/state/calendar-duration.ts`), y que por eso fluye
|
|
142
|
-
* solo por vistas, ChangeSets y undo. Milestone → 0; fechas inválidas → null.
|
|
143
|
-
*/
|
|
144
137
|
calendarDuration?: number | null;
|
|
145
138
|
expectedProgress: number | null;
|
|
146
139
|
expectedProgressBaseline: number | null;
|
|
@@ -203,7 +196,6 @@ interface SectorMetadata {
|
|
|
203
196
|
updateDurationForPrimaveraEndDate?: boolean;
|
|
204
197
|
activityCreter?: ActivityCreter;
|
|
205
198
|
statusCriteria: StatusCriteria;
|
|
206
|
-
/** Declared by the loader input; never derived from the backend payload. */
|
|
207
199
|
ganttId: number | null;
|
|
208
200
|
}
|
|
209
201
|
interface EntityChange<T> {
|
|
@@ -318,28 +310,12 @@ interface FilterState {
|
|
|
318
310
|
}
|
|
319
311
|
|
|
320
312
|
interface OrderRule {
|
|
321
|
-
/**
|
|
322
|
-
* Deliberately FilterField, not an alias of it: the columns a user can sort by
|
|
323
|
-
* are the columns a user can filter by, and the filter's registry already
|
|
324
|
-
* resolves units, baseline snapshots and critical-path values for all of them.
|
|
325
|
-
* A second field vocabulary would drift from this one on the first new column.
|
|
326
|
-
*/
|
|
327
313
|
readonly field: FilterField;
|
|
328
314
|
readonly direction: 'asc' | 'desc';
|
|
329
315
|
}
|
|
330
|
-
/**
|
|
331
|
-
* The active ordering, as an ordered list of keys: rule 0 decides, rule 1 breaks
|
|
332
|
-
* its ties, and so on. An empty list means "no user ordering", which is stored
|
|
333
|
-
* as null rather than an empty state (mirroring isEmptyFilter).
|
|
334
|
-
*/
|
|
335
316
|
interface OrderState {
|
|
336
317
|
readonly rules: ReadonlyArray<OrderRule>;
|
|
337
318
|
}
|
|
338
|
-
/**
|
|
339
|
-
* One resequenced sibling group. Ordering is hierarchical: an activity only ever
|
|
340
|
-
* competes with its own siblings, so a change is expressed per parent rather
|
|
341
|
-
* than as a flat sequence over the whole schedule.
|
|
342
|
-
*/
|
|
343
319
|
interface BranchOrderChange {
|
|
344
320
|
readonly parentId: string;
|
|
345
321
|
readonly childIds: ReadonlyArray<string>;
|
|
@@ -412,12 +388,6 @@ type DispatchAction = {
|
|
|
412
388
|
kind: 'persistence-acknowledge';
|
|
413
389
|
activities?: ReadonlyArray<PersistedEntityIdentity>;
|
|
414
390
|
links?: ReadonlyArray<PersistedEntityIdentity>;
|
|
415
|
-
/**
|
|
416
|
-
* CP19 (ISSUE-070): valores que el backend normalizo al guardar (hoy solo
|
|
417
|
-
* progress). El motor los reconcilia — aplica los que difieren, ignora
|
|
418
|
-
* los iguales — para que el core refleje lo persistido. Sin undo: el
|
|
419
|
-
* acuse es clear-on-success y el tracker snapshotea despues.
|
|
420
|
-
*/
|
|
421
391
|
reconciledProgress?: ReadonlyArray<ReconciledActivityProgress>;
|
|
422
392
|
} | {
|
|
423
393
|
kind: 'baseline-apply';
|
|
@@ -497,14 +467,6 @@ type DispatchAction = {
|
|
|
497
467
|
kind: 'activity-set-progress';
|
|
498
468
|
activityId: ActivityId;
|
|
499
469
|
newValue: 0 | 100;
|
|
500
|
-
/**
|
|
501
|
-
* CP15 (ISSUE-066): el origen se DECLARA, no se adivina. 'action-button'
|
|
502
|
-
* es el unico origen con salvoconducto
|
|
503
|
-
* de negocio para actividades en Lookahead (espejo del flag
|
|
504
|
-
* progressChangedByActionButton que consume parseToUpdate en el
|
|
505
|
-
* backend; guia agents/progreso-lookahead.md). Sin origen declarado
|
|
506
|
-
* aplica el canEdit completo del pipeline.
|
|
507
|
-
*/
|
|
508
470
|
origin?: 'action-button';
|
|
509
471
|
eventSource?: string;
|
|
510
472
|
} | {
|
|
@@ -627,14 +589,6 @@ interface ChangeSet {
|
|
|
627
589
|
calendars: ReadonlyArray<EntityChange<Calendar>>;
|
|
628
590
|
trackingEvents: ReadonlyArray<TrackingEvent>;
|
|
629
591
|
viewState?: ReadonlyArray<ViewStateChange>;
|
|
630
|
-
/**
|
|
631
|
-
* Sibling groups whose display sequence changed, each already in final order.
|
|
632
|
-
* Carried per branch rather than as a flat sequence because ordering never
|
|
633
|
-
* reparents: the renderer assigns each array and repaints once.
|
|
634
|
-
*
|
|
635
|
-
* Absent when nothing resequenced. Never a partial answer: a branch listed
|
|
636
|
-
* here holds all of its children.
|
|
637
|
-
*/
|
|
638
592
|
order?: ReadonlyArray<BranchOrderChange>;
|
|
639
593
|
effects?: ReadonlyArray<ScheduleEffect>;
|
|
640
594
|
warnings?: ReadonlyArray<ConstraintWarning>;
|
|
@@ -667,15 +621,6 @@ interface BackendCalendarInput {
|
|
|
667
621
|
baseexceptiondays?: BackendCalendarExceptionInput[];
|
|
668
622
|
}
|
|
669
623
|
interface BackendActivityInput {
|
|
670
|
-
/**
|
|
671
|
-
* Persisted backend identity.
|
|
672
|
-
*
|
|
673
|
-
* Synthetic activities that have not been persisted yet use `null`.
|
|
674
|
-
* `unique_id` remains their stable local identity.
|
|
675
|
-
*
|
|
676
|
-
* A numeric zero is intentionally preserved as a numeric backend identity
|
|
677
|
-
* for compatibility with the certified proplanner-id/002 scenario.
|
|
678
|
-
*/
|
|
679
624
|
id: number | null;
|
|
680
625
|
unique_id: string;
|
|
681
626
|
parent_id: string;
|
|
@@ -814,29 +759,6 @@ declare class ScheduleCore {
|
|
|
814
759
|
private readonly _undo;
|
|
815
760
|
private _opQueue;
|
|
816
761
|
private _scheduleRevision;
|
|
817
|
-
/**
|
|
818
|
-
* Revision counting mutations that have been ADMITTED, whether or not they
|
|
819
|
-
* have changed anything yet. `_scheduleRevision` counts the ones that
|
|
820
|
-
* actually did.
|
|
821
|
-
*
|
|
822
|
-
* INVARIANT: `_pendingScheduleRevision >= _scheduleRevision`, and equality
|
|
823
|
-
* means no mutation is in flight.
|
|
824
|
-
*
|
|
825
|
-
* The two exist separately because the useful instant and the knowable
|
|
826
|
-
* instant are not the same one. A critical-path calculation becomes garbage
|
|
827
|
-
* the moment the next mutation is admitted, but whether that mutation is
|
|
828
|
-
* substantive is only knowable once its ChangeSet exists, which is hundreds
|
|
829
|
-
* of milliseconds later at project scale. Measured live on a 12268-activity
|
|
830
|
-
* project: the cancellation flag flipped 929 ms into a 930 ms calculation,
|
|
831
|
-
* 812 into 812 and 785 into 785, because the job's apply block queues behind
|
|
832
|
-
* the very dispatch whose completion cancels it. Cancellation and job end
|
|
833
|
-
* were the same event, so every discarded job ran the whole calculation.
|
|
834
|
-
*
|
|
835
|
-
* Splitting the counter buys the early signal without moving the meaning of
|
|
836
|
-
* `_scheduleRevision`, whose three readers (`isCriticalPathSettled`,
|
|
837
|
-
* `createDateGesturePreview` and the job's own `isCurrent`) are all written
|
|
838
|
-
* against "the state actually changed".
|
|
839
|
-
*/
|
|
840
762
|
private _pendingScheduleRevision;
|
|
841
763
|
private _criticalPathRevision;
|
|
842
764
|
private _activeCriticalPath;
|
|
@@ -851,13 +773,6 @@ declare class ScheduleCore {
|
|
|
851
773
|
getActivityView(id: ActivityId): Readonly<CoreActivity> | null;
|
|
852
774
|
createDateGesturePreview(gesture: DateGesture): DateGesturePreview;
|
|
853
775
|
getAllActivitiesView(): ReadonlyArray<Readonly<CoreActivity>>;
|
|
854
|
-
/**
|
|
855
|
-
* Read del plan de indent (ISSUE-080): los padres destino DISTINTOS bajo los
|
|
856
|
-
* que quedarían las actividades si se indentaran ahora. Es exactamente la
|
|
857
|
-
* planificación que ejecuta el handler (`planIndentMoves`, autoridad única),
|
|
858
|
-
* expuesta para que la frontera pueda correr el protocolo de conversión a
|
|
859
|
-
* madre (chequeo backend + modal) ANTES de despachar. Solo lecturas.
|
|
860
|
-
*/
|
|
861
776
|
getIndentTargetParentIds(activityIds: ReadonlyArray<ActivityId | string>): readonly string[];
|
|
862
777
|
getChildrenView(parentId: ActivityId | '0'): ReadonlyArray<Readonly<CoreActivity>>;
|
|
863
778
|
getLinkView(id: LinkId): Readonly<Link> | null;
|
|
@@ -884,53 +799,14 @@ declare class ScheduleCore {
|
|
|
884
799
|
getModifiedActivities(): ReadonlyArray<Readonly<CoreActivity>>;
|
|
885
800
|
getNewActivities(): ReadonlyArray<Readonly<CoreActivity>>;
|
|
886
801
|
hasUnsavedChanges(): boolean;
|
|
887
|
-
/** Read-only revision; moves once per substantive mutation. */
|
|
888
802
|
getScheduleRevision(): number;
|
|
889
803
|
getCanonicalDigest(): string;
|
|
890
804
|
createProjectionChangeSetFrom(source: ScheduleCore): ChangeSet;
|
|
891
805
|
getDeletedActivitiesSinceLastSave(): ReadonlyArray<Readonly<DeletedActivitySnapshot>>;
|
|
892
806
|
getDeletedLinksSinceLastSave(): ReadonlyArray<Readonly<DeletedLinkSnapshot>>;
|
|
893
807
|
private _enqueue;
|
|
894
|
-
/**
|
|
895
|
-
* Marks a mutation as admitted and invalidates the calculation in flight.
|
|
896
|
-
*
|
|
897
|
-
* Called BEFORE `_enqueue`, which is the point of the whole thing: the wait
|
|
898
|
-
* in the operation queue is part of the window a running calculation wastes,
|
|
899
|
-
* and it is the longest part of it when several mutations are already
|
|
900
|
-
* queued.
|
|
901
|
-
*
|
|
902
|
-
* `dispatchChangesSchedulingState` is a pure function of the action, so this
|
|
903
|
-
* decision needs no state and cannot be wrong about the action's nature. What
|
|
904
|
-
* it cannot know yet is whether the mutation will produce anything, which is
|
|
905
|
-
* what `_settleScheduleMutation` reconciles afterwards.
|
|
906
|
-
*/
|
|
907
808
|
private _beginScheduleMutation;
|
|
908
|
-
/** Undo and redo have no action to classify: reaching them IS the mutation. */
|
|
909
809
|
private _admitScheduleMutation;
|
|
910
|
-
/**
|
|
911
|
-
* Closes a mutation admitted by `_beginScheduleMutation`, on EVERY exit path.
|
|
912
|
-
*
|
|
913
|
-
* `changedState` false means the mutation was admitted and produced nothing
|
|
914
|
-
* (rejected, non-substantive, or rolled back). The pending revision walks
|
|
915
|
-
* back so the invariant holds and `isCriticalPathSettled` keeps telling the
|
|
916
|
-
* truth, and the calculation this mutation killed for nothing is re-armed.
|
|
917
|
-
*
|
|
918
|
-
* The re-arm goes through the queue and that is not incidental. Started
|
|
919
|
-
* outside it, the calculation would run immediately while the next queued
|
|
920
|
-
* mutation is still waiting, and that mutation would kill it again on
|
|
921
|
-
* admission: a cancel-and-restart treadmill burning a fresh project-wide deep
|
|
922
|
-
* copy per lap. Inside the queue the restart cannot happen until the queue
|
|
923
|
-
* drains, so at most one calculation is armed per settled mutation. The burst
|
|
924
|
-
* scenario will NOT catch a regression here, because there every dispatch
|
|
925
|
-
* succeeds and this path is never taken.
|
|
926
|
-
*
|
|
927
|
-
* It re-arms through `recomputeCriticalPath` rather than enqueueing the job
|
|
928
|
-
* directly, because the queue slot must NOT await the job: the job's own
|
|
929
|
-
* apply block needs a later slot on this same queue, so awaiting it from
|
|
930
|
-
* inside a slot deadlocks the core. `recomputeCriticalPath` already has the
|
|
931
|
-
* shape that returns the job's promise out of the slot instead of awaiting
|
|
932
|
-
* it, and it keeps `_criticalPathReady` pointing at the live calculation.
|
|
933
|
-
*/
|
|
934
810
|
private _settleScheduleMutation;
|
|
935
811
|
dispatch(action: DispatchAction, options?: DispatchOptions): Promise<DispatchResult>;
|
|
936
812
|
applyActivityBatch(action: ActivityBatchAction, options?: DispatchOptions): Promise<DispatchResult>;
|
|
@@ -942,51 +818,8 @@ declare class ScheduleCore {
|
|
|
942
818
|
isCriticalPathSettled(): boolean;
|
|
943
819
|
whenCriticalPathSettled(): Promise<void>;
|
|
944
820
|
private _withReappliedViewState;
|
|
945
|
-
private _recordRelativePlacementPin;
|
|
946
|
-
/**
|
|
947
|
-
* The single place the two view-state passes are chained. Dispatch, undo and
|
|
948
|
-
* redo all route through here: when this existed only inside the dispatch
|
|
949
|
-
* path, undo and redo reapplied the filter and forgot the order, so an edit
|
|
950
|
-
* that moved a row and was then undone left the row in its new position.
|
|
951
|
-
*
|
|
952
|
-
* The sequence between the passes is indifferent. Filter and order are
|
|
953
|
-
* orthogonal projections over the same tree — the filter decides which rows
|
|
954
|
-
* exist on screen and never reads the order; the order sequences every
|
|
955
|
-
* sibling group from the hierarchy index and never reads visibility. Either
|
|
956
|
-
* sequence produces the same ChangeSet.
|
|
957
|
-
*
|
|
958
|
-
* Both passes answer null while their state is inactive, so an unfiltered,
|
|
959
|
-
* unsorted schedule pays two property reads.
|
|
960
|
-
*/
|
|
961
821
|
private _reapplyViewState;
|
|
962
|
-
/**
|
|
963
|
-
* Emits `order` for the branches this mutation resequenced, when no user order
|
|
964
|
-
* is active.
|
|
965
|
-
*
|
|
966
|
-
* The contract is that `order` reports a CHANGED SEQUENCE, not the presence of
|
|
967
|
-
* a sort. Tying emission to the cause instead of the effect is what produced
|
|
968
|
-
* the undo bug and, later, the reparent ones: without an active order a move,
|
|
969
|
-
* an indent, an outdent or the undo of any of them rearranged rows and said
|
|
970
|
-
* nothing, so an incremental consumer kept the old sequence. The undo of a
|
|
971
|
-
* reparent was the worst of them — it carried neither `order` nor a single
|
|
972
|
-
* correlativeId, so the position was not recoverable by any consumer.
|
|
973
|
-
*
|
|
974
|
-
* The touched branches are derived from the ChangeSet rather than accumulated
|
|
975
|
-
* in the state: an entity whose parentId or correlativeId moved, plus the
|
|
976
|
-
* parents of created and deleted rows, is exactly the set of branches whose
|
|
977
|
-
* sequence can differ. That keeps this linear in the blast radius, adds
|
|
978
|
-
* nothing to the write path, and cannot leak across dispatches.
|
|
979
|
-
*/
|
|
980
822
|
private _emitTouchedBranchOrder;
|
|
981
|
-
/**
|
|
982
|
-
* Re-sequences the grid after any mutation that could have changed a value the
|
|
983
|
-
* active order sorts by. Ordering is a view over the data, so an edit that
|
|
984
|
-
* moves a row past its sibling must move the row, exactly as the filter makes
|
|
985
|
-
* a no-longer-matching row disappear.
|
|
986
|
-
*
|
|
987
|
-
* Production only re-sorts after a bar drag; diverging from that is a
|
|
988
|
-
* deliberate product decision, not an oversight.
|
|
989
|
-
*/
|
|
990
823
|
private _reapplyActiveOrder;
|
|
991
824
|
private _reapplyActiveFilter;
|
|
992
825
|
private _recordScheduleMutation;
|
package/dist/index.d.ts
CHANGED
|
@@ -134,13 +134,6 @@ interface CoreActivity {
|
|
|
134
134
|
recursiveDurationHours: number;
|
|
135
135
|
isCritical: boolean;
|
|
136
136
|
freeSlackHours: number | null;
|
|
137
|
-
/**
|
|
138
|
-
* Días de calendario crudos entre start y end (incluye no laborables). Es una
|
|
139
|
-
* columna del grid, así que la posee el core (decisión del owner 2026-08-03):
|
|
140
|
-
* estado derivado que el core mantiene al nacer la actividad y al escribir
|
|
141
|
-
* start/end/type (`internal/state/calendar-duration.ts`), y que por eso fluye
|
|
142
|
-
* solo por vistas, ChangeSets y undo. Milestone → 0; fechas inválidas → null.
|
|
143
|
-
*/
|
|
144
137
|
calendarDuration?: number | null;
|
|
145
138
|
expectedProgress: number | null;
|
|
146
139
|
expectedProgressBaseline: number | null;
|
|
@@ -203,7 +196,6 @@ interface SectorMetadata {
|
|
|
203
196
|
updateDurationForPrimaveraEndDate?: boolean;
|
|
204
197
|
activityCreter?: ActivityCreter;
|
|
205
198
|
statusCriteria: StatusCriteria;
|
|
206
|
-
/** Declared by the loader input; never derived from the backend payload. */
|
|
207
199
|
ganttId: number | null;
|
|
208
200
|
}
|
|
209
201
|
interface EntityChange<T> {
|
|
@@ -318,28 +310,12 @@ interface FilterState {
|
|
|
318
310
|
}
|
|
319
311
|
|
|
320
312
|
interface OrderRule {
|
|
321
|
-
/**
|
|
322
|
-
* Deliberately FilterField, not an alias of it: the columns a user can sort by
|
|
323
|
-
* are the columns a user can filter by, and the filter's registry already
|
|
324
|
-
* resolves units, baseline snapshots and critical-path values for all of them.
|
|
325
|
-
* A second field vocabulary would drift from this one on the first new column.
|
|
326
|
-
*/
|
|
327
313
|
readonly field: FilterField;
|
|
328
314
|
readonly direction: 'asc' | 'desc';
|
|
329
315
|
}
|
|
330
|
-
/**
|
|
331
|
-
* The active ordering, as an ordered list of keys: rule 0 decides, rule 1 breaks
|
|
332
|
-
* its ties, and so on. An empty list means "no user ordering", which is stored
|
|
333
|
-
* as null rather than an empty state (mirroring isEmptyFilter).
|
|
334
|
-
*/
|
|
335
316
|
interface OrderState {
|
|
336
317
|
readonly rules: ReadonlyArray<OrderRule>;
|
|
337
318
|
}
|
|
338
|
-
/**
|
|
339
|
-
* One resequenced sibling group. Ordering is hierarchical: an activity only ever
|
|
340
|
-
* competes with its own siblings, so a change is expressed per parent rather
|
|
341
|
-
* than as a flat sequence over the whole schedule.
|
|
342
|
-
*/
|
|
343
319
|
interface BranchOrderChange {
|
|
344
320
|
readonly parentId: string;
|
|
345
321
|
readonly childIds: ReadonlyArray<string>;
|
|
@@ -412,12 +388,6 @@ type DispatchAction = {
|
|
|
412
388
|
kind: 'persistence-acknowledge';
|
|
413
389
|
activities?: ReadonlyArray<PersistedEntityIdentity>;
|
|
414
390
|
links?: ReadonlyArray<PersistedEntityIdentity>;
|
|
415
|
-
/**
|
|
416
|
-
* CP19 (ISSUE-070): valores que el backend normalizo al guardar (hoy solo
|
|
417
|
-
* progress). El motor los reconcilia — aplica los que difieren, ignora
|
|
418
|
-
* los iguales — para que el core refleje lo persistido. Sin undo: el
|
|
419
|
-
* acuse es clear-on-success y el tracker snapshotea despues.
|
|
420
|
-
*/
|
|
421
391
|
reconciledProgress?: ReadonlyArray<ReconciledActivityProgress>;
|
|
422
392
|
} | {
|
|
423
393
|
kind: 'baseline-apply';
|
|
@@ -497,14 +467,6 @@ type DispatchAction = {
|
|
|
497
467
|
kind: 'activity-set-progress';
|
|
498
468
|
activityId: ActivityId;
|
|
499
469
|
newValue: 0 | 100;
|
|
500
|
-
/**
|
|
501
|
-
* CP15 (ISSUE-066): el origen se DECLARA, no se adivina. 'action-button'
|
|
502
|
-
* es el unico origen con salvoconducto
|
|
503
|
-
* de negocio para actividades en Lookahead (espejo del flag
|
|
504
|
-
* progressChangedByActionButton que consume parseToUpdate en el
|
|
505
|
-
* backend; guia agents/progreso-lookahead.md). Sin origen declarado
|
|
506
|
-
* aplica el canEdit completo del pipeline.
|
|
507
|
-
*/
|
|
508
470
|
origin?: 'action-button';
|
|
509
471
|
eventSource?: string;
|
|
510
472
|
} | {
|
|
@@ -627,14 +589,6 @@ interface ChangeSet {
|
|
|
627
589
|
calendars: ReadonlyArray<EntityChange<Calendar>>;
|
|
628
590
|
trackingEvents: ReadonlyArray<TrackingEvent>;
|
|
629
591
|
viewState?: ReadonlyArray<ViewStateChange>;
|
|
630
|
-
/**
|
|
631
|
-
* Sibling groups whose display sequence changed, each already in final order.
|
|
632
|
-
* Carried per branch rather than as a flat sequence because ordering never
|
|
633
|
-
* reparents: the renderer assigns each array and repaints once.
|
|
634
|
-
*
|
|
635
|
-
* Absent when nothing resequenced. Never a partial answer: a branch listed
|
|
636
|
-
* here holds all of its children.
|
|
637
|
-
*/
|
|
638
592
|
order?: ReadonlyArray<BranchOrderChange>;
|
|
639
593
|
effects?: ReadonlyArray<ScheduleEffect>;
|
|
640
594
|
warnings?: ReadonlyArray<ConstraintWarning>;
|
|
@@ -667,15 +621,6 @@ interface BackendCalendarInput {
|
|
|
667
621
|
baseexceptiondays?: BackendCalendarExceptionInput[];
|
|
668
622
|
}
|
|
669
623
|
interface BackendActivityInput {
|
|
670
|
-
/**
|
|
671
|
-
* Persisted backend identity.
|
|
672
|
-
*
|
|
673
|
-
* Synthetic activities that have not been persisted yet use `null`.
|
|
674
|
-
* `unique_id` remains their stable local identity.
|
|
675
|
-
*
|
|
676
|
-
* A numeric zero is intentionally preserved as a numeric backend identity
|
|
677
|
-
* for compatibility with the certified proplanner-id/002 scenario.
|
|
678
|
-
*/
|
|
679
624
|
id: number | null;
|
|
680
625
|
unique_id: string;
|
|
681
626
|
parent_id: string;
|
|
@@ -814,29 +759,6 @@ declare class ScheduleCore {
|
|
|
814
759
|
private readonly _undo;
|
|
815
760
|
private _opQueue;
|
|
816
761
|
private _scheduleRevision;
|
|
817
|
-
/**
|
|
818
|
-
* Revision counting mutations that have been ADMITTED, whether or not they
|
|
819
|
-
* have changed anything yet. `_scheduleRevision` counts the ones that
|
|
820
|
-
* actually did.
|
|
821
|
-
*
|
|
822
|
-
* INVARIANT: `_pendingScheduleRevision >= _scheduleRevision`, and equality
|
|
823
|
-
* means no mutation is in flight.
|
|
824
|
-
*
|
|
825
|
-
* The two exist separately because the useful instant and the knowable
|
|
826
|
-
* instant are not the same one. A critical-path calculation becomes garbage
|
|
827
|
-
* the moment the next mutation is admitted, but whether that mutation is
|
|
828
|
-
* substantive is only knowable once its ChangeSet exists, which is hundreds
|
|
829
|
-
* of milliseconds later at project scale. Measured live on a 12268-activity
|
|
830
|
-
* project: the cancellation flag flipped 929 ms into a 930 ms calculation,
|
|
831
|
-
* 812 into 812 and 785 into 785, because the job's apply block queues behind
|
|
832
|
-
* the very dispatch whose completion cancels it. Cancellation and job end
|
|
833
|
-
* were the same event, so every discarded job ran the whole calculation.
|
|
834
|
-
*
|
|
835
|
-
* Splitting the counter buys the early signal without moving the meaning of
|
|
836
|
-
* `_scheduleRevision`, whose three readers (`isCriticalPathSettled`,
|
|
837
|
-
* `createDateGesturePreview` and the job's own `isCurrent`) are all written
|
|
838
|
-
* against "the state actually changed".
|
|
839
|
-
*/
|
|
840
762
|
private _pendingScheduleRevision;
|
|
841
763
|
private _criticalPathRevision;
|
|
842
764
|
private _activeCriticalPath;
|
|
@@ -851,13 +773,6 @@ declare class ScheduleCore {
|
|
|
851
773
|
getActivityView(id: ActivityId): Readonly<CoreActivity> | null;
|
|
852
774
|
createDateGesturePreview(gesture: DateGesture): DateGesturePreview;
|
|
853
775
|
getAllActivitiesView(): ReadonlyArray<Readonly<CoreActivity>>;
|
|
854
|
-
/**
|
|
855
|
-
* Read del plan de indent (ISSUE-080): los padres destino DISTINTOS bajo los
|
|
856
|
-
* que quedarían las actividades si se indentaran ahora. Es exactamente la
|
|
857
|
-
* planificación que ejecuta el handler (`planIndentMoves`, autoridad única),
|
|
858
|
-
* expuesta para que la frontera pueda correr el protocolo de conversión a
|
|
859
|
-
* madre (chequeo backend + modal) ANTES de despachar. Solo lecturas.
|
|
860
|
-
*/
|
|
861
776
|
getIndentTargetParentIds(activityIds: ReadonlyArray<ActivityId | string>): readonly string[];
|
|
862
777
|
getChildrenView(parentId: ActivityId | '0'): ReadonlyArray<Readonly<CoreActivity>>;
|
|
863
778
|
getLinkView(id: LinkId): Readonly<Link> | null;
|
|
@@ -884,53 +799,14 @@ declare class ScheduleCore {
|
|
|
884
799
|
getModifiedActivities(): ReadonlyArray<Readonly<CoreActivity>>;
|
|
885
800
|
getNewActivities(): ReadonlyArray<Readonly<CoreActivity>>;
|
|
886
801
|
hasUnsavedChanges(): boolean;
|
|
887
|
-
/** Read-only revision; moves once per substantive mutation. */
|
|
888
802
|
getScheduleRevision(): number;
|
|
889
803
|
getCanonicalDigest(): string;
|
|
890
804
|
createProjectionChangeSetFrom(source: ScheduleCore): ChangeSet;
|
|
891
805
|
getDeletedActivitiesSinceLastSave(): ReadonlyArray<Readonly<DeletedActivitySnapshot>>;
|
|
892
806
|
getDeletedLinksSinceLastSave(): ReadonlyArray<Readonly<DeletedLinkSnapshot>>;
|
|
893
807
|
private _enqueue;
|
|
894
|
-
/**
|
|
895
|
-
* Marks a mutation as admitted and invalidates the calculation in flight.
|
|
896
|
-
*
|
|
897
|
-
* Called BEFORE `_enqueue`, which is the point of the whole thing: the wait
|
|
898
|
-
* in the operation queue is part of the window a running calculation wastes,
|
|
899
|
-
* and it is the longest part of it when several mutations are already
|
|
900
|
-
* queued.
|
|
901
|
-
*
|
|
902
|
-
* `dispatchChangesSchedulingState` is a pure function of the action, so this
|
|
903
|
-
* decision needs no state and cannot be wrong about the action's nature. What
|
|
904
|
-
* it cannot know yet is whether the mutation will produce anything, which is
|
|
905
|
-
* what `_settleScheduleMutation` reconciles afterwards.
|
|
906
|
-
*/
|
|
907
808
|
private _beginScheduleMutation;
|
|
908
|
-
/** Undo and redo have no action to classify: reaching them IS the mutation. */
|
|
909
809
|
private _admitScheduleMutation;
|
|
910
|
-
/**
|
|
911
|
-
* Closes a mutation admitted by `_beginScheduleMutation`, on EVERY exit path.
|
|
912
|
-
*
|
|
913
|
-
* `changedState` false means the mutation was admitted and produced nothing
|
|
914
|
-
* (rejected, non-substantive, or rolled back). The pending revision walks
|
|
915
|
-
* back so the invariant holds and `isCriticalPathSettled` keeps telling the
|
|
916
|
-
* truth, and the calculation this mutation killed for nothing is re-armed.
|
|
917
|
-
*
|
|
918
|
-
* The re-arm goes through the queue and that is not incidental. Started
|
|
919
|
-
* outside it, the calculation would run immediately while the next queued
|
|
920
|
-
* mutation is still waiting, and that mutation would kill it again on
|
|
921
|
-
* admission: a cancel-and-restart treadmill burning a fresh project-wide deep
|
|
922
|
-
* copy per lap. Inside the queue the restart cannot happen until the queue
|
|
923
|
-
* drains, so at most one calculation is armed per settled mutation. The burst
|
|
924
|
-
* scenario will NOT catch a regression here, because there every dispatch
|
|
925
|
-
* succeeds and this path is never taken.
|
|
926
|
-
*
|
|
927
|
-
* It re-arms through `recomputeCriticalPath` rather than enqueueing the job
|
|
928
|
-
* directly, because the queue slot must NOT await the job: the job's own
|
|
929
|
-
* apply block needs a later slot on this same queue, so awaiting it from
|
|
930
|
-
* inside a slot deadlocks the core. `recomputeCriticalPath` already has the
|
|
931
|
-
* shape that returns the job's promise out of the slot instead of awaiting
|
|
932
|
-
* it, and it keeps `_criticalPathReady` pointing at the live calculation.
|
|
933
|
-
*/
|
|
934
810
|
private _settleScheduleMutation;
|
|
935
811
|
dispatch(action: DispatchAction, options?: DispatchOptions): Promise<DispatchResult>;
|
|
936
812
|
applyActivityBatch(action: ActivityBatchAction, options?: DispatchOptions): Promise<DispatchResult>;
|
|
@@ -942,51 +818,8 @@ declare class ScheduleCore {
|
|
|
942
818
|
isCriticalPathSettled(): boolean;
|
|
943
819
|
whenCriticalPathSettled(): Promise<void>;
|
|
944
820
|
private _withReappliedViewState;
|
|
945
|
-
private _recordRelativePlacementPin;
|
|
946
|
-
/**
|
|
947
|
-
* The single place the two view-state passes are chained. Dispatch, undo and
|
|
948
|
-
* redo all route through here: when this existed only inside the dispatch
|
|
949
|
-
* path, undo and redo reapplied the filter and forgot the order, so an edit
|
|
950
|
-
* that moved a row and was then undone left the row in its new position.
|
|
951
|
-
*
|
|
952
|
-
* The sequence between the passes is indifferent. Filter and order are
|
|
953
|
-
* orthogonal projections over the same tree — the filter decides which rows
|
|
954
|
-
* exist on screen and never reads the order; the order sequences every
|
|
955
|
-
* sibling group from the hierarchy index and never reads visibility. Either
|
|
956
|
-
* sequence produces the same ChangeSet.
|
|
957
|
-
*
|
|
958
|
-
* Both passes answer null while their state is inactive, so an unfiltered,
|
|
959
|
-
* unsorted schedule pays two property reads.
|
|
960
|
-
*/
|
|
961
821
|
private _reapplyViewState;
|
|
962
|
-
/**
|
|
963
|
-
* Emits `order` for the branches this mutation resequenced, when no user order
|
|
964
|
-
* is active.
|
|
965
|
-
*
|
|
966
|
-
* The contract is that `order` reports a CHANGED SEQUENCE, not the presence of
|
|
967
|
-
* a sort. Tying emission to the cause instead of the effect is what produced
|
|
968
|
-
* the undo bug and, later, the reparent ones: without an active order a move,
|
|
969
|
-
* an indent, an outdent or the undo of any of them rearranged rows and said
|
|
970
|
-
* nothing, so an incremental consumer kept the old sequence. The undo of a
|
|
971
|
-
* reparent was the worst of them — it carried neither `order` nor a single
|
|
972
|
-
* correlativeId, so the position was not recoverable by any consumer.
|
|
973
|
-
*
|
|
974
|
-
* The touched branches are derived from the ChangeSet rather than accumulated
|
|
975
|
-
* in the state: an entity whose parentId or correlativeId moved, plus the
|
|
976
|
-
* parents of created and deleted rows, is exactly the set of branches whose
|
|
977
|
-
* sequence can differ. That keeps this linear in the blast radius, adds
|
|
978
|
-
* nothing to the write path, and cannot leak across dispatches.
|
|
979
|
-
*/
|
|
980
822
|
private _emitTouchedBranchOrder;
|
|
981
|
-
/**
|
|
982
|
-
* Re-sequences the grid after any mutation that could have changed a value the
|
|
983
|
-
* active order sorts by. Ordering is a view over the data, so an edit that
|
|
984
|
-
* moves a row past its sibling must move the row, exactly as the filter makes
|
|
985
|
-
* a no-longer-matching row disappear.
|
|
986
|
-
*
|
|
987
|
-
* Production only re-sorts after a bar drag; diverging from that is a
|
|
988
|
-
* deliberate product decision, not an oversight.
|
|
989
|
-
*/
|
|
990
823
|
private _reapplyActiveOrder;
|
|
991
824
|
private _reapplyActiveFilter;
|
|
992
825
|
private _recordScheduleMutation;
|