@outbuild-company/schedule-core 1.10.3 → 1.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,21 +1,67 @@
1
- # @outbuild-company/schedule-core
1
+ <div align="center">
2
2
 
3
- UI-agnostic schedule engine for activities, links, calendars, autoscheduling
4
- and critical-path calculation.
3
+ # Schedule Core
5
4
 
6
- ## Install
5
+ **A UI-agnostic domain engine for project schedules.**
7
6
 
8
- ```bash
9
- npm install @outbuild-company/schedule-core
10
- ```
7
+ Activities, dependencies, working calendars, constraints, autoscheduling, and critical path — behind one typed boundary.
11
8
 
12
- The package exposes a single public entry point:
9
+ [![CI](https://github.com/OutBuild-Construction-Software/schedule-core/actions/workflows/ci.yml/badge.svg)](https://github.com/OutBuild-Construction-Software/schedule-core/actions/workflows/ci.yml)
10
+ [![npm](https://img.shields.io/npm/v/%40outbuild-company%2Fschedule-core)](https://www.npmjs.com/package/@outbuild-company/schedule-core)
13
11
 
14
- ```ts
15
- import { ScheduleCore } from '@outbuild-company/schedule-core';
12
+ </div>
13
+
14
+ ## Why Schedule Core?
15
+
16
+ Scheduling behavior needs one authority. If dates, dependency cascades, calendar math, and summary rollups are split between a Gantt widget and application code, the same edit can acquire different meanings in different consumers.
17
+
18
+ Schedule Core owns normalized schedule state and its mutations. A consumer supplies backend data, sends typed commands, and projects the resulting changes. Rendering and storage stay at the boundary.
19
+
20
+ ## Mental model
21
+
22
+ ```mermaid
23
+ flowchart LR
24
+ Payload["Backend payload"] --> Normalize["Parse + normalize"]
25
+ Normalize --> Core
26
+ Command["DispatchAction"] --> Core
27
+
28
+ subgraph Engine["Schedule Core"]
29
+ Core["Canonical state"] --> Pipeline["Validate · mutate · derive"]
30
+ Pipeline --> Core
31
+ end
32
+
33
+ Pipeline --> Changes["ChangeSet"]
34
+ Core --> Reads["Read-only snapshots"]
35
+ Changes --> Consumers["UI · persistence · analytics"]
36
+ Reads --> Consumers
16
37
  ```
17
38
 
18
- ## Quick start
39
+ | Part | Contract |
40
+ | --- | --- |
41
+ | **Input** | Backend-shaped sector, activities, links, and calendars. Construction parses and normalizes them. |
42
+ | **State** | `ScheduleCore` owns the live activity, link, calendar, hierarchy, view-state, and history model. |
43
+ | **Command** | A `DispatchAction` expresses an edit, structural operation, dependency change, or synchronization event. |
44
+ | **Result** | Accepted commands return a `ChangeSet`; expected validation failures return `{ ok: false, reason }`. |
45
+ | **Consumer** | Applies projections, presents warnings, sends analytics, and performs I/O. |
46
+
47
+ ## Core concepts
48
+
49
+ | Concept | Role in the engine |
50
+ | --- | --- |
51
+ | **Activities** | Tasks, milestones, and summary projects in a hierarchical schedule. |
52
+ | **Links** | Typed dependencies with working-time lag and effective-graph cycle guards. |
53
+ | **Calendars** | Working days, shifts, exceptions, and date/duration calculations. |
54
+ | **Constraints** | ASAP, ALAP, start-based, finish-based, and fixed-date scheduling rules. |
55
+ | **Autoscheduler** | Applies dependency, constraint, calendar, and parent-bound rules after relevant mutations. |
56
+ | **Critical path** | Computes early/late dates, slack, and critical flags through an asynchronous job. |
57
+ | **ChangeSet** | Entity diffs plus view state, ordering, tracking events, effects, and constraint warnings. |
58
+ | **History** | Undo/redo state and persistence checkpoints owned by the core instance. |
59
+
60
+ ## Use it in 30 seconds
61
+
62
+ ```bash
63
+ npm install @outbuild-company/schedule-core
64
+ ```
19
65
 
20
66
  ```ts
21
67
  import {
@@ -28,37 +74,142 @@ const input: ScheduleCoreInput = getScheduleInput();
28
74
  const core = new ScheduleCore(input);
29
75
  await core.ready;
30
76
 
31
- const result = await core.dispatch({
32
- kind: 'inline-edit',
33
- activityId,
34
- column: COLUMN.TEXT,
35
- newValue: 'Updated activity'
36
- });
77
+ const activity = core.getAllActivitiesView()[0];
78
+ if (activity) {
79
+ const result = await core.dispatch({
80
+ kind: 'inline-edit',
81
+ activityId: activity.id,
82
+ column: COLUMN.TEXT,
83
+ newValue: 'Updated activity'
84
+ });
37
85
 
38
- if (!result.ok) throw new Error(result.reason);
39
- applyChangeSet(result.changes);
86
+ if (!result.ok) throw new Error(result.reason);
87
+ applyChangeSet(result.changes);
88
+ }
40
89
 
41
90
  core.destroy();
42
91
  ```
43
92
 
44
- `getScheduleInput`, `activityId`, and `applyChangeSet` are consumer-provided
45
- values.
93
+ `getScheduleInput()` and `applyChangeSet()` belong to the consumer. The package exports one supported root entry point; deep imports are internal.
94
+
95
+ See the [API reference](docs/API.md) for initialization, commands, read APIs, persistence, undo/redo, forks, critical path, constants, and exported types.
96
+
97
+ ## What a change contains
98
+
99
+ ```ts
100
+ interface ChangeSet {
101
+ source: ChangeSetSource;
102
+ activities: ReadonlyArray<EntityChange<CoreActivity>>;
103
+ links: ReadonlyArray<EntityChange<Link>>;
104
+ calendars: ReadonlyArray<EntityChange<Calendar>>;
105
+ trackingEvents: ReadonlyArray<TrackingEvent>;
106
+ viewState?: ReadonlyArray<ViewStateChange>;
107
+ order?: ReadonlyArray<BranchOrderChange>;
108
+ effects?: ReadonlyArray<ScheduleEffect>;
109
+ warnings?: ReadonlyArray<ConstraintWarning>;
110
+ }
111
+ ```
112
+
113
+ Changes are data, not side effects. A successful dispatch updates core state; consumers decide how to render, persist, report, or transmit the returned records.
114
+
115
+ ## Core invariants
116
+
117
+ - **Serialized writes.** State-changing operations on one `ScheduleCore` instance run through a single operation queue.
118
+ - **Isolated reads.** Public read methods return cloned snapshots or read-only collections; mutating a returned value cannot mutate core state.
119
+ - **Guarded commits.** A rejected dispatch restores captured mutations. A failed rollback poisons the instance instead of continuing with uncertain state.
120
+ - **Cycle-safe graph edits.** New dependency and hierarchy mutations are checked against the effective dependency graph. Pre-existing cycles can be inspected with `auditEffectiveGraph()`.
121
+ - **Explicit time units.** Duration commands accept working days; domain snapshots expose `durationHours`, and link lag is stored and exposed in working hours.
122
+ - **Persistence is acknowledged.** Storage remains external; a successful `persistence-acknowledge` establishes the saved checkpoint and history boundary.
123
+
124
+ The complete, code-linked contract lives in [INVARIANTS.md](INVARIANTS.md).
125
+
126
+ ## Architecture principles
127
+
128
+ ### One mutation boundary
129
+
130
+ Domain writes enter through `dispatch()` or `applyActivityBatch()`. Handlers validate commands, update the canonical state, run the required derived passes, and assemble one result for the consumer.
131
+
132
+ ### Explicit ownership
133
+
134
+ The core owns schedule entities, temporal calculations, dependency semantics, derived fields, and change tracking. Consumers own transport, persistence execution, UI projection, and presentation of rejected commands.
135
+
136
+ ### Narrow internal roles
137
+
138
+ `ScheduleState` is the store, but subsystems depend on smaller capabilities such as activity readers/writers, calendar operations, the write journal, and the autoscheduler port. Architecture tests ratchet layer boundaries and public-entry reachability.
139
+
140
+ ### Legacy engines behind adapters
141
+
142
+ The package has no runtime dependency on React or the DHTMLX package. Its calendar and critical-path implementations do retain adapted legacy engine code and Gantt-shaped internal contracts. The application-side bridge projects `ChangeSet` data into DHTMLX; that bridge remains outside this package.
143
+
144
+ ## What Schedule Core is not
145
+
146
+ Schedule Core does not:
147
+
148
+ - render a Gantt chart or React component;
149
+ - own a browser application's component state;
150
+ - fetch schedule data or make HTTP requests;
151
+ - write to a database or storage service;
152
+ - decide how warnings, analytics, or rejected commands are presented.
153
+
154
+ It does track dirty entities and persistence checkpoints, but the consumer performs the actual save.
155
+
156
+ ## Repository map
157
+
158
+ ```text
159
+ src/
160
+ ├── index.ts public package contract
161
+ ├── init/ facade, initialization, read API
162
+ ├── dispatch/ commands, handlers, ChangeSets, undo/redo
163
+ ├── internal/ state, hierarchy, ordering, dependency graph
164
+ ├── autoscheduler/ ASAP/ALAP scheduling and link propagation
165
+ ├── calendar/ working-time API and engine adapter
166
+ ├── columns/ typed field mutation pipelines
167
+ ├── propagations/ parent and derived-field propagation
168
+ ├── critical-path/ critical-path facade and legacy adapter
169
+ ├── constraints/ constraint vocabulary and date semantics
170
+ ├── boundary/ backend normalization and save tracking
171
+ └── testing/ fixtures, scenarios, recordings, and parity harnesses
172
+ ```
173
+
174
+ ## Testing
175
+
176
+ [Vitest](https://vitest.dev/) runs two explicit projects:
46
177
 
47
- Schedule Core owns domain state and mutations. Consumers provide normalized
48
- input, send commands through `dispatch()`, apply returned changes at the UI
49
- boundary, and persist them at the storage boundary.
178
+ - **Unit** sibling tests for domain modules, mutation pipelines, calendars, scheduling, graph rules, history, and architecture gates.
179
+ - **Integration** parity suites and recorded sessions over captured project data.
50
180
 
51
- See the [complete API reference](docs/API.md) for initialization, every command,
52
- read APIs, persistence, history, critical path, helpers, constants, and types.
181
+ The repository also contains Gherkin behavior scenarios, production-derived recordings, undo/redo corpus checks, large-project regression cases, and compile-time boundary tests. These are verification strategies, not a published coverage or benchmark claim.
182
+
183
+ ```bash
184
+ npm test # all Vitest projects
185
+ npm run test:unit # unit project
186
+ npm run test:integration # parity and session replays
187
+ ```
53
188
 
54
189
  ## Development
55
190
 
191
+ Requires Node.js 20 or newer.
192
+
56
193
  ```bash
57
194
  npm ci
58
195
  npm run typecheck
196
+ npm run typecheck:boundary
197
+ npm run lint
59
198
  npm test
60
199
  npm run build
61
200
  ```
62
201
 
63
- The build produces ESM, CommonJS, type declarations and a browser IIFE under
64
- `dist/`.
202
+ The build emits ESM, CommonJS, type declarations, source maps, and a browser IIFE under `dist/`. The package declares no runtime dependencies.
203
+
204
+ ## Documentation
205
+
206
+ - [Public API](docs/API.md) — supported entry point, lifecycle, commands, reads, persistence, and types.
207
+ - [Model invariants](INVARIANTS.md) — verified units, dates, queueing, write capture, persistence, and graph rules.
208
+ - [Domain and architecture index](docs/domain/README.md) — canonical map of the detailed domain documentation.
209
+ - [State roles](docs/domain/STATE_ROLES.md) — internal capability boundaries around `ScheduleState`.
210
+ - [Activity ownership](docs/domain/model/SCHEDULE_CORE_OWNERSHIP.md) — current core/render authority by field category.
211
+ - [Temporal model](docs/domain/scheduling/temporal-model.md) — temporal vocabulary, policies, and known open decisions.
212
+ - [Calendars](docs/domain/dates-calendars/CALENDARS.md) — working-time model, normalization, and engine boundary.
213
+ - [Constraints](docs/domain/constraints/01-constraint-types-catalog.md) — supported constraint vocabulary and semantics.
214
+ - [Architecture audit](docs/audit/README.md) — measured implementation map, findings, and unresolved questions.
215
+ - [Changelog](CHANGELOG.md) — released behavior and package history.