@outbuild-company/schedule-core 1.6.3 → 1.8.0

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.d.cts CHANGED
@@ -134,6 +134,14 @@ 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
+ calendarDuration?: number | null;
137
145
  expectedProgress: number | null;
138
146
  expectedProgressBaseline: number | null;
139
147
  status: ActivityStatus | null;
@@ -145,6 +153,8 @@ interface Link {
145
153
  target: ActivityId;
146
154
  type: LinkType;
147
155
  lag: number;
156
+ freeSlackHours: number | null;
157
+ isCritical: boolean;
148
158
  ganttId?: number;
149
159
  sectorId?: number;
150
160
  proplannerId?: number;
@@ -193,6 +203,8 @@ interface SectorMetadata {
193
203
  updateDurationForPrimaveraEndDate?: boolean;
194
204
  activityCreter?: ActivityCreter;
195
205
  statusCriteria: StatusCriteria;
206
+ /** Declared by the loader input; never derived from the backend payload. */
207
+ ganttId: number | null;
196
208
  }
197
209
  interface EntityChange<T> {
198
210
  id: string;
@@ -279,14 +291,22 @@ type NumberOperator = 'equals' | 'notEquals' | 'greaterThan' | 'lessThan' | 'gre
279
291
  type DateOperator = 'after' | 'before';
280
292
  type MembershipOperator = 'someOf' | 'notSomeOf';
281
293
  type FilterOperator = StringOperator | NumberOperator | DateOperator | MembershipOperator;
282
- type FilterField = 'name' | 'description' | 'customId' | 'correlativeId' | 'uniqueCorrelativeId' | 'progress' | 'durationDays' | 'calendarDuration' | 'cost' | 'usedCost' | 'realCost' | 'workHours' | 'realWorkHours' | 'ponderator' | 'freeSlackDays' | 'totalSlackDays' | 'expectedProgressBaseline' | 'baselineDurationDays' | 'baselineCost' | 'baselineWorkHours' | 'startDate' | 'endDate' | 'constraintDate' | 'baselineStartDate' | 'baselineEndDate' | 'earlyStart' | 'earlyFinish' | 'lateStart' | 'lateFinish' | 'responsableIds' | 'tagIds' | 'status' | 'constraintType' | 'calendarId' | 'subcontractId' | 'isCritical';
294
+ type StringFilterField = 'name' | 'description' | 'customId';
295
+ type NumberFilterField = 'correlativeId' | 'uniqueCorrelativeId' | 'progress' | 'durationDays' | 'calendarDuration' | 'cost' | 'usedCost' | 'realCost' | 'workHours' | 'realWorkHours' | 'ponderator' | 'freeSlackDays' | 'totalSlackDays' | 'expectedProgressBaseline' | 'baselineDurationDays' | 'baselineCost' | 'baselineWorkHours';
296
+ type DateFilterField = 'startDate' | 'endDate' | 'constraintDate' | 'baselineStartDate' | 'baselineEndDate' | 'earlyStart' | 'earlyFinish' | 'lateStart' | 'lateFinish';
297
+ type IdArrayFilterField = 'responsableIds' | 'tagIds';
298
+ type EnumFilterField = 'status' | 'constraintType';
299
+ type ReferenceFilterField = 'calendarId' | 'subcontractId';
300
+ type BooleanFilterField = 'isCritical';
301
+ type FilterField = StringFilterField | NumberFilterField | DateFilterField | IdArrayFilterField | EnumFilterField | ReferenceFilterField | BooleanFilterField;
283
302
  type FilterScalarValue = string | number | Date;
284
- type FilterCriterionValue = FilterScalarValue | ReadonlyArray<string | number>;
285
- interface FilterCriterion {
286
- readonly field: FilterField;
287
- readonly operator: FilterOperator;
288
- readonly value: FilterCriterionValue;
303
+ type FilterCriterionValue = FilterScalarValue | ReadonlyArray<string | number | boolean>;
304
+ interface Criterion<Field extends FilterField, Operator, Value> {
305
+ readonly field: Field;
306
+ readonly operator: Operator;
307
+ readonly value: Value;
289
308
  }
309
+ type FilterCriterion = Criterion<StringFilterField, StringOperator, string> | Criterion<NumberFilterField, NumberOperator, string | number> | Criterion<DateFilterField, DateOperator, string | number | Date> | Criterion<IdArrayFilterField, MembershipOperator, ReadonlyArray<string | number>> | Criterion<EnumFilterField, MembershipOperator, ReadonlyArray<string>> | Criterion<ReferenceFilterField, MembershipOperator, ReadonlyArray<string | number>> | Criterion<BooleanFilterField, MembershipOperator, ReadonlyArray<boolean>>;
290
310
  interface FilterDateRange {
291
311
  readonly start: Date;
292
312
  readonly end: Date;
@@ -341,6 +361,10 @@ type LinksBatchOperation = {
341
361
  kind: 'delete';
342
362
  linkId: LinkId;
343
363
  };
364
+ interface ReconciledActivityProgress {
365
+ readonly activityId: string;
366
+ readonly progress: number;
367
+ }
344
368
  interface PersistedEntityIdentity {
345
369
  readonly id: string;
346
370
  readonly proplannerId: number;
@@ -355,7 +379,7 @@ interface ActivityBatchItem {
355
379
  readonly parent: ActivityBatchParentReference;
356
380
  readonly index?: number;
357
381
  readonly activityId?: ActivityId;
358
- readonly overrides?: CreationOverrides;
382
+ readonly overrides?: ActivityCreationOverrides;
359
383
  }
360
384
  interface ActivityBatchLinkInput {
361
385
  readonly source: ActivityBatchReference;
@@ -373,9 +397,28 @@ interface ActivityBatchAction {
373
397
  }
374
398
 
375
399
  type DispatchAction = {
400
+ kind: 'activity-copy';
401
+ eventSource?: string;
402
+ } | {
403
+ kind: 'activity-clipboard-clear';
404
+ eventSource?: string;
405
+ } | {
406
+ kind: 'activity-paste-copied';
407
+ destination: {
408
+ afterSiblingId: ActivityId;
409
+ };
410
+ eventSource?: string;
411
+ } | {
376
412
  kind: 'persistence-acknowledge';
377
413
  activities?: ReadonlyArray<PersistedEntityIdentity>;
378
414
  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
+ reconciledProgress?: ReadonlyArray<ReconciledActivityProgress>;
379
422
  } | {
380
423
  kind: 'baseline-apply';
381
424
  points: ReadonlyArray<BaselinePoint>;
@@ -428,7 +471,7 @@ type DispatchAction = {
428
471
  parentId: ActivityId | '0';
429
472
  afterSiblingId?: ActivityId | undefined;
430
473
  beforeSiblingId?: ActivityId | undefined;
431
- overrides?: CreationOverrides;
474
+ overrides?: ActivityCreationOverrides;
432
475
  activityId?: ActivityId;
433
476
  eventSource?: string | undefined;
434
477
  } | {
@@ -454,6 +497,15 @@ type DispatchAction = {
454
497
  kind: 'activity-set-progress';
455
498
  activityId: ActivityId;
456
499
  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
+ origin?: 'action-button';
457
509
  eventSource?: string;
458
510
  } | {
459
511
  kind: 'selection-toggle';
@@ -490,40 +542,17 @@ type DispatchAction = {
490
542
  activityIds: ReadonlyArray<ActivityId>;
491
543
  isLookahead: boolean;
492
544
  hasLookaheadTasks: boolean;
545
+ persistedProgress?: number;
493
546
  acknowledgePersistedLookahead?: boolean;
494
547
  eventSource?: string;
495
- } | {
496
- kind: 'activity-paste';
497
- destination: {
498
- parentId: ActivityId | '0';
499
- index: number;
500
- } | {
501
- afterSiblingId: ActivityId;
502
- };
503
- referenceActivityId: ActivityId;
504
- activities: ReadonlyArray<PastedActivityInput>;
505
- links: ReadonlyArray<PastedLinkInput>;
506
- eventSource?: string;
548
+ };
549
+ type ActivityCreationOverrides = Omit<CreationOverrides, 'durationHours'> & {
550
+ readonly durationDays?: number;
507
551
  };
508
552
  type InternalDispatchAction = DispatchAction | ActivityBatchAction;
509
- interface PastedActivityInput {
510
- readonly originalId: ActivityId;
511
- readonly originalParentId: ActivityId | '0';
512
- readonly activityId?: ActivityId;
513
- readonly overrides: CreationOverrides;
514
- readonly baselineSnapshot?: ActivityBaselineSnapshot | null;
515
- }
516
- interface PastedLinkInput {
517
- readonly source: ActivityId;
518
- readonly target: ActivityId;
519
- readonly type: LinkType;
520
- readonly lag: number;
521
- readonly linkId?: LinkId;
522
- }
523
553
  interface DispatchOptions {
524
554
  skipAutoSchedule?: boolean;
525
555
  skipCriticalPath?: boolean;
526
- inputUnit?: 'days' | 'hours';
527
556
  }
528
557
  type DispatchResult = {
529
558
  ok: true;
@@ -746,6 +775,7 @@ interface ScheduleCoreInput extends BackendScheduleInput {
746
775
  clock?: () => Date;
747
776
  criticalPathOnLoad?: boolean;
748
777
  statusCriteria?: StatusCriteria;
778
+ ganttId?: number;
749
779
  reporter?: ScheduleCoreReporter;
750
780
  }
751
781
 
@@ -764,14 +794,23 @@ interface DateGesturePreview {
764
794
  } | null;
765
795
  }
766
796
 
797
+ interface EffectiveGraphAudit {
798
+ readonly activityCount: number;
799
+ readonly logicalLinkCount: number;
800
+ readonly effectiveEdgeCount: number;
801
+ readonly circularComponents: ReadonlyArray<ReadonlyArray<string>>;
802
+ readonly largestComponentSize: number;
803
+ }
767
804
  interface UndoOptions {
768
805
  readonly skipCriticalPath?: boolean;
769
806
  readonly expectedUndoDepth?: number;
770
807
  }
771
808
 
772
809
  declare class ScheduleCore {
810
+ private readonly _activityClipboard;
773
811
  private _status;
774
812
  private readonly coreRuntime;
813
+ private readonly _isFork;
775
814
  private readonly _undo;
776
815
  private _opQueue;
777
816
  private _scheduleRevision;
@@ -803,6 +842,7 @@ declare class ScheduleCore {
803
842
  private _activeCriticalPath;
804
843
  constructor(input: ScheduleCoreInput);
805
844
  get ready(): Promise<void>;
845
+ fork(): Promise<ScheduleCore>;
806
846
  get criticalPathReady(): Promise<{
807
847
  changes: ChangeSet;
808
848
  } | null>;
@@ -811,9 +851,19 @@ declare class ScheduleCore {
811
851
  getActivityView(id: ActivityId): Readonly<CoreActivity> | null;
812
852
  createDateGesturePreview(gesture: DateGesture): DateGesturePreview;
813
853
  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
+ getIndentTargetParentIds(activityIds: ReadonlyArray<ActivityId | string>): readonly string[];
814
862
  getChildrenView(parentId: ActivityId | '0'): ReadonlyArray<Readonly<CoreActivity>>;
815
863
  getLinkView(id: LinkId): Readonly<Link> | null;
864
+ getLinksForActivityView(activityId: ActivityId): ReadonlyArray<Readonly<Link>>;
816
865
  getAllLinksView(): ReadonlyArray<Readonly<Link>>;
866
+ auditEffectiveGraph(): EffectiveGraphAudit;
817
867
  getProperty<Property extends keyof CoreActivity>(activityId: ActivityId, property: Property): CoreActivity[Property] | null;
818
868
  getAllIds(): readonly string[];
819
869
  forEachActivityId(visit: (id: string) => void): void;
@@ -830,8 +880,14 @@ declare class ScheduleCore {
830
880
  isCustomIdInUse(customId: string, currentCustomId?: string | null): boolean;
831
881
  getProjectWorkHours(): ProjectWorkHours | null;
832
882
  getModifiedLinks(): ReadonlyArray<Readonly<Link>>;
883
+ getNewLinks(): ReadonlyArray<Readonly<Link>>;
833
884
  getModifiedActivities(): ReadonlyArray<Readonly<CoreActivity>>;
885
+ getNewActivities(): ReadonlyArray<Readonly<CoreActivity>>;
834
886
  hasUnsavedChanges(): boolean;
887
+ /** Read-only revision; moves once per substantive mutation. */
888
+ getScheduleRevision(): number;
889
+ getCanonicalDigest(): string;
890
+ createProjectionChangeSetFrom(source: ScheduleCore): ChangeSet;
835
891
  getDeletedActivitiesSinceLastSave(): ReadonlyArray<Readonly<DeletedActivitySnapshot>>;
836
892
  getDeletedLinksSinceLastSave(): ReadonlyArray<Readonly<DeletedLinkSnapshot>>;
837
893
  private _enqueue;
@@ -1029,6 +1085,9 @@ declare const DEFAULT_HOURS_PER_DAY = 8;
1029
1085
 
1030
1086
  type DispatchActionKind = DispatchAction['kind'];
1031
1087
  declare const DISPATCH_ACTION_KIND: {
1088
+ readonly ACTIVITY_CLIPBOARD_CLEAR: "activity-clipboard-clear";
1089
+ readonly ACTIVITY_COPY: "activity-copy";
1090
+ readonly ACTIVITY_PASTE_COPIED: "activity-paste-copied";
1032
1091
  readonly PERSISTENCE_ACKNOWLEDGE: "persistence-acknowledge";
1033
1092
  readonly BASELINE_APPLY: "baseline-apply";
1034
1093
  readonly PONDERATOR_CRITERION_SET: "ponderator-criterion-set";
@@ -1046,7 +1105,6 @@ declare const DISPATCH_ACTION_KIND: {
1046
1105
  readonly ACTIVITY_INDENT: "activity-indent";
1047
1106
  readonly ACTIVITY_OUTDENT: "activity-outdent";
1048
1107
  readonly ACTIVITY_SET_PROGRESS: "activity-set-progress";
1049
- readonly ACTIVITY_PASTE: "activity-paste";
1050
1108
  readonly SELECTION_TOGGLE: "selection-toggle";
1051
1109
  readonly SELECTION_REPLACE: "selection-replace";
1052
1110
  readonly VISIBILITY_SET: "visibility-set";
@@ -1077,6 +1135,9 @@ declare const REJECTION_REASON: {
1077
1135
  readonly ACTIVITY_NOT_FOUND: "activity_not_found";
1078
1136
  readonly PARENT_NOT_FOUND: "parent_not_found";
1079
1137
  readonly ACTIVITY_IDS_EMPTY: "activity_ids_empty";
1138
+ readonly NO_ACTIVITY_SELECTION: "no_activity_selection";
1139
+ readonly CLIPBOARD_EMPTY: "clipboard_empty";
1140
+ readonly ACTIVITY_PASTE_INVARIANT_FAILED: "activity_paste_invariant_failed";
1080
1141
  readonly ANCHOR_SIBLING_CONFLICT: "anchor_sibling_conflict";
1081
1142
  readonly ANCHOR_SIBLING_NOT_FOUND: "anchor_sibling_not_found";
1082
1143
  readonly ANCHOR_SIBLING_WRONG_PARENT: "anchor_sibling_wrong_parent";
@@ -1084,6 +1145,8 @@ declare const REJECTION_REASON: {
1084
1145
  readonly CANNOT_MOVE_INTO_OWN_DESCENDANT: "cannot_move_into_own_descendant";
1085
1146
  readonly INDENT_NO_ELIGIBLE_SIBLING: "indent_no_eligible_sibling";
1086
1147
  readonly OUTDENT_ROOT_LEVEL_NOT_EDITABLE: "outdent_root_level_not_editable";
1148
+ readonly HIERARCHY_CYCLE: "hierarchy_cycle";
1149
+ readonly SANDBOX_PERSISTENCE_FORBIDDEN: "sandbox_persistence_forbidden";
1087
1150
  readonly INVALID_PROGRESS_VALUE: "invalid_progress_value_must_be_0_or_100";
1088
1151
  };
1089
1152
  type DispatchRejectReason = (typeof REJECTION_REASON)[keyof typeof REJECTION_REASON];
@@ -1097,4 +1160,4 @@ declare const DISPATCH_TRACK_EVENT: {
1097
1160
  };
1098
1161
  type DispatchTrackEvent = (typeof DISPATCH_TRACK_EVENT)[keyof typeof DISPATCH_TRACK_EVENT];
1099
1162
 
1100
- export { ACTIVITY_TYPE, type ActivityBaselineSnapshot, type ActivityBatchAction, type ActivityBatchItem, type ActivityBatchLinkInput, type ActivityBatchMode, type ActivityBatchParentReference, type ActivityBatchReference, type ActivityCreter, type ActivityId, type ActivityStatus, type ActivityType, type BackendActivityInput, type BackendCalendarExceptionInput, type BackendCalendarInput, type BackendLinkInput, type BackendScheduleInput, type BackendSectorInput, type BackendShiftInput, type BaselinePoint, type BaselineVersion, type BranchOrderChange, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, type Calendar, type CalendarId, type CalendarLike, type CalendarUnit, type CalendarWorktime, type ChangeSet, type ChangeSetSource, type ColumnName, type ConstraintType, type ConstraintWarning, type CoreActivity, type CoreBaselinePoint, type CreationKind, type CreationOverrides, type CriticalPathResult, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, type DateGesture, type DateGesturePreview, type DatesBatchVerdict, type DeletedActivitySnapshot, type DeletedLinkSnapshot, type DispatchAction, type DispatchActionKind, type DispatchOptions, type DispatchRejectReason, type DispatchResult, type DispatchTrackEvent, type EditableColumnName, type EntityChange, type ExpectedProgressAdapter, type FilterCriterion, type FilterCriterionValue, type FilterDateRange, type FilterField, type FilterOperator, type FilterState, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, type Link, type LinkBatchVerdict, type LinkId, type LinkType, type LinkTypeCode, type LinksBatchOperation, NEW_ACTIVITY_DEFAULTS, type OrderRule, type OrderState, type ParsedInput, type PastedActivityInput, type PastedLinkInput, type PendingRequest, type PersistedEntityIdentity, type PipelineColumnName, type ProjectWorkHours, REJECTION_REASON, ROOT_PARENT_ID, SCHEDULE_CORE_STATUS, STATUS, ScheduleCore, type ScheduleCoreInput, type ScheduleCoreReporter, type ScheduleCoreStatus, type ScheduleEffect, type SectorMetadata, type StaticActivityDefaults, type StatusCriteria, type TrackingEvent, type UndoOptions, type ViewStateChange, type ViewStatePropChange, WORK_TIME_DIRECTION, type WithProplannerId, type WorkTimeDirection, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };
1163
+ export { ACTIVITY_TYPE, type ActivityBaselineSnapshot, type ActivityBatchAction, type ActivityBatchItem, type ActivityBatchLinkInput, type ActivityBatchMode, type ActivityBatchParentReference, type ActivityBatchReference, type ActivityCreationOverrides, type ActivityCreter, type ActivityId, type ActivityStatus, type ActivityType, type BackendActivityInput, type BackendCalendarExceptionInput, type BackendCalendarInput, type BackendLinkInput, type BackendScheduleInput, type BackendSectorInput, type BackendShiftInput, type BaselinePoint, type BaselineVersion, type BranchOrderChange, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, type Calendar, type CalendarId, type CalendarLike, type CalendarUnit, type CalendarWorktime, type ChangeSet, type ChangeSetSource, type ColumnName, type ConstraintType, type ConstraintWarning, type CoreActivity, type CoreBaselinePoint, type CreationKind, type CriticalPathResult, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, type DateGesture, type DateGesturePreview, type DatesBatchVerdict, type DeletedActivitySnapshot, type DeletedLinkSnapshot, type DispatchAction, type DispatchActionKind, type DispatchOptions, type DispatchRejectReason, type DispatchResult, type DispatchTrackEvent, type EditableColumnName, type EffectiveGraphAudit, type EntityChange, type ExpectedProgressAdapter, type FilterCriterion, type FilterCriterionValue, type FilterDateRange, type FilterField, type FilterOperator, type FilterState, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, type Link, type LinkBatchVerdict, type LinkId, type LinkType, type LinkTypeCode, type LinksBatchOperation, NEW_ACTIVITY_DEFAULTS, type OrderRule, type OrderState, type ParsedInput, type PendingRequest, type PersistedEntityIdentity, type PipelineColumnName, type ProjectWorkHours, REJECTION_REASON, ROOT_PARENT_ID, SCHEDULE_CORE_STATUS, STATUS, ScheduleCore, type ScheduleCoreInput, type ScheduleCoreReporter, type ScheduleCoreStatus, type ScheduleEffect, type SectorMetadata, type StaticActivityDefaults, type StatusCriteria, type TrackingEvent, type UndoOptions, type ViewStateChange, type ViewStatePropChange, WORK_TIME_DIRECTION, type WithProplannerId, type WorkTimeDirection, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };
package/dist/index.d.ts CHANGED
@@ -134,6 +134,14 @@ 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
+ calendarDuration?: number | null;
137
145
  expectedProgress: number | null;
138
146
  expectedProgressBaseline: number | null;
139
147
  status: ActivityStatus | null;
@@ -145,6 +153,8 @@ interface Link {
145
153
  target: ActivityId;
146
154
  type: LinkType;
147
155
  lag: number;
156
+ freeSlackHours: number | null;
157
+ isCritical: boolean;
148
158
  ganttId?: number;
149
159
  sectorId?: number;
150
160
  proplannerId?: number;
@@ -193,6 +203,8 @@ interface SectorMetadata {
193
203
  updateDurationForPrimaveraEndDate?: boolean;
194
204
  activityCreter?: ActivityCreter;
195
205
  statusCriteria: StatusCriteria;
206
+ /** Declared by the loader input; never derived from the backend payload. */
207
+ ganttId: number | null;
196
208
  }
197
209
  interface EntityChange<T> {
198
210
  id: string;
@@ -279,14 +291,22 @@ type NumberOperator = 'equals' | 'notEquals' | 'greaterThan' | 'lessThan' | 'gre
279
291
  type DateOperator = 'after' | 'before';
280
292
  type MembershipOperator = 'someOf' | 'notSomeOf';
281
293
  type FilterOperator = StringOperator | NumberOperator | DateOperator | MembershipOperator;
282
- type FilterField = 'name' | 'description' | 'customId' | 'correlativeId' | 'uniqueCorrelativeId' | 'progress' | 'durationDays' | 'calendarDuration' | 'cost' | 'usedCost' | 'realCost' | 'workHours' | 'realWorkHours' | 'ponderator' | 'freeSlackDays' | 'totalSlackDays' | 'expectedProgressBaseline' | 'baselineDurationDays' | 'baselineCost' | 'baselineWorkHours' | 'startDate' | 'endDate' | 'constraintDate' | 'baselineStartDate' | 'baselineEndDate' | 'earlyStart' | 'earlyFinish' | 'lateStart' | 'lateFinish' | 'responsableIds' | 'tagIds' | 'status' | 'constraintType' | 'calendarId' | 'subcontractId' | 'isCritical';
294
+ type StringFilterField = 'name' | 'description' | 'customId';
295
+ type NumberFilterField = 'correlativeId' | 'uniqueCorrelativeId' | 'progress' | 'durationDays' | 'calendarDuration' | 'cost' | 'usedCost' | 'realCost' | 'workHours' | 'realWorkHours' | 'ponderator' | 'freeSlackDays' | 'totalSlackDays' | 'expectedProgressBaseline' | 'baselineDurationDays' | 'baselineCost' | 'baselineWorkHours';
296
+ type DateFilterField = 'startDate' | 'endDate' | 'constraintDate' | 'baselineStartDate' | 'baselineEndDate' | 'earlyStart' | 'earlyFinish' | 'lateStart' | 'lateFinish';
297
+ type IdArrayFilterField = 'responsableIds' | 'tagIds';
298
+ type EnumFilterField = 'status' | 'constraintType';
299
+ type ReferenceFilterField = 'calendarId' | 'subcontractId';
300
+ type BooleanFilterField = 'isCritical';
301
+ type FilterField = StringFilterField | NumberFilterField | DateFilterField | IdArrayFilterField | EnumFilterField | ReferenceFilterField | BooleanFilterField;
283
302
  type FilterScalarValue = string | number | Date;
284
- type FilterCriterionValue = FilterScalarValue | ReadonlyArray<string | number>;
285
- interface FilterCriterion {
286
- readonly field: FilterField;
287
- readonly operator: FilterOperator;
288
- readonly value: FilterCriterionValue;
303
+ type FilterCriterionValue = FilterScalarValue | ReadonlyArray<string | number | boolean>;
304
+ interface Criterion<Field extends FilterField, Operator, Value> {
305
+ readonly field: Field;
306
+ readonly operator: Operator;
307
+ readonly value: Value;
289
308
  }
309
+ type FilterCriterion = Criterion<StringFilterField, StringOperator, string> | Criterion<NumberFilterField, NumberOperator, string | number> | Criterion<DateFilterField, DateOperator, string | number | Date> | Criterion<IdArrayFilterField, MembershipOperator, ReadonlyArray<string | number>> | Criterion<EnumFilterField, MembershipOperator, ReadonlyArray<string>> | Criterion<ReferenceFilterField, MembershipOperator, ReadonlyArray<string | number>> | Criterion<BooleanFilterField, MembershipOperator, ReadonlyArray<boolean>>;
290
310
  interface FilterDateRange {
291
311
  readonly start: Date;
292
312
  readonly end: Date;
@@ -341,6 +361,10 @@ type LinksBatchOperation = {
341
361
  kind: 'delete';
342
362
  linkId: LinkId;
343
363
  };
364
+ interface ReconciledActivityProgress {
365
+ readonly activityId: string;
366
+ readonly progress: number;
367
+ }
344
368
  interface PersistedEntityIdentity {
345
369
  readonly id: string;
346
370
  readonly proplannerId: number;
@@ -355,7 +379,7 @@ interface ActivityBatchItem {
355
379
  readonly parent: ActivityBatchParentReference;
356
380
  readonly index?: number;
357
381
  readonly activityId?: ActivityId;
358
- readonly overrides?: CreationOverrides;
382
+ readonly overrides?: ActivityCreationOverrides;
359
383
  }
360
384
  interface ActivityBatchLinkInput {
361
385
  readonly source: ActivityBatchReference;
@@ -373,9 +397,28 @@ interface ActivityBatchAction {
373
397
  }
374
398
 
375
399
  type DispatchAction = {
400
+ kind: 'activity-copy';
401
+ eventSource?: string;
402
+ } | {
403
+ kind: 'activity-clipboard-clear';
404
+ eventSource?: string;
405
+ } | {
406
+ kind: 'activity-paste-copied';
407
+ destination: {
408
+ afterSiblingId: ActivityId;
409
+ };
410
+ eventSource?: string;
411
+ } | {
376
412
  kind: 'persistence-acknowledge';
377
413
  activities?: ReadonlyArray<PersistedEntityIdentity>;
378
414
  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
+ reconciledProgress?: ReadonlyArray<ReconciledActivityProgress>;
379
422
  } | {
380
423
  kind: 'baseline-apply';
381
424
  points: ReadonlyArray<BaselinePoint>;
@@ -428,7 +471,7 @@ type DispatchAction = {
428
471
  parentId: ActivityId | '0';
429
472
  afterSiblingId?: ActivityId | undefined;
430
473
  beforeSiblingId?: ActivityId | undefined;
431
- overrides?: CreationOverrides;
474
+ overrides?: ActivityCreationOverrides;
432
475
  activityId?: ActivityId;
433
476
  eventSource?: string | undefined;
434
477
  } | {
@@ -454,6 +497,15 @@ type DispatchAction = {
454
497
  kind: 'activity-set-progress';
455
498
  activityId: ActivityId;
456
499
  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
+ origin?: 'action-button';
457
509
  eventSource?: string;
458
510
  } | {
459
511
  kind: 'selection-toggle';
@@ -490,40 +542,17 @@ type DispatchAction = {
490
542
  activityIds: ReadonlyArray<ActivityId>;
491
543
  isLookahead: boolean;
492
544
  hasLookaheadTasks: boolean;
545
+ persistedProgress?: number;
493
546
  acknowledgePersistedLookahead?: boolean;
494
547
  eventSource?: string;
495
- } | {
496
- kind: 'activity-paste';
497
- destination: {
498
- parentId: ActivityId | '0';
499
- index: number;
500
- } | {
501
- afterSiblingId: ActivityId;
502
- };
503
- referenceActivityId: ActivityId;
504
- activities: ReadonlyArray<PastedActivityInput>;
505
- links: ReadonlyArray<PastedLinkInput>;
506
- eventSource?: string;
548
+ };
549
+ type ActivityCreationOverrides = Omit<CreationOverrides, 'durationHours'> & {
550
+ readonly durationDays?: number;
507
551
  };
508
552
  type InternalDispatchAction = DispatchAction | ActivityBatchAction;
509
- interface PastedActivityInput {
510
- readonly originalId: ActivityId;
511
- readonly originalParentId: ActivityId | '0';
512
- readonly activityId?: ActivityId;
513
- readonly overrides: CreationOverrides;
514
- readonly baselineSnapshot?: ActivityBaselineSnapshot | null;
515
- }
516
- interface PastedLinkInput {
517
- readonly source: ActivityId;
518
- readonly target: ActivityId;
519
- readonly type: LinkType;
520
- readonly lag: number;
521
- readonly linkId?: LinkId;
522
- }
523
553
  interface DispatchOptions {
524
554
  skipAutoSchedule?: boolean;
525
555
  skipCriticalPath?: boolean;
526
- inputUnit?: 'days' | 'hours';
527
556
  }
528
557
  type DispatchResult = {
529
558
  ok: true;
@@ -746,6 +775,7 @@ interface ScheduleCoreInput extends BackendScheduleInput {
746
775
  clock?: () => Date;
747
776
  criticalPathOnLoad?: boolean;
748
777
  statusCriteria?: StatusCriteria;
778
+ ganttId?: number;
749
779
  reporter?: ScheduleCoreReporter;
750
780
  }
751
781
 
@@ -764,14 +794,23 @@ interface DateGesturePreview {
764
794
  } | null;
765
795
  }
766
796
 
797
+ interface EffectiveGraphAudit {
798
+ readonly activityCount: number;
799
+ readonly logicalLinkCount: number;
800
+ readonly effectiveEdgeCount: number;
801
+ readonly circularComponents: ReadonlyArray<ReadonlyArray<string>>;
802
+ readonly largestComponentSize: number;
803
+ }
767
804
  interface UndoOptions {
768
805
  readonly skipCriticalPath?: boolean;
769
806
  readonly expectedUndoDepth?: number;
770
807
  }
771
808
 
772
809
  declare class ScheduleCore {
810
+ private readonly _activityClipboard;
773
811
  private _status;
774
812
  private readonly coreRuntime;
813
+ private readonly _isFork;
775
814
  private readonly _undo;
776
815
  private _opQueue;
777
816
  private _scheduleRevision;
@@ -803,6 +842,7 @@ declare class ScheduleCore {
803
842
  private _activeCriticalPath;
804
843
  constructor(input: ScheduleCoreInput);
805
844
  get ready(): Promise<void>;
845
+ fork(): Promise<ScheduleCore>;
806
846
  get criticalPathReady(): Promise<{
807
847
  changes: ChangeSet;
808
848
  } | null>;
@@ -811,9 +851,19 @@ declare class ScheduleCore {
811
851
  getActivityView(id: ActivityId): Readonly<CoreActivity> | null;
812
852
  createDateGesturePreview(gesture: DateGesture): DateGesturePreview;
813
853
  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
+ getIndentTargetParentIds(activityIds: ReadonlyArray<ActivityId | string>): readonly string[];
814
862
  getChildrenView(parentId: ActivityId | '0'): ReadonlyArray<Readonly<CoreActivity>>;
815
863
  getLinkView(id: LinkId): Readonly<Link> | null;
864
+ getLinksForActivityView(activityId: ActivityId): ReadonlyArray<Readonly<Link>>;
816
865
  getAllLinksView(): ReadonlyArray<Readonly<Link>>;
866
+ auditEffectiveGraph(): EffectiveGraphAudit;
817
867
  getProperty<Property extends keyof CoreActivity>(activityId: ActivityId, property: Property): CoreActivity[Property] | null;
818
868
  getAllIds(): readonly string[];
819
869
  forEachActivityId(visit: (id: string) => void): void;
@@ -830,8 +880,14 @@ declare class ScheduleCore {
830
880
  isCustomIdInUse(customId: string, currentCustomId?: string | null): boolean;
831
881
  getProjectWorkHours(): ProjectWorkHours | null;
832
882
  getModifiedLinks(): ReadonlyArray<Readonly<Link>>;
883
+ getNewLinks(): ReadonlyArray<Readonly<Link>>;
833
884
  getModifiedActivities(): ReadonlyArray<Readonly<CoreActivity>>;
885
+ getNewActivities(): ReadonlyArray<Readonly<CoreActivity>>;
834
886
  hasUnsavedChanges(): boolean;
887
+ /** Read-only revision; moves once per substantive mutation. */
888
+ getScheduleRevision(): number;
889
+ getCanonicalDigest(): string;
890
+ createProjectionChangeSetFrom(source: ScheduleCore): ChangeSet;
835
891
  getDeletedActivitiesSinceLastSave(): ReadonlyArray<Readonly<DeletedActivitySnapshot>>;
836
892
  getDeletedLinksSinceLastSave(): ReadonlyArray<Readonly<DeletedLinkSnapshot>>;
837
893
  private _enqueue;
@@ -1029,6 +1085,9 @@ declare const DEFAULT_HOURS_PER_DAY = 8;
1029
1085
 
1030
1086
  type DispatchActionKind = DispatchAction['kind'];
1031
1087
  declare const DISPATCH_ACTION_KIND: {
1088
+ readonly ACTIVITY_CLIPBOARD_CLEAR: "activity-clipboard-clear";
1089
+ readonly ACTIVITY_COPY: "activity-copy";
1090
+ readonly ACTIVITY_PASTE_COPIED: "activity-paste-copied";
1032
1091
  readonly PERSISTENCE_ACKNOWLEDGE: "persistence-acknowledge";
1033
1092
  readonly BASELINE_APPLY: "baseline-apply";
1034
1093
  readonly PONDERATOR_CRITERION_SET: "ponderator-criterion-set";
@@ -1046,7 +1105,6 @@ declare const DISPATCH_ACTION_KIND: {
1046
1105
  readonly ACTIVITY_INDENT: "activity-indent";
1047
1106
  readonly ACTIVITY_OUTDENT: "activity-outdent";
1048
1107
  readonly ACTIVITY_SET_PROGRESS: "activity-set-progress";
1049
- readonly ACTIVITY_PASTE: "activity-paste";
1050
1108
  readonly SELECTION_TOGGLE: "selection-toggle";
1051
1109
  readonly SELECTION_REPLACE: "selection-replace";
1052
1110
  readonly VISIBILITY_SET: "visibility-set";
@@ -1077,6 +1135,9 @@ declare const REJECTION_REASON: {
1077
1135
  readonly ACTIVITY_NOT_FOUND: "activity_not_found";
1078
1136
  readonly PARENT_NOT_FOUND: "parent_not_found";
1079
1137
  readonly ACTIVITY_IDS_EMPTY: "activity_ids_empty";
1138
+ readonly NO_ACTIVITY_SELECTION: "no_activity_selection";
1139
+ readonly CLIPBOARD_EMPTY: "clipboard_empty";
1140
+ readonly ACTIVITY_PASTE_INVARIANT_FAILED: "activity_paste_invariant_failed";
1080
1141
  readonly ANCHOR_SIBLING_CONFLICT: "anchor_sibling_conflict";
1081
1142
  readonly ANCHOR_SIBLING_NOT_FOUND: "anchor_sibling_not_found";
1082
1143
  readonly ANCHOR_SIBLING_WRONG_PARENT: "anchor_sibling_wrong_parent";
@@ -1084,6 +1145,8 @@ declare const REJECTION_REASON: {
1084
1145
  readonly CANNOT_MOVE_INTO_OWN_DESCENDANT: "cannot_move_into_own_descendant";
1085
1146
  readonly INDENT_NO_ELIGIBLE_SIBLING: "indent_no_eligible_sibling";
1086
1147
  readonly OUTDENT_ROOT_LEVEL_NOT_EDITABLE: "outdent_root_level_not_editable";
1148
+ readonly HIERARCHY_CYCLE: "hierarchy_cycle";
1149
+ readonly SANDBOX_PERSISTENCE_FORBIDDEN: "sandbox_persistence_forbidden";
1087
1150
  readonly INVALID_PROGRESS_VALUE: "invalid_progress_value_must_be_0_or_100";
1088
1151
  };
1089
1152
  type DispatchRejectReason = (typeof REJECTION_REASON)[keyof typeof REJECTION_REASON];
@@ -1097,4 +1160,4 @@ declare const DISPATCH_TRACK_EVENT: {
1097
1160
  };
1098
1161
  type DispatchTrackEvent = (typeof DISPATCH_TRACK_EVENT)[keyof typeof DISPATCH_TRACK_EVENT];
1099
1162
 
1100
- export { ACTIVITY_TYPE, type ActivityBaselineSnapshot, type ActivityBatchAction, type ActivityBatchItem, type ActivityBatchLinkInput, type ActivityBatchMode, type ActivityBatchParentReference, type ActivityBatchReference, type ActivityCreter, type ActivityId, type ActivityStatus, type ActivityType, type BackendActivityInput, type BackendCalendarExceptionInput, type BackendCalendarInput, type BackendLinkInput, type BackendScheduleInput, type BackendSectorInput, type BackendShiftInput, type BaselinePoint, type BaselineVersion, type BranchOrderChange, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, type Calendar, type CalendarId, type CalendarLike, type CalendarUnit, type CalendarWorktime, type ChangeSet, type ChangeSetSource, type ColumnName, type ConstraintType, type ConstraintWarning, type CoreActivity, type CoreBaselinePoint, type CreationKind, type CreationOverrides, type CriticalPathResult, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, type DateGesture, type DateGesturePreview, type DatesBatchVerdict, type DeletedActivitySnapshot, type DeletedLinkSnapshot, type DispatchAction, type DispatchActionKind, type DispatchOptions, type DispatchRejectReason, type DispatchResult, type DispatchTrackEvent, type EditableColumnName, type EntityChange, type ExpectedProgressAdapter, type FilterCriterion, type FilterCriterionValue, type FilterDateRange, type FilterField, type FilterOperator, type FilterState, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, type Link, type LinkBatchVerdict, type LinkId, type LinkType, type LinkTypeCode, type LinksBatchOperation, NEW_ACTIVITY_DEFAULTS, type OrderRule, type OrderState, type ParsedInput, type PastedActivityInput, type PastedLinkInput, type PendingRequest, type PersistedEntityIdentity, type PipelineColumnName, type ProjectWorkHours, REJECTION_REASON, ROOT_PARENT_ID, SCHEDULE_CORE_STATUS, STATUS, ScheduleCore, type ScheduleCoreInput, type ScheduleCoreReporter, type ScheduleCoreStatus, type ScheduleEffect, type SectorMetadata, type StaticActivityDefaults, type StatusCriteria, type TrackingEvent, type UndoOptions, type ViewStateChange, type ViewStatePropChange, WORK_TIME_DIRECTION, type WithProplannerId, type WorkTimeDirection, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };
1163
+ export { ACTIVITY_TYPE, type ActivityBaselineSnapshot, type ActivityBatchAction, type ActivityBatchItem, type ActivityBatchLinkInput, type ActivityBatchMode, type ActivityBatchParentReference, type ActivityBatchReference, type ActivityCreationOverrides, type ActivityCreter, type ActivityId, type ActivityStatus, type ActivityType, type BackendActivityInput, type BackendCalendarExceptionInput, type BackendCalendarInput, type BackendLinkInput, type BackendScheduleInput, type BackendSectorInput, type BackendShiftInput, type BaselinePoint, type BaselineVersion, type BranchOrderChange, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, type Calendar, type CalendarId, type CalendarLike, type CalendarUnit, type CalendarWorktime, type ChangeSet, type ChangeSetSource, type ColumnName, type ConstraintType, type ConstraintWarning, type CoreActivity, type CoreBaselinePoint, type CreationKind, type CriticalPathResult, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, type DateGesture, type DateGesturePreview, type DatesBatchVerdict, type DeletedActivitySnapshot, type DeletedLinkSnapshot, type DispatchAction, type DispatchActionKind, type DispatchOptions, type DispatchRejectReason, type DispatchResult, type DispatchTrackEvent, type EditableColumnName, type EffectiveGraphAudit, type EntityChange, type ExpectedProgressAdapter, type FilterCriterion, type FilterCriterionValue, type FilterDateRange, type FilterField, type FilterOperator, type FilterState, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, type Link, type LinkBatchVerdict, type LinkId, type LinkType, type LinkTypeCode, type LinksBatchOperation, NEW_ACTIVITY_DEFAULTS, type OrderRule, type OrderState, type ParsedInput, type PendingRequest, type PersistedEntityIdentity, type PipelineColumnName, type ProjectWorkHours, REJECTION_REASON, ROOT_PARENT_ID, SCHEDULE_CORE_STATUS, STATUS, ScheduleCore, type ScheduleCoreInput, type ScheduleCoreReporter, type ScheduleCoreStatus, type ScheduleEffect, type SectorMetadata, type StaticActivityDefaults, type StatusCriteria, type TrackingEvent, type UndoOptions, type ViewStateChange, type ViewStatePropChange, WORK_TIME_DIRECTION, type WithProplannerId, type WorkTimeDirection, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, willRunCriticalPath, yieldToBrowser };