@outbuild-company/schedule-core 1.0.1 → 1.1.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
@@ -5,10 +5,8 @@
5
5
  * This file is the single seam between all components. All scheduler code
6
6
  * depends ONLY on these types — never on the DHTMLX gantt object directly.
7
7
  */
8
- type ActivityId$2 = string;
8
+ type ActivityId$1 = string;
9
9
  type LinkId$1 = string;
10
- type CalendarId$2 = string;
11
-
12
10
  /** Value constants for link types. Matches `gantt.config.links`. */
13
11
  declare const LINK_TYPE: {
14
12
  readonly FINISH_TO_START: "0";
@@ -16,172 +14,10 @@ declare const LINK_TYPE: {
16
14
  readonly FINISH_TO_FINISH: "2";
17
15
  readonly START_TO_FINISH: "3";
18
16
  };
19
- /**
20
- * RAW DHTMLX row as the scheduler engine and `ScheduleState` see it:
21
- * snake_case fields, `parent` with the numeric-0 root sentinel,
22
- * `$source`/`$target` link id arrays, `duration` in HOURS, ids
23
- * `string | number`. Dates are real Date objects (not ISO strings);
24
- * serialization for JSON fixtures happens in the recording layer.
25
- * Sibling shapes: persisted `Activity` (`src/types.ts`) and the
26
- * pipelines' camelCase `ActivitySnapshot` (`src/columns/types.ts`) —
27
- * see the `Activity` docblock for the full map.
28
- */
29
- interface EngineActivitySnapshot {
30
- id: ActivityId$2;
31
- start_date: Date;
32
- end_date: Date;
33
- duration: number;
34
- type: ActivityType;
35
- parent: ActivityId$2 | 0;
36
- constraint_type: ConstraintType | null;
37
- constraint_date: Date | null;
38
- progress: number;
39
- auto_scheduling: boolean;
40
- calendar_id: CalendarId$2 | null;
41
- /** Outgoing link ids (this activity is the link source) */
42
- $source: LinkId$1[];
43
- /** Incoming link ids (this activity is the link target) */
44
- $target: LinkId$1[];
45
- /** Mirrors `Activity.is_critical` (`CriticalFlag`): boolean fresh from the
46
- * backend, `'Si'`/`'No'` after the critical-path pass. */
47
- is_critical?: boolean | 'Si' | 'No';
48
- dragged?: boolean;
49
- /**
50
- * Display/domain fields carried at runtime via the activityToSnapshot `...a`
51
- * spread; declared so state-ports reads them typed instead of casting.
52
- */
53
- text?: string;
54
- description?: string;
55
- cost?: number;
56
- used_cost?: number;
57
- real_cost?: number;
58
- hhWorkTime?: number;
59
- real_work?: number;
60
- ponderator?: number;
61
- tasks?: unknown[];
62
- real_constraint_type?: ConstraintType | null;
63
- last_constraint?: ConstraintType | null;
64
- last_constraint_date?: Date | null;
65
- last_start_date?: Date | null;
66
- date_origin?: Date | null;
67
- /**
68
- * Backend DB row id (distinct from `id` which is `unique_id`). Optional
69
- * because activities created in-session have no backend row yet.
70
- */
71
- proplannerId?: number;
72
- /** Sequential display index used as a short human-readable activity label.
73
- * `| undefined` is explicit: rollback before-images assign the prior value,
74
- * which is `undefined` for an activity that had no correlative_id yet. */
75
- correlative_id?: number | undefined;
76
- /**
77
- * Project-scoped unique identifier string, user-visible (e.g. "A-0001").
78
- * Null for activities that have not been assigned one yet.
79
- */
80
- custom_id?: string | null;
81
- /**
82
- * UUID-like correlative assigned by Outbuild. May be string or number
83
- * depending on the backend version; absent on in-session-created activities.
84
- */
85
- unique_correlative_id?: string | number | null;
86
- /**
87
- * Working-hours mirror of `duration` used by the Duration column renderer to
88
- * avoid re-computing hours from days on every render. Stamped by
89
- * `parseFromBackend`, `activityCreationPipeline`, and parent-bounds.
90
- */
91
- for_disable_milestone_duration?: number;
92
- /**
93
- * View-model visibility bit (UI filters); ex `should_be_showed` of the
94
- * DHTMLX task. `visible !== false` = visible; default true.
95
- */
96
- visible?: boolean;
97
- /** Checkbox-selection bit owned by the selection pipeline. */
98
- checked?: boolean;
99
- /** Visible (UI-layer) checkbox state, kept in sync with `checked`. */
100
- visibleChecked?: boolean;
101
- /** Signal to the bridge that `visibleChecked` was set this dispatch. */
102
- mustApplyVisibleChecked?: boolean;
103
- /**
104
- * Pending Schedule Impact Requests freezing this activity (id-only
105
- * reduction; non-empty ⇒ frozen). Carried verbatim from the backend payload.
106
- * Only for dynamic setActivityField writes + arbitrary backend passthrough;
107
- * all known fields are declared above.
108
- */
109
- pendingRequests?: PendingRequest[];
110
- earlyStart?: Date | null;
111
- earlyFinish?: Date | null;
112
- lateStart?: Date | null;
113
- lateFinish?: Date | null;
114
- totalSlack?: number | null;
115
- freeSlack?: number | null;
116
- /** Expected-progress baseline output, written by the expected-progress pass. */
117
- expected_progress?: number;
118
- /** Lookahead membership; the core derives it in promote/demote (R4). */
119
- is_lookahead?: boolean;
120
- /** Client-side "new, unsaved" marker (not persisted as such). */
121
- isNewActivity?: true | null;
122
- /** Descendant new-activity id bookkeeping (R15, temporal). */
123
- newActivitiesArray?: ActivityId$2[];
124
- /** `newActivitiesArray.length > 0` mirror (R15, temporal). */
125
- hasNewActivities?: boolean;
126
- /** Activity modification log carried from the backend. */
127
- activityModifications?: unknown[];
128
- /** Load-derived: the activity fell back to the default calendar. */
129
- assignedDefaultCalendar?: boolean;
130
- /** Backend flag: has persisted children. */
131
- has_childs?: boolean;
132
- /** Backend flag: ponderator set manually (not auto-distributed). */
133
- hasCustomPonderator?: boolean;
134
- /** Backend aggregate: recursive duration sum. */
135
- sumOfDurationRecursively?: number;
136
- /** Backend row ids (distinct from the domain `id`). */
137
- ganttId?: number;
138
- sectorId?: number;
139
- companyId?: number;
140
- /** Subcontract column id + its raw backend object. */
141
- subcontractId?: number | null;
142
- subcontract?: unknown;
143
- /** Responsibility / tag columns (arrays of backend rows). */
144
- responsables?: unknown[];
145
- tags?: unknown[];
146
- /** Active baseline points overlaid at load. */
147
- baseline_points?: BaselinePoint[];
148
- /** Backend timestamps. */
149
- createdAt?: string;
150
- updatedAt?: string;
151
- old_progress_registered?: number;
152
- old_duration_registered?: number;
153
- old_cost_registered?: number;
154
- old_used_cost_registered?: number;
155
- old_real_cost_registered?: number;
156
- old_hhWorkTime_registered?: number;
157
- /** Mirror of the constraint before the last change (constraint cluster). */
158
- constraint_type_old?: ConstraintType | null;
159
- /** `type === 'milestone'` cache flipped by the duration pipeline. */
160
- is_milestone?: boolean;
161
- /** DHTMLX markers consumed by the bridge / render layer. */
162
- $keep_constraints?: boolean;
163
- $rendered_type?: ActivityType;
164
- $no_start?: boolean;
165
- $no_end?: boolean;
166
- status?: 'Waiting' | 'Doing' | 'Done';
167
- progressSolidColor?: string;
168
- color?: string;
169
- /** Flags a recursive complete/uncomplete from the action-button flow. */
170
- progressChangedByActionButton?: boolean;
171
- custom_predecessors?: string;
172
- /** Backend typo preserved (single 'c'). */
173
- custom_sucessors?: string;
174
- start_base?: Date;
175
- end_base?: Date;
176
- duration_base?: number;
177
- cost_base?: number;
178
- work_base?: number;
179
- expected_progress_base?: number;
180
- }
181
17
  interface LinkSnapshot {
182
18
  id: LinkId$1;
183
- source: ActivityId$2;
184
- target: ActivityId$2;
19
+ source: ActivityId$1;
20
+ target: ActivityId$1;
185
21
  type: LinkType;
186
22
  lag: number;
187
23
  /**
@@ -208,6 +44,11 @@ interface LinkSnapshot {
208
44
  /** BE row id (distinct from the schedule-level `id`). */
209
45
  proplannerId?: number;
210
46
  }
47
+ /**
48
+ * Gantt-wide flags that influence scheduling decisions. Captured at the
49
+ * boundary of every scheduling run.
50
+ */
51
+ type MutableLinkField = 'lag' | 'type';
211
52
 
212
53
  /**
213
54
  * Constraint Rules — single source of truth.
@@ -259,21 +100,13 @@ declare const CONSTRAINT_TYPE: {
259
100
  * DHTMLX convention) and camelCase for everything else, per Q14 in
260
101
  * SCHEDULE_CORE_API.md.
261
102
  */
262
- type ActivityId$1 = string;
103
+ type ActivityId = string;
263
104
  type LinkId = string;
264
- type CalendarId$1 = string;
105
+ type CalendarId = string;
265
106
  type ActivityType = 'project' | 'task' | 'milestone';
266
107
 
267
108
  /** DHTMLX link kinds: 0 = FS, 1 = SS, 2 = FF, 3 = SF. */
268
109
  type LinkType = '0' | '1' | '2' | '3';
269
- /**
270
- * Critical-path output flag. Carries two historical shapes: `parseFromBackend`
271
- * stores a boolean, and the critical-path pass (`initial-passes.ts`) overwrites
272
- * it with the DHTMLX string `'Si'`/`'No'`. Both are observed at runtime (the
273
- * CP / paste tests assert against `'Si'`/`'No'`; `parseFromBackend` against
274
- * boolean), so the type unions all three rather than lying with a bare boolean.
275
- */
276
- type CriticalFlag = boolean | 'Si' | 'No';
277
110
  /** Direction for closest-work-time snapping. */
278
111
  type WorkTimeDirection = 'future' | 'past';
279
112
  declare const WORK_TIME_DIRECTION: {
@@ -351,9 +184,6 @@ interface BaselinePoint {
351
184
  * matches the backend convention. No index signature — every field is
352
185
  * explicit. New backend fields must be added here and preserved by
353
186
  * `normalize-activity.ts`.
354
- *
355
- * Companion type for runtime mutations: see `ActivityRuntime` below,
356
- * which extends this with `DhtmlxHeritageFields`.
357
187
  */
358
188
  /**
359
189
  * A pending SIR freezing an activity, reduced to the only field the core
@@ -363,121 +193,101 @@ interface BaselinePoint {
363
193
  interface PendingRequest {
364
194
  id: string;
365
195
  }
366
- /**
367
- * PUBLIC persisted domain model — what `core.getActivityView()` returns and
368
- * what the backend payload parses into. Fields are snake_case (backend +
369
- * DHTMLX convention); `duration` is in DAYS at this boundary.
370
- *
371
- * The package has three activity shapes — one per layer:
372
- * - `Activity` (this): public, persisted, snake_case.
373
- * - `ActivitySnapshot` (`src/columns/types.ts`): camelCase + derived
374
- * fields (hasChildren, isMilestone…); what column pipelines read.
375
- * Built per-read by `state-ports.ts`; never persisted.
376
- * - `EngineActivitySnapshot` (`src/autoscheduler/types.ts`): raw DHTMLX
377
- * row (snake_case + `parent`/`$source`/`$target`, hours-based
378
- * duration); what `ScheduleState` stores and the scheduler engine
379
- * consumes. Translation Activity ↔ engine: `src/dispatch/conversion.ts`.
380
- */
381
- interface Activity {
382
- id: ActivityId$1;
383
- /** Parent's `id`, or `'0'` when the activity is a root. */
384
- parent: ActivityId$1 | '0';
385
- text: string;
196
+ declare const STATUS: {
197
+ readonly DONE: "Done";
198
+ readonly OVERDUE: "Overdue";
199
+ readonly ADVANCEMENT: "Advancement";
200
+ readonly WAITING: "Waiting";
201
+ readonly DOING: "Doing";
202
+ };
203
+ type ActivityStatus = (typeof STATUS)[keyof typeof STATUS];
204
+ interface CriticalPathResult {
205
+ earlyStart: Date | null;
206
+ earlyFinish: Date | null;
207
+ lateStart: Date | null;
208
+ lateFinish: Date | null;
209
+ totalSlackHours: number | null;
210
+ }
211
+ interface ActivityBaselineSnapshot {
212
+ startDate: Date | null;
213
+ endDate: Date | null;
214
+ durationDays: number;
215
+ cost: number;
216
+ workHours: number;
217
+ }
218
+ interface CoreBaselinePoint {
219
+ startDate: Date | null;
220
+ endDate: Date | null;
221
+ durationDays: number;
222
+ cost: number;
223
+ workHours: number;
224
+ versionId: number | null;
225
+ isActiveVersion: boolean;
226
+ baseCalendarId: CalendarId | null;
227
+ hoursPerDay: number | null;
228
+ hoursPerWeek: number | null;
229
+ }
230
+ interface CoreActivity {
231
+ id: ActivityId;
232
+ proplannerId: number | null;
233
+ parentId: ActivityId | null;
234
+ name: string;
386
235
  description: string;
387
236
  type: ActivityType;
388
- start_date: Date;
389
- end_date: Date;
390
- duration: number;
391
- constraint_type: ConstraintType | null;
392
- constraint_date: Date | null;
393
- auto_scheduling: boolean;
394
- calendar_id: CalendarId$1 | null;
395
- /**
396
- * True when the activity had no valid calendar of its own and inherited the
397
- * project default at load (its backend `calendarId` was null/undefined or a
398
- * dangling reference). Set by `parseFromBackend` when `resolveCalendarId`
399
- * falls back. The legacy DHTMLX worker computed this; the core owns calendar
400
- * assignment now, so it owns the flag. The UI uses it to surface
401
- * default-assigned activities. See `CALENDARS.md`.
402
- */
403
- assignedDefaultCalendar?: boolean;
237
+ startDate: Date;
238
+ endDate: Date;
239
+ durationHours: number;
240
+ constraintType: ConstraintType | null;
241
+ constraintDate: Date | null;
242
+ autoScheduling: boolean;
243
+ calendarId: CalendarId | null;
244
+ assignedDefaultCalendar: boolean;
245
+ dateOrigin: Date | null;
404
246
  progress: number;
405
247
  cost: number;
406
- used_cost: number;
407
- real_cost: number;
408
- hhWorkTime: number;
409
- real_work: number;
248
+ usedCost: number;
249
+ realCost: number;
250
+ workHours: number;
251
+ realWorkHours: number;
410
252
  ponderator: number;
411
- correlative_id: number;
412
- is_lookahead: boolean;
413
- /**
414
- * Bit de visibilidad del view-model (filtros de UI); ex `should_be_showed`
415
- * del task DHTMLX. `visible !== false` = visible; default true. Escrito por
416
- * el intent `visibility-set` (prop-only) y por `parseFromBackend` al load.
417
- */
418
- visible?: boolean;
419
- newActivitiesArray: ActivityId$1[];
420
- activityModifications: unknown[];
421
- /**
422
- * Backend DB row id (distinct from the core `id`, which is `unique_id`).
423
- * Captured from `a.id` in `parseActivity`; `undefined` for activities
424
- * created in-session (no backend id yet). Used by save dirty-detection to
425
- * tell persisted activities from new ones. Mirrors `Link.proplannerId`.
426
- */
427
- proplannerId?: number;
428
- unique_correlative_id: string;
429
- ganttId: number;
430
- sectorId: number;
431
- companyId: number;
432
- subcontractId: number | null;
433
- subcontract: unknown;
434
- custom_id: string | null;
435
253
  hasCustomPonderator: boolean;
436
- has_childs: boolean;
437
- sumOfDurationRecursively: number;
438
- /**
439
- * Critical-path outputs (poblados cuando corre el CP: en background tras la
440
- * carga vía `criticalPathReady`, o tras cada dispatch). `undefined` si el CP
441
- * aún no corrió. `is_critical` es string DHTMLX (`'Si'`/`'No'`) post-CP,
442
- * boolean recién parseado del backend — ver `CriticalFlag`.
443
- */
444
- earlyStart?: Date | null;
445
- earlyFinish?: Date | null;
446
- lateStart?: Date | null;
447
- lateFinish?: Date | null;
448
- totalSlack?: number | null;
449
- freeSlack: number | null;
450
- is_critical: CriticalFlag;
254
+ correlativeId: number;
255
+ uniqueCorrelativeId: string;
256
+ customId: string | null;
257
+ subcontractId: number | null;
258
+ isLookahead: boolean;
259
+ hasLookaheadTasks: boolean;
260
+ newActivityIds: ActivityId[];
451
261
  hasNewActivities: boolean;
452
- isNewActivity: true | null;
453
- date_origin?: Date | null;
454
- /**
455
- * Active-baseline snapshots for this activity (backend
456
- * `sectorbaselinepoint[]`). Passthrough — carried verbatim so the
457
- * frontend baseline columns and the ponderator computation can read the
458
- * ACTIVE point via `getActiveBaseline`. `undefined` when the activity has
459
- * no baseline (e.g. created in-session after the snapshot).
460
- */
461
- baseline_points?: BaselinePoint[];
462
- tasks: unknown[];
463
- responsables: unknown[];
464
- tags: unknown[];
465
- /**
466
- * Pending Schedule Impact Requests (SIRs) freezing this activity. The
467
- * schedule load path (`sector.controller.js`) already filters to
468
- * `state==='pending'` and sends `{ id }` only, so the core stores just the
469
- * id — enough to name the SIR when emitting a `sir-auto-reject` effect.
470
- * Non-empty ⇒ the activity is frozen (`isFrozen`). The full SIR record lives
471
- * in the front's Redux, not here. See `SIR_MAP.md`.
472
- */
473
- pendingRequests: PendingRequest[];
474
- createdAt: string;
475
- updatedAt: string;
262
+ isNewActivity?: true | null;
263
+ pendingRequestIds: string[];
264
+ responsableIds: string[];
265
+ tagIds: string[];
266
+ baselinePoints: CoreBaselinePoint[];
267
+ baselineSnapshot: ActivityBaselineSnapshot | null;
268
+ recursiveDurationHours: number;
269
+ isCritical: boolean;
270
+ freeSlackHours: number | null;
271
+ expectedProgress: number | null;
272
+ expectedProgressBaseline: number | null;
273
+ status: ActivityStatus | null;
274
+ criticalPath: CriticalPathResult | null;
275
+ /** Internal reversible leaf→project promotion state; never serialized. */
276
+ promotionRestore: {
277
+ type: 'task' | 'milestone';
278
+ startDate: Date;
279
+ endDate: Date;
280
+ durationHours: number;
281
+ expectedProgressBaseline: number | null;
282
+ constraintType: ConstraintType;
283
+ constraintDate: Date | null;
284
+ progress: number;
285
+ } | null;
476
286
  }
477
287
  interface Link {
478
288
  id: LinkId;
479
- source: ActivityId$1;
480
- target: ActivityId$1;
289
+ source: ActivityId;
290
+ target: ActivityId;
481
291
  type: LinkType;
482
292
  lag: number;
483
293
  ganttId?: number;
@@ -494,10 +304,12 @@ interface CalendarWorktime {
494
304
  * (supports per-day variation, e.g. a short Friday,
495
305
  * and multi-shift split days like `["8-12","13-17"]`)
496
306
  *
497
- * Single source of truth: this is exactly what `parseFromBackend` emits —
498
- * a working day ALWAYS carries its resolved windows (the parser resolves
499
- * the default-hours fallback at parse time). The vendored work-calendar
500
- * engine natively also accepts a boolean `true` per day (DHTMLX
307
+ * Single source of truth: this is exactly what `parseFromBackend` emits. A
308
+ * usable working day carries its resolved windows; `[]` is reserved for a
309
+ * catalog calendar that declares the day as working but provides no usable
310
+ * shift anywhere. Those catalog-only calendars remain selectable/persistable
311
+ * but are deliberately not registered as arithmetic calendars. The vendored
312
+ * work-calendar engine natively also accepts a boolean `true` per day (DHTMLX
501
313
  * contract), but that form never appears in the domain `Calendar`; it is
502
314
  * reserved for the engine-facing internals (`SnapshotWorktime`,
503
315
  * synthetic replay fixtures).
@@ -508,8 +320,8 @@ interface CalendarWorktime {
508
320
  days: Array<false | string[]>;
509
321
  /**
510
322
  * Default working-hour windows (`"HH:MM-HH:MM"`). Used as the engine's
511
- * global fallback. `parseFromBackend` sets it to the first working day's
512
- * windows.
323
+ * global fallback. `parseFromBackend` sets it to the first usable working
324
+ * day's windows, or `[]` when the calendar has no usable shift.
513
325
  */
514
326
  hours: string[];
515
327
  /**
@@ -523,7 +335,7 @@ interface CalendarWorktime {
523
335
  * - `string[]` → use these `"HH:MM-HH:MM"` windows instead
524
336
  * of the default `hours`
525
337
  *
526
- * Source: `BackendCalendar.exceptiondays[]` after the adapter expands
338
+ * Source: `BackendCalendarInput.exceptiondays[]` after the adapter expands
527
339
  * `from_date`/`to_date` ranges into individual UTC days.
528
340
  */
529
341
  dates?: Record<string, false | string[]>;
@@ -531,7 +343,7 @@ interface CalendarWorktime {
531
343
  customWeeks?: Record<string, unknown>;
532
344
  }
533
345
  interface Calendar {
534
- id: CalendarId$1;
346
+ id: CalendarId;
535
347
  /** Display name. Used by the DHTMLX calendar-selector column. */
536
348
  name: string;
537
349
  worktime: CalendarWorktime;
@@ -613,6 +425,68 @@ interface EntityChange<T> {
613
425
  after: Readonly<T> | null;
614
426
  }
615
427
 
428
+ declare const COLUMN: {
429
+ readonly REAL_WORK: "real_work";
430
+ readonly REAL_COST: "real_cost";
431
+ readonly EXPECTED_PROGRESS: "expected_progress";
432
+ readonly EXPECTED_PROGRESS_BASE: "expected_progress_base";
433
+ readonly START_BASE: "start_base";
434
+ readonly END_BASE: "end_base";
435
+ readonly DURATION_BASE: "duration_base";
436
+ readonly COST_BASE: "cost_base";
437
+ readonly WORK_BASE: "work_base";
438
+ readonly CALENDAR_DURATION: "calendarDuration";
439
+ readonly IS_CRITICAL: "is_critical";
440
+ readonly EARLY_START: "earlyStart";
441
+ readonly EARLY_FINISH: "earlyFinish";
442
+ readonly LATE_START: "lateStart";
443
+ readonly LATE_FINISH: "lateFinish";
444
+ readonly FREE_SLACK: "freeSlack";
445
+ readonly TOTAL_SLACK: "totalSlack";
446
+ readonly CORRELATIVE_ID: "correlative_id";
447
+ readonly UNIQUE_CORRELATIVE_ID: "unique_correlative_id";
448
+ readonly PONDERATOR: "ponderator";
449
+ readonly STATUS: "status";
450
+ readonly TEXT: "text";
451
+ readonly DESCRIPTION: "description";
452
+ readonly DURATION: "duration";
453
+ readonly PROGRESS: "progress";
454
+ readonly COST: "cost";
455
+ readonly USED_COST: "used_cost";
456
+ readonly HH_WORK_TIME: "hhWorkTime";
457
+ readonly START_DATE: "start_date";
458
+ readonly END_DATE: "end_date";
459
+ readonly CONSTRAINT_TYPE: "constraint_type";
460
+ readonly CONSTRAINT_DATE: "constraint_date";
461
+ readonly CALENDAR_ID: "calendar_id";
462
+ readonly CUSTOM_ID: "custom_id";
463
+ readonly SUBCONTRACT_ID: "subcontractId";
464
+ readonly RESPONSABLES: "responsables";
465
+ readonly TAGS: "tags";
466
+ readonly CUSTOM_PREDECESSORS: "custom_predecessors";
467
+ readonly CUSTOM_SUCESSORS: "custom_sucessors";
468
+ };
469
+ type ColumnName = (typeof COLUMN)[keyof typeof COLUMN];
470
+
471
+ /**
472
+ * Task creation pipeline — types.
473
+ *
474
+ * Ports the pure parts of `src/assets/js/custom_actions/createTask/` into a
475
+ * functional pipeline that replay tests (and eventually prod) can invoke
476
+ * against an adapter instead of the live gantt.
477
+ */
478
+
479
+ /**
480
+ * Closed, canonical contract for create/paste overrides: camelCase, working
481
+ * hours, limited to the fields a caller may seed on a new activity. Identity
482
+ * and structure (`id`/`parentId`/`correlativeId`/`uniqueCorrelativeId`),
483
+ * derived/CP/baseline outputs and view-state are NOT overridable. PP2 adapts
484
+ * its own vocabulary to this contract in step 9.
485
+ */
486
+ declare const CREATION_OVERRIDE_FIELD_LIST: readonly ["name", "description", "type", "startDate", "durationHours", "constraintType", "constraintDate", "calendarId", "assignedDefaultCalendar", "autoScheduling", "progress", "cost", "usedCost", "realCost", "workHours", "realWorkHours", "ponderator", "hasCustomPonderator", "customId", "subcontractId", "responsableIds", "tagIds", "isLookahead"];
487
+ type CreationOverrideField = (typeof CREATION_OVERRIDE_FIELD_LIST)[number];
488
+ type CreationOverrides = Partial<Pick<CoreActivity, CreationOverrideField>>;
489
+
616
490
  /**
617
491
  * Public dispatch types — see Q8/Q9/Q10 in SCHEDULE_CORE_API.md.
618
492
  *
@@ -635,8 +509,8 @@ interface EntityChange<T> {
635
509
  */
636
510
  type LinksBatchOperation = {
637
511
  kind: 'create';
638
- source: ActivityId$1;
639
- target: ActivityId$1;
512
+ source: ActivityId;
513
+ target: ActivityId;
640
514
  type: LinkType;
641
515
  lag?: number;
642
516
  linkId?: LinkId;
@@ -652,7 +526,7 @@ type LinksBatchOperation = {
652
526
 
653
527
  type DispatchAction = {
654
528
  kind: 'inline-edit';
655
- activityId: ActivityId$1;
529
+ activityId: ActivityId;
656
530
  column: string;
657
531
  newValue: unknown;
658
532
  } | {
@@ -665,7 +539,7 @@ type DispatchAction = {
665
539
  */
666
540
  kind: 'dates-batch';
667
541
  edits: ReadonlyArray<{
668
- activityId: ActivityId$1;
542
+ activityId: ActivityId;
669
543
  column: 'start_date' | 'end_date';
670
544
  newValue: unknown;
671
545
  }>;
@@ -687,15 +561,15 @@ type DispatchAction = {
687
561
  */
688
562
  kind: 'bulk-edit';
689
563
  edits: ReadonlyArray<{
690
- activityId: ActivityId$1;
564
+ activityId: ActivityId;
691
565
  column: string;
692
566
  newValue: unknown;
693
567
  }>;
694
568
  eventSource?: string;
695
569
  } | {
696
570
  kind: 'link-create';
697
- source: ActivityId$1;
698
- target: ActivityId$1;
571
+ source: ActivityId;
572
+ target: ActivityId;
699
573
  type: LinkType;
700
574
  /** Lag in DAYS (public boundary unit; converted to working hours inside). */
701
575
  lag: number;
@@ -717,7 +591,7 @@ type DispatchAction = {
717
591
  } | {
718
592
  kind: 'activity-create';
719
593
  /** Where to put the new activity. Use `'0'` for root. */
720
- parentId: ActivityId$1 | '0';
594
+ parentId: ActivityId | '0';
721
595
  /**
722
596
  * Optional — insert the new activity immediately AFTER this sibling.
723
597
  * If omitted (and `beforeSiblingId` also omitted), the new activity
@@ -725,7 +599,7 @@ type DispatchAction = {
725
599
  * currently be a child of `parentId`, otherwise the dispatch is
726
600
  * rejected. Mutually exclusive with `beforeSiblingId`.
727
601
  */
728
- afterSiblingId?: ActivityId$1 | undefined;
602
+ afterSiblingId?: ActivityId | undefined;
729
603
  /**
730
604
  * Optional — insert the new activity immediately BEFORE this sibling.
731
605
  * Use case: "insert as first child" (`beforeSiblingId = currentFirstChild`)
@@ -733,25 +607,20 @@ type DispatchAction = {
733
607
  * The sibling must currently be a child of `parentId`, otherwise the
734
608
  * dispatch is rejected. Mutually exclusive with `afterSiblingId`.
735
609
  */
736
- beforeSiblingId?: ActivityId$1 | undefined;
610
+ beforeSiblingId?: ActivityId | undefined;
737
611
  /**
738
- * Optional field overrides applied on top of the defaults built by
739
- * the creation pipeline. Common cases: `text`, `duration`,
740
- * `start_date`, `constraint_type`, `constraint_date`, `calendar_id`.
741
- *
742
- * Only keys that name a real model field are honored — the pipeline
743
- * drops any incidental non-model key (dhtmlx runtime junk, lightbox UI
744
- * state) so it can never phantom onto the created activity. `name` is
745
- * accepted as an alias for `text` (mapped, then dropped as a raw key).
746
- * See `isDroppableOverrideKey` in `creation/defaults.ts`.
612
+ * Canonical field overrides applied on top of the creation defaults —
613
+ * camelCase, working hours, limited to creation-writable fields
614
+ * (`CreationOverrides`). Identity/structure and derived outputs are not
615
+ * overridable.
747
616
  */
748
- overrides?: Partial<Activity>;
617
+ overrides?: CreationOverrides;
749
618
  /**
750
619
  * Deterministic activity id — used by tests and by replay flows
751
620
  * (paste, undo) that need to assign a specific id. If omitted, the
752
621
  * core's internal id generator allocates one.
753
622
  */
754
- activityId?: ActivityId$1;
623
+ activityId?: ActivityId;
755
624
  /**
756
625
  * Where this create originated from — passed through to the
757
626
  * `schedule_activity_creation` Amplitude event. Free-form string
@@ -766,7 +635,7 @@ type DispatchAction = {
766
635
  * Operation is atomic — if any id is missing, the whole dispatch is
767
636
  * rejected before mutating anything.
768
637
  */
769
- activityIds: ReadonlyArray<ActivityId$1>;
638
+ activityIds: ReadonlyArray<ActivityId>;
770
639
  eventSource?: string;
771
640
  } | {
772
641
  kind: 'activity-move';
@@ -774,16 +643,17 @@ type DispatchAction = {
774
643
  * The activity to move. Single-id only — for batch reorder use
775
644
  * multiple dispatches (each one observes the post-previous state).
776
645
  */
777
- activityId: ActivityId$1;
646
+ activityId: ActivityId;
778
647
  /** Destination parent. Same as current parent = reorder within. */
779
- parentId: ActivityId$1 | '0';
648
+ parentId: ActivityId | '0';
780
649
  /**
781
650
  * Optional — position the moved activity immediately below this
782
651
  * sibling. If omitted, appended as the last child of `parentId`.
783
652
  * The sibling must currently be a child of `parentId`; otherwise
784
- * the dispatch is rejected.
653
+ * the dispatch is rejected. Mutually exclusive with `beforeSiblingId`.
785
654
  */
786
- afterSiblingId?: ActivityId$1;
655
+ afterSiblingId?: ActivityId;
656
+ beforeSiblingId?: ActivityId;
787
657
  eventSource?: string;
788
658
  } | {
789
659
  kind: 'activity-indent';
@@ -793,7 +663,7 @@ type DispatchAction = {
793
663
  * selected set, so consecutive selected siblings all land under the
794
664
  * same anchor (matches legacy `findPreviousNonSelectedSibling`).
795
665
  */
796
- activityIds: ReadonlyArray<ActivityId$1>;
666
+ activityIds: ReadonlyArray<ActivityId>;
797
667
  eventSource?: string;
798
668
  } | {
799
669
  kind: 'activity-outdent';
@@ -802,7 +672,7 @@ type DispatchAction = {
802
672
  * selected siblings via initial-index capture (matches legacy
803
673
  * `initialFirstSiblings` + `initialTaskIndexes` pre-loop setup).
804
674
  */
805
- activityIds: ReadonlyArray<ActivityId$1>;
675
+ activityIds: ReadonlyArray<ActivityId>;
806
676
  eventSource?: string;
807
677
  } | {
808
678
  /**
@@ -825,7 +695,7 @@ type DispatchAction = {
825
695
  * with newValue=0 or newValue=100.
826
696
  */
827
697
  kind: 'activity-set-progress';
828
- activityId: ActivityId$1;
698
+ activityId: ActivityId;
829
699
  /** Strictly 0 (uncomplete) or 100 (complete). */
830
700
  newValue: 0 | 100;
831
701
  eventSource?: string;
@@ -842,7 +712,7 @@ type DispatchAction = {
842
712
  * critical path.
843
713
  */
844
714
  kind: 'selection-toggle';
845
- activityId: ActivityId$1;
715
+ activityId: ActivityId;
846
716
  /** Checkbox state AFTER the user click. */
847
717
  isChecked: boolean;
848
718
  /**
@@ -851,7 +721,7 @@ type DispatchAction = {
851
721
  * is load-time-stale until TODO #10). When omitted, the core
852
722
  * falls back to its own snapshots.
853
723
  */
854
- frozenIds?: ReadonlyArray<ActivityId$1>;
724
+ frozenIds?: ReadonlyArray<ActivityId>;
855
725
  /**
856
726
  * Enable the upward auto-check of ancestors when all their
857
727
  * checkable children become selected. Mirrors the (inverted)
@@ -867,7 +737,7 @@ type DispatchAction = {
867
737
  * `selection-toggle`.
868
738
  */
869
739
  kind: 'selection-replace';
870
- activityIds: ReadonlyArray<ActivityId$1>;
740
+ activityIds: ReadonlyArray<ActivityId>;
871
741
  eventSource?: string;
872
742
  } | {
873
743
  /**
@@ -881,7 +751,7 @@ type DispatchAction = {
881
751
  * path, no undo step. Idempotent.
882
752
  */
883
753
  kind: 'visibility-set';
884
- visibleIds: ReadonlyArray<ActivityId$1>;
754
+ visibleIds: ReadonlyArray<ActivityId>;
885
755
  eventSource?: string;
886
756
  } | {
887
757
  /**
@@ -893,9 +763,21 @@ type DispatchAction = {
893
763
  * ChangeSet; no autoscheduler, no CP. Idempotent.
894
764
  */
895
765
  kind: 'sir-sync';
896
- activityId: ActivityId$1;
766
+ activityId: ActivityId;
897
767
  pendingRequests: ReadonlyArray<PendingRequest>;
898
768
  eventSource?: string;
769
+ } | {
770
+ /**
771
+ * Synchronize the schedule-side flags owned by Lookahead task
772
+ * creation/deletion. The Lookahead records remain at the application
773
+ * boundary; the core owns these flags because they affect schedule
774
+ * editing rules and the public activity view.
775
+ */
776
+ kind: 'activity-lookahead-sync';
777
+ activityIds: ReadonlyArray<ActivityId>;
778
+ isLookahead: boolean;
779
+ hasLookaheadTasks: boolean;
780
+ eventSource?: string;
899
781
  } | {
900
782
  /**
901
783
  * Bulk paste (2026-06-08). Creates N activities (preserving the
@@ -920,22 +802,24 @@ type DispatchAction = {
920
802
  * is derived from the sibling.
921
803
  */
922
804
  destination: {
923
- parentId: ActivityId$1 | '0';
805
+ parentId: ActivityId | '0';
924
806
  index: number;
925
807
  } | {
926
- afterSiblingId: ActivityId$1;
808
+ afterSiblingId: ActivityId;
927
809
  };
928
810
  /**
929
811
  * The activity the paste is anchored to (the single selected row).
930
812
  * Used as the custom_id reference for pasted children. Replaces
931
813
  * the legacy `gantt.pasteReferenceActivity` instance flag.
932
814
  */
933
- referenceActivityId: ActivityId$1;
815
+ referenceActivityId: ActivityId;
934
816
  /**
935
817
  * Activities to create, in tree order (parents before children).
936
818
  * `originalId` / `originalParentId` are the ids from the copied
937
819
  * payload; the core remaps them to freshly allocated ids and uses
938
- * the remap to re-hang the hierarchy and the links.
820
+ * the remap to re-hang the hierarchy and the links. A pasted activity
821
+ * may carry its visible baseline snapshot, but it is not enrolled in an
822
+ * already-created historical baseline.
939
823
  */
940
824
  activities: ReadonlyArray<PastedActivityInput>;
941
825
  /**
@@ -947,26 +831,30 @@ type DispatchAction = {
947
831
  eventSource?: string;
948
832
  };
949
833
  interface PastedActivityInput {
950
- readonly originalId: ActivityId$1;
951
- readonly originalParentId: ActivityId$1 | '0';
952
- readonly overrides: Partial<Activity>;
834
+ readonly originalId: ActivityId;
835
+ readonly originalParentId: ActivityId | '0';
836
+ /**
837
+ * Optional explicit destination id. Production normally omits it and lets
838
+ * the adapter allocate; recorder replay supplies MAIN's observed id so the
839
+ * whole-tree oracle can compare identity without an invented id remap.
840
+ */
841
+ readonly activityId?: ActivityId;
842
+ readonly overrides: CreationOverrides;
843
+ readonly baselineSnapshot?: ActivityBaselineSnapshot | null;
953
844
  }
954
845
  interface PastedLinkInput {
955
- readonly source: ActivityId$1;
956
- readonly target: ActivityId$1;
846
+ readonly source: ActivityId;
847
+ readonly target: ActivityId;
957
848
  readonly type: LinkType;
958
849
  /** Lag in DAYS (public boundary unit; converted to working hours inside). */
959
850
  readonly lag: number;
851
+ readonly linkId?: LinkId;
960
852
  }
961
- /** Unit of duration/lag at the public boundary. Default 'days'. */
962
- type OutputUnit = 'days' | 'hours';
963
853
  interface DispatchOptions {
964
854
  /** Skip the autoscheduler pass after the mutation. Default: false. */
965
855
  skipAutoSchedule?: boolean;
966
856
  /** Skip the CP recompute after the mutation. Default: false. */
967
857
  skipCriticalPath?: boolean;
968
- /** 'days' default; the DHTMLX bridge passes 'hours' to skip conversion. */
969
- outputUnit?: OutputUnit;
970
858
  /**
971
859
  * Unit of the INPUT `newValue` for unit-bearing inline-edit columns (today:
972
860
  * duration). Default 'days' (public contract; card + tests send days). The
@@ -974,7 +862,7 @@ interface DispatchOptions {
974
862
  * the bridge passes 'hours' for those edits → the pipeline skips the days→hours
975
863
  * conversion instead of double-converting.
976
864
  */
977
- inputUnit?: OutputUnit;
865
+ inputUnit?: 'days' | 'hours';
978
866
  }
979
867
  type DispatchResult = {
980
868
  ok: true;
@@ -994,7 +882,7 @@ type DispatchResult = {
994
882
  * handlers (delete/move/paste); stripped before the result reaches the
995
883
  * bridge in the Wave-3 integration.
996
884
  */
997
- __beforeSnap?: ReadonlyMap<string, EngineActivitySnapshot>;
885
+ __beforeSnap?: ReadonlyMap<string, CoreActivity>;
998
886
  /**
999
887
  * INTERNAL (undo / B4). Incident links of deleted activities, keyed by
1000
888
  * STRING id (EntityChange link ids are String()-normalized). Carries the
@@ -1030,7 +918,7 @@ interface TrackingEvent {
1030
918
  */
1031
919
  type ScheduleEffect = {
1032
920
  kind: 'sir-auto-reject';
1033
- activityId: ActivityId$1;
921
+ activityId: ActivityId;
1034
922
  /** Backend SIR id == the front Redux item id (see parseFromBackend A1). */
1035
923
  sirId: string;
1036
924
  reason: 'date_changed' | 'activity_deleted';
@@ -1044,13 +932,22 @@ type ScheduleEffect = {
1044
932
  */
1045
933
  interface ConstraintWarning {
1046
934
  kind: 'constraint_violation';
1047
- activityId: ActivityId$1;
935
+ activityId: ActivityId;
1048
936
  constraintType: ConstraintType;
1049
937
  constraintDate: Date;
1050
938
  /** The projected date that violated (start or end, per constraint type). */
1051
939
  projectedDate: Date;
1052
940
  messageKey: string;
1053
941
  }
942
+ interface ViewStatePropChange {
943
+ readonly before: boolean;
944
+ readonly after: boolean;
945
+ }
946
+ interface ViewStateChange {
947
+ readonly activityId: ActivityId;
948
+ readonly checked?: ViewStatePropChange;
949
+ readonly visible?: ViewStatePropChange;
950
+ }
1054
951
  interface ChangeSet {
1055
952
  source: DispatchAction | {
1056
953
  kind: 'init';
@@ -1059,10 +956,11 @@ interface ChangeSet {
1059
956
  } | {
1060
957
  kind: 'redo';
1061
958
  };
1062
- activities: ReadonlyArray<EntityChange<Activity>>;
959
+ activities: ReadonlyArray<EntityChange<CoreActivity>>;
1063
960
  links: ReadonlyArray<EntityChange<Link>>;
1064
961
  calendars: ReadonlyArray<EntityChange<Calendar>>;
1065
962
  trackingEvents: ReadonlyArray<TrackingEvent>;
963
+ viewState?: ReadonlyArray<ViewStateChange>;
1066
964
  /**
1067
965
  * Optional — present only when the dispatch produced side effects. Builders
1068
966
  * that emit none omit it; consumers read `changeSet.effects ?? []`. Kept
@@ -1083,133 +981,69 @@ interface ProjectWorkHours {
1083
981
  endHour: string;
1084
982
  }
1085
983
 
1086
- /**
1087
- * Backend payload shapes — exactly as the Outbuild server returns.
1088
- *
1089
- * The core accepts these directly in the constructor and parses them into
1090
- * normalized internal types. Keeping these as the public input type means
1091
- * any consumer of the schedule API (frontend, node_server, future) speaks
1092
- * the same contract.
1093
- *
1094
- * Validated against the real mocks in
1095
- * `packages/schedule-core/src/testing/projects/startDate/`.
1096
- */
1097
-
1098
- /** Calendar shift definition — one shift per day, CSV-encoded strings. */
1099
- interface BackendShift {
1100
- id: number;
1101
- /**
1102
- * Encoded shift string for the week:
1103
- * `false,8:00,8:00,8:00,8:00,8:00,false-false,16:00,...,false`
1104
- * left side = starts, right side = ends, each CSV is Sun..Sat.
1105
- * `false` means non-working day.
1106
- */
984
+ interface BackendShiftInput {
1107
985
  shift_string: string;
1108
- correlative_id: number;
1109
- createdAt: string;
1110
- updatedAt: string;
1111
- calendarId: number;
1112
- calendarexceptiondayId: number | null;
1113
986
  }
1114
- /** Backend calendar exception (per-date override). */
1115
- interface BackendCalendarException {
1116
- id: number;
1117
- date: string;
1118
- /** Optional shifts for this specific exception. */
1119
- shifts?: BackendShift[];
1120
- [key: string]: unknown;
987
+ interface BackendCalendarExceptionInput {
988
+ from_date: string;
989
+ to_date: string;
990
+ workable: boolean;
991
+ shifts?: BackendShiftInput[];
1121
992
  }
1122
- /** Calendar as returned by the server. */
1123
- interface BackendCalendar {
993
+ interface BackendCalendarInput {
1124
994
  id: number;
1125
995
  name: string;
1126
- unique_id: number;
1127
996
  is_default: boolean;
1128
- /** CSV of Sun..Sat: `"0,1,1,1,1,1,0"` (0 = non-working, 1 = working). */
997
+ baseDefault?: boolean;
1129
998
  working_days: string;
1130
- /** CSV of shift starts per day: `"false,8:00,8:00,8:00,8:00,8:00,false"`. */
1131
- shift_start: string;
1132
- /** CSV of shift ends per day: `"false,16:00,...,false"`. */
1133
- shift_end: string;
1134
- exceptiondays: BackendCalendarException[];
1135
- baseexceptiondays?: BackendCalendarException[];
1136
- shifts: BackendShift[];
1137
- status: boolean;
1138
- companyId: number;
1139
- ganttId: number | null;
1140
- userId: number;
1141
- sectorId: number;
1142
- createdAt: string;
1143
- updatedAt: string;
1144
- [key: string]: unknown;
999
+ shift_start: string | null;
1000
+ shift_end: string | null;
1001
+ shifts: BackendShiftInput[];
1002
+ exceptiondays: BackendCalendarExceptionInput[];
1003
+ baseexceptiondays?: BackendCalendarExceptionInput[];
1145
1004
  }
1146
- /**
1147
- * Activity exactly as the Outbuild server returns it — the raw, untrusted
1148
- * input boundary. Dates are strings, `duration` is in backend DAYS, and field
1149
- * names are the backend's (snake_case, `unique_id`, `parent_id`, `name`).
1150
- *
1151
- * `parseFromBackend` is the only place that consumes it: it validates and
1152
- * normalizes each row into the internal model. Nothing else in the core should
1153
- * read a `BackendActivityInput` after parse.
1154
- */
1155
1005
  interface BackendActivityInput {
1156
- /** Database row id. Distinct from `unique_id`. */
1157
1006
  id: number;
1158
- /** Canonical schedule id (used by links and DHTMLX). String-encoded number. */
1159
1007
  unique_id: string;
1160
- /** Parent's `unique_id`, or `"0"` for root. */
1161
1008
  parent_id: string;
1162
1009
  unique_correlative_id: string;
1163
1010
  correlative_id: number;
1164
1011
  name: string;
1165
- description: string;
1012
+ description: string | null;
1166
1013
  type: 'project' | 'task' | 'milestone';
1167
- /** Format: `"YYYY/MM/DD H:MM"` (server local, see dateFormat in sector). */
1168
1014
  start_date: string;
1169
1015
  end_date: string;
1170
1016
  duration: number;
1171
- /**
1172
- * Constraint label in plain English: `"As soon As Possible"`,
1173
- * `"Start no earlier than"`, etc. Mapped to internal `ConstraintType`.
1174
- */
1175
- constraint: string;
1176
- /** Optional constraint date — server uses ISO 8601 or null. */
1017
+ constraint: string | null;
1177
1018
  constraint_date?: string | null;
1178
1019
  progress: number;
1179
1020
  cost: number;
1180
- used_cost: number;
1181
- real_cost: number;
1021
+ used_cost: number | null;
1022
+ real_cost: number | null;
1182
1023
  hhWorkTime: number;
1183
- real_work: number;
1184
- ponderator: number;
1024
+ real_work: number | null;
1025
+ ponderator: number | null;
1185
1026
  hasCustomPonderator: boolean;
1186
1027
  has_childs: boolean;
1187
1028
  isOnLookahead: boolean;
1188
- sumOfDurationRecursively: number;
1029
+ sumOfDurationRecursively: number | null;
1189
1030
  freeSlack: number | null;
1190
1031
  is_critical: boolean;
1191
- newActivitiesArray: string;
1192
- hasNewActivities: boolean;
1032
+ newActivitiesArray: string | (string | number)[] | null;
1033
+ hasNewActivities: boolean | null;
1193
1034
  isNewActivity: true | null;
1194
1035
  custom_id: string | null;
1195
1036
  ganttId: number;
1196
1037
  sectorId: number;
1197
1038
  companyId: number;
1198
- calendarId: number;
1039
+ calendarId: number | null;
1199
1040
  subcontractId: number | null;
1200
- /**
1201
- * Visibility bit of the legacy view-model. Historically NEVER sent by the
1202
- * backend (0 of ~105k activities across the captured seeds carry it) — the
1203
- * legacy client hardcoded `should_be_showed: true` at parse. Declared so
1204
- * `parseActivity` can map it to `visible` if it ever arrives; absent/null
1205
- * defaults to visible.
1206
- */
1207
- should_be_showed?: boolean;
1041
+ should_be_showed?: boolean | null;
1208
1042
  tasks: unknown[];
1209
1043
  responsables: unknown[];
1210
1044
  tags: unknown[];
1211
1045
  activitymodifications: unknown[];
1212
- pendingRequests: readonly {
1046
+ pendingRequests?: readonly {
1213
1047
  id?: unknown;
1214
1048
  }[];
1215
1049
  subcontract: unknown;
@@ -1217,10 +1051,8 @@ interface BackendActivityInput {
1217
1051
  baseline_points?: BaselinePoint[];
1218
1052
  createdAt: string;
1219
1053
  updatedAt: string;
1220
- /** Custom fields the backend may include — passed through opaquely. */
1221
- [key: string]: unknown;
1222
1054
  }
1223
- interface BackendLink {
1055
+ interface BackendLinkInput {
1224
1056
  id: number | string;
1225
1057
  unique_id?: string | null;
1226
1058
  source_id?: string;
@@ -1228,116 +1060,32 @@ interface BackendLink {
1228
1060
  source?: number | string;
1229
1061
  target?: number | string;
1230
1062
  type?: unknown;
1231
- lag: number;
1063
+ lag: number | null;
1232
1064
  ganttId?: number;
1233
1065
  sectorId?: number;
1234
1066
  }
1235
- /** Sector metadata — project-level config from the server. */
1236
- interface BackendSector {
1067
+ interface BackendSectorInput {
1237
1068
  id: number;
1238
1069
  name: string;
1239
- description: string | null;
1240
- status: boolean;
1241
- set_current: boolean;
1242
- visible: boolean;
1243
- order: number;
1244
- productive: boolean;
1245
1070
  hoursPerDay: number;
1246
1071
  hoursPerWeek: number;
1247
- accumulatedDuration: number;
1248
- /** Date format string used by the backend, e.g. `"DD/MM/YY hh:mm"`. */
1249
1072
  dateFormat: string;
1250
- didCloseWeek: string | null;
1251
- currentClosedWeek: string | null;
1252
- expectedProgress: number;
1253
- /**
1254
- * Legacy Primavera-import flag. When true, the stored `duration` of each
1255
- * activity may not match the calendar (Primavera stores end-driven
1256
- * durations); the core recomputes duration from start/end at load. ~218
1257
- * production sectors carry it (active). See `Obsidian:newPlanSchedule/CALENDARS.md`.
1258
- */
1259
- update_duration_for_primavera_for_end_date?: boolean | null;
1260
- companyId: number;
1261
1073
  projectId: number;
1262
- version: string;
1263
- createdAt: string;
1264
- updatedAt: string;
1265
- /** Calendars nested inside sector when the sector-fetch endpoint is used. */
1266
- calendars?: BackendCalendar[];
1267
- [key: string]: unknown;
1268
- }
1269
- /** Optional sibling payloads the API often returns alongside the sector. */
1270
- interface BackendScheduleImpactRequests {
1271
- pending: unknown[];
1272
- approved: unknown[];
1273
- rejected: unknown[];
1074
+ companyId: number;
1075
+ update_duration_for_primavera_for_end_date?: boolean | null;
1076
+ activity_creter?: string | null;
1077
+ custom_id_prefix?: string | null;
1078
+ custom_id_increment?: string | number | null;
1079
+ calendars?: BackendCalendarInput[];
1274
1080
  }
1275
- /** Complete server payload accepted by `ScheduleCore`. */
1276
- interface BackendInput {
1277
- sector: BackendSector;
1081
+ interface BackendScheduleInput {
1082
+ sector: BackendSectorInput;
1278
1083
  activities: BackendActivityInput[];
1279
- links: BackendLink[];
1280
- /**
1281
- * Calendars come either inside `sector.calendars` or as a sibling array.
1282
- * If both are present, the sibling array wins.
1283
- */
1284
- calendars?: BackendCalendar[] | undefined;
1285
- /**
1286
- * Baseline calendars, RAW from the backend's `showBaseCalendar` endpoint
1287
- * (exceptions under `baseexceptiondays`, `is_default`, no `-base` suffix).
1288
- * Parsed into a separate `ParsedInput.baseCalendars` collection — never
1289
- * mixed into the scheduling calendars. The core owns their reshape /
1290
- * differentiation (previously done by the frontend `refreshCalendarsRewrite`).
1291
- */
1292
- baseCalendars?: BackendCalendar[] | undefined;
1084
+ links: BackendLinkInput[];
1085
+ calendars?: BackendCalendarInput[] | undefined;
1086
+ baseCalendars?: BackendCalendarInput[] | undefined;
1293
1087
  }
1294
1088
 
1295
- declare const COLUMN: {
1296
- readonly REAL_WORK: "real_work";
1297
- readonly REAL_COST: "real_cost";
1298
- readonly EXPECTED_PROGRESS: "expected_progress";
1299
- readonly EXPECTED_PROGRESS_BASE: "expected_progress_base";
1300
- readonly START_BASE: "start_base";
1301
- readonly END_BASE: "end_base";
1302
- readonly DURATION_BASE: "duration_base";
1303
- readonly COST_BASE: "cost_base";
1304
- readonly WORK_BASE: "work_base";
1305
- readonly CALENDAR_DURATION: "calendarDuration";
1306
- readonly IS_CRITICAL: "is_critical";
1307
- readonly EARLY_START: "earlyStart";
1308
- readonly EARLY_FINISH: "earlyFinish";
1309
- readonly LATE_START: "lateStart";
1310
- readonly LATE_FINISH: "lateFinish";
1311
- readonly FREE_SLACK: "freeSlack";
1312
- readonly TOTAL_SLACK: "totalSlack";
1313
- readonly CORRELATIVE_ID: "correlative_id";
1314
- readonly UNIQUE_CORRELATIVE_ID: "unique_correlative_id";
1315
- readonly PONDERATOR: "ponderator";
1316
- readonly STATUS: "status";
1317
- readonly TEXT: "text";
1318
- readonly DESCRIPTION: "description";
1319
- readonly DURATION: "duration";
1320
- readonly PROGRESS: "progress";
1321
- readonly COST: "cost";
1322
- readonly USED_COST: "used_cost";
1323
- readonly HH_WORK_TIME: "hhWorkTime";
1324
- readonly START_DATE: "start_date";
1325
- readonly END_DATE: "end_date";
1326
- readonly CONSTRAINT_TYPE: "constraint_type";
1327
- readonly CONSTRAINT_DATE: "constraint_date";
1328
- readonly CALENDAR_ID: "calendar_id";
1329
- readonly CUSTOM_ID: "custom_id";
1330
- readonly SUBCONTRACT_ID: "subcontractId";
1331
- readonly RESPONSABLES: "responsables";
1332
- readonly TAGS: "tags";
1333
- readonly CUSTOM_PREDECESSORS: "custom_predecessors";
1334
- readonly CUSTOM_SUCESSORS: "custom_sucessors";
1335
- };
1336
- type ColumnName = (typeof COLUMN)[keyof typeof COLUMN];
1337
-
1338
- type ActivityId = string;
1339
- type CalendarId = string;
1340
-
1341
1089
  /**
1342
1090
  * Role interfaces (Interface Segregation).
1343
1091
  *
@@ -1355,30 +1103,37 @@ type CalendarId = string;
1355
1103
 
1356
1104
  /** READ surface over the activity/link store and the hierarchy index. */
1357
1105
  interface ActivityReader {
1358
- getActivity(activityId: ActivityId$2): EngineActivitySnapshot | null;
1359
- getAllActivities(): ReadonlyArray<EngineActivitySnapshot>;
1106
+ getActivity(activityId: ActivityId$1): CoreActivity | null;
1107
+ getLastStartDate(activityId: ActivityId$1): Date | null;
1108
+ getAllActivities(): ReadonlyArray<CoreActivity>;
1360
1109
  getAllLinks(): LinkSnapshot[];
1361
1110
  getLink(linkId: LinkId$1): LinkSnapshot | null;
1362
- activityExists(activityId: ActivityId$2): boolean;
1363
- getChildren(parentId: ActivityId$2): ActivityId$2[];
1364
- getParent(activityId: ActivityId$2): EngineActivitySnapshot | null;
1365
- getParentId(activityId: ActivityId$2): ActivityId$2 | 0;
1366
- isChildOf(childId: ActivityId$2, parentId: ActivityId$2): boolean;
1367
- getAllIds(): readonly ActivityId$2[];
1111
+ activityExists(activityId: ActivityId$1): boolean;
1112
+ getChildren(parentId: ActivityId$1): ActivityId$1[];
1113
+ hasChildren(parentId: ActivityId$1): boolean;
1114
+ getParent(activityId: ActivityId$1): CoreActivity | null;
1115
+ getParentId(activityId: ActivityId$1): ActivityId$1 | null;
1116
+ getRootIds(): ReadonlyArray<ActivityId$1>;
1117
+ isChildOf(childId: ActivityId$1, parentId: ActivityId$1): boolean;
1118
+ getOutgoingLinkIds(activityId: ActivityId$1): ReadonlyArray<LinkId$1>;
1119
+ getIncomingLinkIds(activityId: ActivityId$1): ReadonlyArray<LinkId$1>;
1120
+ getAllIds(): readonly ActivityId$1[];
1368
1121
  activityCount(): number;
1369
- forEachActivity(visit: (activity: EngineActivitySnapshot, id: ActivityId$2) => void): void;
1122
+ forEachActivity(visit: (activity: CoreActivity, id: ActivityId$1) => void): void;
1370
1123
  }
1371
1124
  /** READ + WRITE surface over the store. */
1372
1125
  interface ActivityWriter extends ActivityReader {
1373
- setActivityField<Field extends keyof EngineActivitySnapshot>(activityId: ActivityId$2, field: Field, value: EngineActivitySnapshot[Field]): void;
1126
+ setActivityField<Field extends keyof CoreActivity>(activityId: ActivityId$1, field: Field, value: CoreActivity[Field]): void;
1127
+ setActivityFieldDynamic(activityId: ActivityId$1, field: string, value: unknown): void;
1374
1128
  /** Bulk write of several fields of one activity in a single getActivity +
1375
1129
  * write-capture note (vs N setActivityField calls). */
1376
- setActivityFields(activityId: ActivityId$2, fields: Partial<EngineActivitySnapshot>): void;
1130
+ setActivityFields(activityId: ActivityId$1, fields: Partial<CoreActivity>): void;
1377
1131
  addLink(link: LinkSnapshot): void;
1378
1132
  removeLink(linkId: LinkId$1): void;
1379
- setLinkField<Field extends keyof LinkSnapshot>(linkId: LinkId$1, field: Field, value: LinkSnapshot[Field]): void;
1380
- addActivity(activity: EngineActivitySnapshot): void;
1381
- removeActivity(activityId: ActivityId$2): void;
1133
+ setLinkField<Field extends MutableLinkField>(linkId: LinkId$1, field: Field, value: LinkSnapshot[Field]): void;
1134
+ setLinkFieldDynamic(linkId: LinkId$1, field: string, value: unknown): void;
1135
+ addActivity(activity: CoreActivity): void;
1136
+ removeActivity(activityId: ActivityId$1): void;
1382
1137
  }
1383
1138
 
1384
1139
  /**
@@ -1416,7 +1171,7 @@ interface ScheduleCoreReporter {
1416
1171
  */
1417
1172
 
1418
1173
  type ScheduleCoreStatus = 'ready' | 'destroyed' | 'poisoned';
1419
- interface ScheduleCoreInput extends BackendInput {
1174
+ interface ScheduleCoreInput extends BackendScheduleInput {
1420
1175
  /**
1421
1176
  * Skip the full autoscheduler pass that normally runs from the
1422
1177
  * constructor (`runInitialPasses`).
@@ -1480,6 +1235,14 @@ interface ScheduleCoreInput extends BackendInput {
1480
1235
  reporter?: ScheduleCoreReporter;
1481
1236
  }
1482
1237
 
1238
+ interface PersistedEntityIdentity {
1239
+ readonly id: string;
1240
+ readonly proplannerId: number;
1241
+ }
1242
+ interface PersistenceAcknowledgement {
1243
+ readonly activities?: ReadonlyArray<PersistedEntityIdentity>;
1244
+ readonly links?: ReadonlyArray<PersistedEntityIdentity>;
1245
+ }
1483
1246
  declare class ScheduleCore {
1484
1247
  private _status;
1485
1248
  /** True while an async dispatch is suspended inside the write-capture window.
@@ -1498,17 +1261,15 @@ declare class ScheduleCore {
1498
1261
  }>;
1499
1262
  get status(): ScheduleCoreStatus;
1500
1263
  getSector(): Readonly<SectorMetadata>;
1501
- getActivityView(id: ActivityId$1, unit?: OutputUnit): Readonly<Activity> | null;
1502
- getAllActivitiesView(unit?: OutputUnit): ReadonlyArray<Readonly<Activity>>;
1503
- getChildrenView(parentId: ActivityId$1 | '0', unit?: OutputUnit): ReadonlyArray<Readonly<Activity>>;
1504
- getLinkView(id: LinkId, unit?: OutputUnit): Readonly<Link> | null;
1505
- getAllLinksView(unit?: OutputUnit): ReadonlyArray<Readonly<Link>>;
1506
- getProperty<Property extends keyof Activity>(activityId: ActivityId$1, property: Property, options?: {
1507
- unit?: OutputUnit;
1508
- }): Activity[Property] | null;
1264
+ getActivityView(id: ActivityId): Readonly<CoreActivity> | null;
1265
+ getAllActivitiesView(): ReadonlyArray<Readonly<CoreActivity>>;
1266
+ getChildrenView(parentId: ActivityId | '0'): ReadonlyArray<Readonly<CoreActivity>>;
1267
+ getLinkView(id: LinkId): Readonly<Link> | null;
1268
+ getAllLinksView(): ReadonlyArray<Readonly<Link>>;
1269
+ getProperty<Property extends keyof CoreActivity>(activityId: ActivityId, property: Property): CoreActivity[Property] | null;
1509
1270
  getAllIds(): readonly string[];
1510
1271
  forEachActivityId(visit: (id: string) => void): void;
1511
- getChildrenIds(parentId: ActivityId$1 | '0'): ReadonlyArray<ActivityId$1>;
1272
+ getChildrenIds(parentId: ActivityId | '0'): ReadonlyArray<ActivityId>;
1512
1273
  getSelectedActivityIds(): string[];
1513
1274
  /**
1514
1275
  * Every activity id in canonical DFS visual order (pre-order from roots,
@@ -1517,18 +1278,28 @@ declare class ScheduleCore {
1517
1278
  * on any structural mutation (add/remove/reparent/renumber), so repeated
1518
1279
  * reads between mutations are O(1).
1519
1280
  */
1520
- getVisualOrderIds(): ReadonlyArray<ActivityId$1>;
1521
- hasChild(parentId: ActivityId$1 | '0'): boolean;
1522
- getCalendar(id: CalendarId$1): Readonly<Calendar> | null;
1281
+ getVisualOrderIds(): ReadonlyArray<ActivityId>;
1282
+ hasChild(parentId: ActivityId | '0'): boolean;
1283
+ getCalendar(id: CalendarId): Readonly<Calendar> | null;
1523
1284
  getAllCalendars(): ReadonlyArray<Readonly<Calendar>>;
1524
1285
  getBaseCalendars(): ReadonlyArray<Readonly<Calendar>>;
1525
1286
  isCustomIdInUse(customId: string, currentCustomId?: string | null): boolean;
1526
1287
  getProjectWorkHours(): ProjectWorkHours | null;
1527
1288
  getModifiedLinks(): ReadonlyArray<Readonly<Link>>;
1528
1289
  markLinksPersisted(): void;
1529
- getModifiedActivities(): ReadonlyArray<Readonly<Activity>>;
1290
+ getModifiedActivities(): ReadonlyArray<Readonly<CoreActivity>>;
1530
1291
  markActivitiesPersisted(): void;
1531
- applyBaselines(points: readonly BaselinePoint[]): ReadonlyArray<Readonly<Activity>>;
1292
+ /**
1293
+ * Reconciles the backend identities returned by a successful schedule save.
1294
+ *
1295
+ * This is an application-boundary acknowledgement, not an editable schedule
1296
+ * gesture: it does not autoschedule, recompute, emit an undo entry, or invent
1297
+ * domain changes. Every assignment is validated before the first mutation so
1298
+ * a malformed/partial response cannot leave the core half-reconciled. Once
1299
+ * applied, the complete live graph becomes the new save-tracker baseline.
1300
+ */
1301
+ acknowledgePersistence(acknowledgement: PersistenceAcknowledgement): void;
1302
+ applyBaselines(points: readonly BaselinePoint[]): ReadonlyArray<Readonly<CoreActivity>>;
1532
1303
  /**
1533
1304
  * Whole-tree ponderator recompute (zeroes, then redistributes 100 within
1534
1305
  * each parent from its children's active baselines, weighted by `criterion`).
@@ -1536,25 +1307,25 @@ declare class ScheduleCore {
1536
1307
  * The base rollup (`applyBaselines`) depends on fresh ponderators, so callers
1537
1308
  * run this before it on a criterion change or baseline save.
1538
1309
  */
1539
- recomputeAllPonderators(criterion: ActivityCreter): ReadonlyArray<Readonly<Activity>>;
1310
+ recomputeAllPonderators(criterion: ActivityCreter): ReadonlyArray<Readonly<CoreActivity>>;
1540
1311
  /**
1541
1312
  * Recompute the weighted-progress rollup of every parent, bottom-up.
1542
1313
  * Returns the activities whose `progress` changed, for a prop-only repaint.
1543
1314
  */
1544
- recomputeAllProgressRollup(): ReadonlyArray<Readonly<Activity>>;
1315
+ recomputeAllProgressRollup(): ReadonlyArray<Readonly<CoreActivity>>;
1545
1316
  /**
1546
1317
  * Set the project's status criterion (the Baseline↔Actual toggle) and
1547
1318
  * recompute every activity's `status` against it. Stores the criterion so
1548
1319
  * future dispatches keep deriving status with it. Returns the activities
1549
1320
  * whose `status` changed, for a prop-only repaint.
1550
1321
  */
1551
- setStatusCriteria(criteria: StatusCriteria): ReadonlyArray<Readonly<Activity>>;
1552
- allocateActivityId(): ActivityId$1;
1322
+ setStatusCriteria(criteria: StatusCriteria): ReadonlyArray<Readonly<CoreActivity>>;
1323
+ allocateActivityId(): ActivityId;
1553
1324
  createActivity(input: Omit<Extract<DispatchAction, {
1554
1325
  kind: 'activity-create';
1555
- }>, 'kind'>, outputUnit?: OutputUnit): {
1326
+ }>, 'kind'>): {
1556
1327
  ok: true;
1557
- activity: Readonly<Activity>;
1328
+ activity: Readonly<CoreActivity>;
1558
1329
  changes: ChangeSet;
1559
1330
  } | {
1560
1331
  ok: false;
@@ -1580,12 +1351,8 @@ declare class ScheduleCore {
1580
1351
  } | null>;
1581
1352
  private _recomputeCriticalPathIfStale;
1582
1353
  private _runCriticalPathAndCapture;
1583
- undo(options?: {
1584
- outputUnit?: OutputUnit;
1585
- }): Promise<ChangeSet | null>;
1586
- redo(options?: {
1587
- outputUnit?: OutputUnit;
1588
- }): Promise<ChangeSet | null>;
1354
+ undo(): Promise<ChangeSet | null>;
1355
+ redo(): Promise<ChangeSet | null>;
1589
1356
  clearHistory(): void;
1590
1357
  canUndo(): boolean;
1591
1358
  canRedo(): boolean;
@@ -1607,14 +1374,18 @@ declare class ScheduleCore {
1607
1374
  private _rollback;
1608
1375
  }
1609
1376
 
1377
+ interface ViewStateSeed {
1378
+ readonly hiddenIds: readonly ActivityId[];
1379
+ }
1610
1380
  interface ParsedInput {
1611
1381
  sector: SectorMetadata;
1612
- activities: Activity[];
1382
+ activities: CoreActivity[];
1613
1383
  links: Link[];
1614
1384
  calendars: Calendar[];
1615
1385
  baseCalendars: Calendar[];
1386
+ viewStateSeed: ViewStateSeed;
1616
1387
  }
1617
- declare function parseFromBackend(input: BackendInput, reporter?: ScheduleCoreReporter): ParsedInput;
1388
+ declare function parseFromBackend(input: BackendScheduleInput, reporter?: ScheduleCoreReporter): ParsedInput;
1618
1389
 
1619
1390
  /**
1620
1391
  * Returns the ACTIVE baseline point of an activity, or null.
@@ -1636,8 +1407,8 @@ declare function parseFromBackend(input: BackendInput, reporter?: ScheduleCoreRe
1636
1407
  * the legacy `if (base.sectorbaselineversion.active)` check.
1637
1408
  */
1638
1409
  declare function getActiveBaseline(activity: {
1639
- baseline_points?: unknown;
1640
- } | null | undefined): BaselinePoint | null;
1410
+ baselinePoints?: readonly CoreBaselinePoint[];
1411
+ } | null | undefined): CoreBaselinePoint | null;
1641
1412
 
1642
1413
  /**
1643
1414
  * Surface this function needs from ScheduleState — kept structural so the
@@ -1656,7 +1427,7 @@ interface BaselineApplyAdapter {
1656
1427
  * `baseline_points` reset to `[]`. Returns the ids of activities whose
1657
1428
  * `baseline_points` changed (so the caller can repaint just those).
1658
1429
  */
1659
- declare function applyBaselinePoints(adapter: BaselineApplyAdapter, points: readonly BaselinePoint[]): string[];
1430
+ declare function applyBaselinePoints(adapter: BaselineApplyAdapter, points: readonly BaselinePoint[], reporter: ScheduleCoreReporter): string[];
1660
1431
 
1661
1432
  interface CalendarLike {
1662
1433
  calculateDuration(start: Date, end: Date): number;
@@ -1730,9 +1501,9 @@ declare function recomputeAllPonderators(criterion: ActivityCreter, adapter: Act
1730
1501
  *
1731
1502
  * PROGRESS-ONLY by design: unlike the dispatch post-processor
1732
1503
  * `recomputeParentFromChildren` (post-processors/parent-bounds.ts), this does NOT
1733
- * touch parent start/end/duration — only `progress` and the milestone mirror
1734
- * `for_disable_milestone_duration`. That keeps it testable in isolation
1735
- * (no calendars/dates needed) and matches what `check_progress` actually did.
1504
+ * touch parent start/end/duration — only `progress`. That keeps it testable
1505
+ * in isolation (no calendars/dates needed) and matches what `check_progress`
1506
+ * actually did.
1736
1507
  *
1737
1508
  * Order is load-bearing (unlike ponderators, which are order-independent): a
1738
1509
  * grandparent's rollup consumes its children-parents' ALREADY rolled-up
@@ -1749,127 +1520,8 @@ declare function recomputeAllPonderators(criterion: ActivityCreter, adapter: Act
1749
1520
 
1750
1521
  declare function recomputeAllProgressRollup(adapter: ActivityWriter): void;
1751
1522
 
1752
- /**
1753
- * Task creation pipeline — types.
1754
- *
1755
- * Ports the pure parts of `src/assets/js/custom_actions/createTask/` into a
1756
- * functional pipeline that replay tests (and eventually prod) can invoke
1757
- * against an adapter instead of the live gantt.
1758
- */
1759
-
1760
- /**
1761
- * Shape of the task object AFTER the pipeline configures it.
1762
- *
1763
- * Mirrors the canonical `Activity` interface (from `../../types.ts`) plus
1764
- * a handful of Outbuild-specific fields (responsables, tags, subcontractId,
1765
- * real_constraint_type) and legacy lifecycle flags (new_task, isNewActivity,
1766
- * $source, $target) that downstream consumers still read.
1767
- *
1768
- * Every field in `Activity` is present here. The defaults for the
1769
- * non-runtime-computed ones live in `NEW_ACTIVITY_DEFAULTS`.
1770
- */
1771
- interface NewActivityFields {
1772
- text: string;
1773
- description: string;
1774
- type: 'task' | 'milestone' | 'project';
1775
- start_date: Date;
1776
- end_date: Date;
1777
- duration: number;
1778
- progress: number;
1779
- constraint_type: ConstraintType | null;
1780
- constraint_date: Date | null;
1781
- calendar_id: CalendarId;
1782
- /** Parent id (string) or `'0'` for root. Always string — no number drift. */
1783
- parent: ActivityId | '0';
1784
- auto_scheduling: boolean;
1785
- hhWorkTime: number;
1786
- cost: number;
1787
- used_cost: number;
1788
- /**
1789
- * Earned cost: `(progress/100) × activeBaseline.cost`. A fresh activity has
1790
- * progress 0 and no active baseline, so it starts at 0 — matching what the
1791
- * load-path `emitRealCost` would compute for a new leaf. Seeded explicitly so
1792
- * the field is never `undefined` (which surfaced as `NaN` downstream).
1793
- */
1794
- real_cost: number;
1795
- /** Real worked hours; aggregated from progress submittals. Starts at 0. */
1796
- real_work: number;
1797
- /**
1798
- * Baseline-derived weighting factor used by the parent.progress rollup.
1799
- * Starts at 0 (no baseline yet); set by the backend on baseline import.
1800
- * Not editable from the schedule UI — see `project_ponderator_not_editable`.
1801
- */
1802
- ponderator: number;
1803
- responsables: unknown[];
1804
- tags: unknown[];
1805
- subcontractId: string | number | null;
1806
- real_constraint_type: ConstraintType | null;
1807
- should_be_showed: boolean;
1808
- /** View-model visibility bit (`visible !== false` = visible). */
1809
- visible: boolean;
1810
- activityModifications: unknown[];
1811
- pendingRequests: unknown[];
1812
- /** String form, matches Sequelize BIGINT serialization. */
1813
- unique_correlative_id: string;
1814
- start_date_backup: string;
1815
- new_task: true;
1816
- isNewActivity: true;
1817
- /**
1818
- * Tracks outgoing link ids (this activity is the link source).
1819
- * Initialized empty; mutated by link-create / link-delete to keep the
1820
- * index consistent. The snapshot reads it directly, so it must always
1821
- * exist (not undefined) — see D1 in DIVERGENCES_activity_create.md.
1822
- */
1823
- $source: string[];
1824
- /** Same as $source for incoming links (this activity is the target). */
1825
- $target: string[];
1826
- /** Pass-through bucket for any extra fields the caller provides. */
1827
- [key: string]: unknown;
1828
- }
1829
-
1830
- /**
1831
- * Working-day vocabulary — genuine cross-component primitive (creation
1832
- * defaults, internal/state context fallbacks, link lag display). The value
1833
- * is the FALLBACK only; a sector- or calendar-provided hoursPerDay always
1834
- * takes precedence at every consumer.
1835
- */
1836
- declare const DEFAULT_HOURS_PER_DAY = 8;
1837
-
1838
- /**
1839
- * Defaults for newly-created activities — the **canonical template** that
1840
- * `buildNewActivity` spreads before applying caller-provided overrides.
1841
- *
1842
- * Single source of truth: any documentation that says "a new activity
1843
- * starts as X" must reference this constant, never inline literals.
1844
- *
1845
- * The shape produced by spreading this constant + the runtime-computed
1846
- * fields below is a complete Activity (every field in the `Activity`
1847
- * interface from `../../types.ts` is accounted for).
1848
- *
1849
- * Fields NOT in this constant are computed at runtime because they depend
1850
- * on input or context:
1851
- * - `id` → allocated by `ActivityIdGenerator.next()`
1852
- * - `parent` → from `DispatchAction.parentId` (or `'0'`)
1853
- * - `start_date` → inherited from parent or `fallbackStartDate`,
1854
- * then snapped to the calendar's next
1855
- * working-time boundary
1856
- * - `end_date` → calendar-aware via `adapter.calculateEndDate`
1857
- * - `duration` → override > `sector.hoursPerDay` > `8`
1858
- * - `calendar_id` → override > `sector.defaultCalendar`
1859
- * - `unique_correlative_id` → allocated by `UniqueCorrelativeIdGenerator.next()`
1860
- * - `custom_id` → allocated by `customIdTracker`
1861
- * - `text` → `'New Master Plan'` when this is the very
1862
- * first activity of the sector, `'New Activity'`
1863
- * otherwise (override beats both)
1864
- * - `correlative_id` → assigned by `recomputeCorrelativeIds` after
1865
- * the new activity has been inserted in the
1866
- * parent's children list
1867
- *
1868
- * The `real_constraint_type` field is set AFTER the spread of overrides so
1869
- * it always mirrors the (possibly overridden) `constraint_type`.
1870
- */
1871
-
1872
- declare const NEW_ACTIVITY_DEFAULTS: Readonly<Omit<NewActivityFields, 'id' | 'parent' | 'start_date' | 'end_date' | 'duration' | 'calendar_id' | 'unique_correlative_id' | 'text' | 'start_date_backup'>>;
1523
+ type StaticActivityDefaults = Omit<CoreActivity, 'id' | 'parentId' | 'name' | 'startDate' | 'endDate' | 'durationHours' | 'calendarId' | 'uniqueCorrelativeId'>;
1524
+ declare const NEW_ACTIVITY_DEFAULTS: Readonly<StaticActivityDefaults>;
1873
1525
 
1874
1526
  /**
1875
1527
  * Schedule-core equivalent of the legacy frontend `checkNoUpdatedLinks`.
@@ -1996,6 +1648,14 @@ declare const LINK_CODE_TO_TYPE: {
1996
1648
  /** Inverse of `CONSTRAINT_LABEL_MAP` — internal code → backend label. */
1997
1649
  declare const CONSTRAINT_TYPE_TO_LABEL: Record<ConstraintType, string>;
1998
1650
 
1651
+ /**
1652
+ * Working-day vocabulary — genuine cross-component primitive (creation
1653
+ * defaults, internal/state context fallbacks, link lag display). The value
1654
+ * is the FALLBACK only; a sector- or calendar-provided hoursPerDay always
1655
+ * takes precedence at every consumer.
1656
+ */
1657
+ declare const DEFAULT_HOURS_PER_DAY = 8;
1658
+
1999
1659
  /**
2000
1660
  * Canonical catalog of `DispatchAction` kinds.
2001
1661
  *
@@ -2032,6 +1692,7 @@ declare const DISPATCH_ACTION_KIND: {
2032
1692
  readonly SELECTION_REPLACE: "selection-replace";
2033
1693
  readonly VISIBILITY_SET: "visibility-set";
2034
1694
  readonly SIR_SYNC: "sir-sync";
1695
+ readonly ACTIVITY_LOOKAHEAD_SYNC: "activity-lookahead-sync";
2035
1696
  };
2036
1697
  declare const DISPATCH_ACTION_KINDS: ReadonlyArray<DispatchActionKind>;
2037
1698
 
@@ -2107,4 +1768,4 @@ declare const DISPATCH_TRACK_EVENT: {
2107
1768
  };
2108
1769
  type DispatchTrackEvent = (typeof DISPATCH_TRACK_EVENT)[keyof typeof DISPATCH_TRACK_EVENT];
2109
1770
 
2110
- export { ACTIVITY_TYPE, type Activity, type ActivityCreter, type ActivityId$1 as ActivityId, type ActivityType, type BackendActivityInput, type BackendCalendar, type BackendCalendarException, type BackendInput, type BackendLink, type BackendScheduleImpactRequests, type BackendSector, type BackendShift, type BaselinePoint, type BaselineVersion, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, type Calendar, type CalendarId$1 as CalendarId, type CalendarUnit, type CalendarWorktime, type ChangeSet, type ColumnName, type ConstraintType, type ConstraintWarning, type CreationKind, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, type DispatchAction, type DispatchActionKind, type DispatchOptions, type DispatchRejectReason, type DispatchResult, type DispatchTrackEvent, type EntityChange, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, type Link, type LinkId, type LinkType, type LinkTypeCode, type LinksBatchOperation, NEW_ACTIVITY_DEFAULTS, type OutputUnit, type ParsedInput, type PastedActivityInput, type PastedLinkInput, type PendingRequest, REJECTION_REASON, ROOT_PARENT_ID, ScheduleCore, type ScheduleCoreInput, type ScheduleCoreReporter, type ScheduleCoreStatus, type ScheduleEffect, type SectorMetadata, type StatusCriteria, type TrackingEvent, WORK_TIME_DIRECTION, type WorkTimeDirection, applyBaselinePoints, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, recomputeAllPonderators, recomputeAllProgressRollup, willRunCriticalPath, yieldToBrowser };
1771
+ export { ACTIVITY_TYPE, type ActivityCreter, type ActivityId, type ActivityType, type BackendActivityInput, type BackendCalendarInput, type BackendLinkInput, type BackendScheduleInput, type BackendSectorInput, type BaselinePoint, type BaselineVersion, CALENDAR_UNIT, COLUMN, CONSTRAINT_TYPE, CONSTRAINT_TYPE_TO_LABEL, CREATION_KIND, type Calendar, type CalendarId, type CalendarUnit, type CalendarWorktime, type ChangeSet, type ColumnName, type ConstraintType, type ConstraintWarning, type CoreActivity, type CreationKind, DEFAULT_HOURS_PER_DAY, DISPATCH_ACTION_KIND, DISPATCH_ACTION_KINDS, DISPATCH_TRACK_EVENT, type DispatchAction, type DispatchActionKind, type DispatchOptions, type DispatchRejectReason, type DispatchResult, type DispatchTrackEvent, type EntityChange, LINK_CODE_TO_TYPE, LINK_TYPE, LINK_TYPE_CODE, type Link, type LinkId, type LinkType, type LinkTypeCode, type LinksBatchOperation, NEW_ACTIVITY_DEFAULTS, type ParsedInput, type PastedActivityInput, type PastedLinkInput, type PendingRequest, type PersistedEntityIdentity, type PersistenceAcknowledgement, REJECTION_REASON, ROOT_PARENT_ID, ScheduleCore, type ScheduleCoreInput, type ScheduleCoreReporter, type ScheduleCoreStatus, type ScheduleEffect, type SectorMetadata, type StatusCriteria, type TrackingEvent, WORK_TIME_DIRECTION, type WorkTimeDirection, applyBaselinePoints, checkNoUpdatedLinks, computeExpectedProgress, expectedProgressFromBaseline, getActiveBaseline, getUnsavedActivities, isRootParent, normalizeParentKey, parseFromBackend, recomputeAllPonderators, recomputeAllProgressRollup, willRunCriticalPath, yieldToBrowser };