October 16, 2026 (round 11)¤
Typed API, docs that run, coverage gate 93. feat: top-level imports are typed; deprecated names are visible to type checkers; transforms, features, ValueMapper, PipelineResult and the warnings/errors are top-level exports; loaders have redacting reprs. perf: scipy and scikit-learn are imported lazily; list_detectors does not import modules. fix: PostgreSQL loaders name the psycopg2 driver (SQLAlchemy 2.1), escape the password and take db_port / db_driver; discover_motifs applies an exclusion zone between motifs; startup by slope with repeated index labels; empty multi-signal startup results keep their columns; DatapointDB with an empty device. docs: every python block on the docs pages runs as a test; new module pages and guides (context, ML features, maintenance, energy); runnable class examples. See docs/migration.md. chore: coverage floor 82 -> 93.
October 15, 2026 (round 10)¤
Fast at 10 and 100 million rows; results unchanged. perf: detector construction copies, sorts and converts only what it must (no full-column text conversion, sort skipped on sorted input); 100M-row frames no longer run out of memory. perf: per-run and per-row Python loops in 19 detector modules replaced by numpy (utils.runs); O(n log w) rolling moments; setpoint KPIs share one window gather; STOMP matrix profile; vectorized DTW with LB_Keogh pruning; faster profile, to_event_log (same event ids), tolerance deviation and apply_ranges. change: ChangePointEvents defaults to method="auto" (PELT up to 20,000 samples, binary segmentation above). fix: setpoint KPIs no longer fail on duplicate index labels. chore: benchmarks/run.py and a scaling check in CI (pytest -m scale). See docs/migration.md.
October 15, 2026 (round 9)¤
KPIs match their textbook definitions. fix: durations and counter increments are split at shift, hour and day boundaries (downtime, availability trend, shift handover, runtime, micro stops, OEE, per-shift quality); OEE across midnight is correct; days without state data are NaN; performance above 100 % warns instead of being clipped. fix: PerformanceLoss counts parts; time_to_settle is the last band entry; overshoot/undershoot are percent (ratio twins added); period roll-ups recompute from summed bases; EnPI/SEC rolling baselines are ratios of sums; stockout prediction is refill-aware. fix: SPC individuals limits, rules and CUSUM use MR-bar/1.128 (sigma_method="std" keeps the old sigma); real moving-range and EWMA charts; Cp/Cpk within sigma, Pp/Ppk overall and per-window sigma. feat: utils.time_accounting; micro-stop performance_loss_pct; reference tests for KPIs in tests/reference. See docs/migration.md.
October 15, 2026 (round 8)¤
Legacy code and tooling removed. change: requires pandas>=2.2.2 and numpy>=2.0; a CI job tests these floors and results match pandas 3 (calendar-day windows on DST days, DST flooring, mixed UTC offsets, clustering). fix: deprecation warnings point at the caller and are no longer hidden; apply_ranges / segment_by_cut compare times in one unit; numeric columns named like times are no longer converted to datetimes; hour folders are UTC in every loader. change: logged data problems are DataQualityWarnings; text in numeric columns is reported; recipe duration_s, downtime_minutes input and old attribute names warn; loader time ranges are start / end (old start_timestamp / start_time keywords warn). See docs/migration.md. fix: CUSUM counts a repeated sample once. chore: setup.py, MANIFEST.in, requirements files, dead scripts and dead code removed; duplicated helpers merged; one source of tool versions; CI runs once per PR commit; per-job release permissions; examples linted; a ts-shape deprecation fails the test suite.
October 14, 2026 (round 7)¤
Robust and consistent behavior for every public function. fix: wrong results: CrossSignalAnalytics.lead_lag named the wrong leader; PatternRecognition dropped the timezone, ignored row order and mixed signals; event ids collided across machines so concat dropped events; ValueMapper/ContextEnricher dropped columns and codes; build_paths missed the last hour; boolean and string change filters missed edges; fill_gaps(max_gap) measured gaps wrongly; lead_times could be negative; reliability and stockout returned inf. fix: crashes on empty, single-row, all-NaN, text-time, nullable and pyarrow input across transforms, features, signals, profile, pipeline, event log and detectors; a missing column raises ColumnNotFoundError everywhere. change: canonical parameter names (value_column, time_column, uuid_column, window) outside the detectors; old names deprecated. No data gives NaN or None, unknown mapping codes are kept. See docs/migration.md. feat: max_gap on detect_flatline, threshold_with_hysteresis and on_off_intervals; contract tests for every public function; the invariant harness checks determinism, input mutation, row order, output sanity, all-NaN, single-row and duplicate timestamps.
October 14, 2026 (round 6)¤
Maturity of the existing functions: same numbers for any data source, fast on real data sizes, proven against references, traceable outputs. fix: results no longer depend on how the data was loaded. Nullable, pyarrow and text-number columns are converted once (utils.normalize): 52 methods gave different numbers (counter totals counted the first reading as production, downtime per shift was 0) and 172 crashed. Rows with the same timestamp are ordered by uuid. perf: shift reports, maintenance trend fits, routing, warmup and stockout methods are vectorized: 10-300x faster on 200k rows (nok_by_shift 59 s -> 1.3 s, remaining_useful_life 55 s -> 0.2 s). fix: DST fall-back nights no longer crash window flooring (floor_local); duplicate timestamps no longer give infinite rates; single-row and constant inputs, all-null/boolean string columns, and window <= 0 in oscillation detection are handled. fix: capability trending uses the spec in force in each window; energy methods with weekly/month-end windows report the real window (and energy_per_unit / carbon_intensity_per_unit no longer return empty or raise); downtime and shift handover read boolean run signals (was 100% downtime); flow_constraint_analytics applies its thresholds; from_shift_data matches string dates; detect_outlier_sensor needs three sensors to name an outlier. fix: group counter totals add up to the signal total (counter_by_group): every shift/day/operator/part/batch boundary lost one increment, and alternating operators or parts were double counted (609 parts reported on a 360-part counter). FlowConstraintEvents intervals end at the next change. change: KPIs carry their basis (run/planned/excluded seconds, parts, resets); every duration has a *_seconds column; seven summary methods return a DataFrame (as_frame=False deprecated). See docs/migration.md. test: reference tests for SPC rules 1-8, Cp/Cpk (Montgomery), GUM, Weibull (Lieblein-Zelen) and energy values; property tests; harness dtypes check; examples/ and docstring examples run in the test suite. types: strict mypy flags for the whole library, no exemptions. fix: cycles, period cutters and object detection verified against hand-built scenarios. Cycles: correct pairing for back-to-back and nested markers, deterministic cycle_uuid, one half-open boundary rule. Segments: the last period keeps its data, boundary samples are cut once, segment_by_cut is no longer one piece off. Objects: empty readings end a presence, change-encoded ids last to the data end, hand-over events link once, pm4py export round-trips. All three are 10-100x faster. feat: severity_level (info/warn/critical) next to every categorical severity, so detectors can be filtered together; detector labels stay. fix: lag_profile windows without speed data are NaN (was the lag at min_speed); CriticalParameterRankingEvents needs no long-format frame; TimeWindowedFeatureTable takes window (freq deprecated). docs: the site is cut from 139 to 106 pages (14k to 6k lines) and rewritten in plain language; every example runs.
October 14, 2026 (round 5)¤
Correct by default. Results change wherever data has counter resets, change-encoded signals, uneven sampling or several signals per frame; the old behavior stays one argument away. Full list: docs/migration.md ("Correct by default"). change: correct defaults: handle_resets=True, interval_end="next_change", time_weighted=True, group_by_uuid=True, slope_per="second", missing_as_zero=False, handle_refills=True, SPC include_severity=True, regex=False for substring filters, trim_to_range=True in loaders, best_and_worst_shifts returns a DataFrame, batch_transition_matrix returns a long from/to/count table (layout="wide" for the matrix). change: full precision: detectors no longer round results. fix: machine_running_pct is 0-100 (was a 0-1 ratio; see machine_running_ratio). fix: nothing is skipped silently: loaders take errors="warn"|"raise" and name unreadable objects; non-numeric values, malformed specs, failed fits and untestable windows warn with DataQualityWarning; a missing value column raises ColumnNotFoundError naming it. fix: flatline detection ignores single samples of regularly sampled signals. change: deprecated (removed in a future major release): OrderTraceabilityEvents, a single tolerance_uuid (upper/lower limits now work one-sided), station_map, adapt(legacy=), integer window in correlation, as_frame=False. Every deprecation message says "removed in the next major release". feat: OutlierDetectionEvents(signal_uuids=...); parquet extra; [all] installs every optional feature. build: setuptools-scm reads its config (builds were versioned 0.0.0); releases publish after the full CI suite, choose their version with a Release-Bump / Release-As commit trailer, and are tagged only after the upload succeeded; CI builds and checks the package; Python 3.14 is fully supported; Development Status: Beta. types: the mypy quarantine is empty; every module is type-checked. policy: every merge publishes the next patch version; renamed names keep working with a warning and are removed only in a major release.
October 14, 2026 (round 4)¤
fix: SPC rules follow Nelson (1984) / Western Electric: rule 8 = 8 in a row
with none within 1 sigma (was within), rule 3 = 6 points, rule 4 = 14
points, rules 5/6 count outer zones per side, rule 2 uses the center line;
rules no longer mutate the input; vectorized == per-rule results.
fix: detectors do what their signatures and docs promise (28 items across
production, quality, engineering, energy, development, loaders, features):
ignored parameters now work or warn (slope_window, max_cycle_gap on every
CycleTimeEvents method, idle_threshold per shift, interval_end on
long-downtime gap counting and recipe phases, value_column in process
alignment, ...); silently overridden ones warn (settle_pct vs tol,
state_map vs station_map); tolerance deviations keep values and single
samples; takt adherence uses strict > and ignores counter resets; golden
batch phases compare like with like; hour-folder loaders include the
end hour; NaN instead of None/0.0 for undefined ratios. Opt-in: time-
weighted time_in_range, slope per second in drift detection,
trim_to_range in loaders, regex=False for substring matching. Every
result change is listed in docs/migration.md.
docs: every public parameter is documented (guard test).
change: consistent input checks for every detector (Base.init_subclass +
utils.signal_checks): a signal uuid that is not in a non-empty frame emits
DataQualityWarning naming the available uuids (one per call, not per
internal sub-call); a missing time or uuid column raises
ColumnNotFoundError (a ValueError) instead of a bare KeyError.
change: parameters follow docs/naming.md: time_column (was column_name),
window (freq/period/resample), window_size (integer row counts), n_sigma,
lower_limit/upper_limit, warning/critical_threshold, include_initial,
only_*, signal_uuids, run_state_uuid, value_column_shape and empty_schema for every method.
fix: weekly / month-end windows ('W', 'ME', ...) reported the bin's last day
as start; windows now span their real [start, end).
fix: night shifts are one (date, shift) row: production_day=True is the
default (False keeps calendar-date grouping, which split a night across
two rows that each mixed two nights); downtime_by_shift,
performance_by_shift and setup_durations gained the option.
fix: CapabilityTrendingEvents.capability_forecast subtracted the window index
twice, understating windows_to_threshold for later windows.
add: ShiftReporting.best_and_worst_shifts(as_frame=True); the dict default
emits a FutureWarning.
add: ReliabilityEvents (events/maintenance/reliability.py) -- reliability
KPIs from a failure-state signal (fault bit or status codes), built on
signals.primitives.intervals so states hold until the next change and
logging gaps (max_gap) are no data: failure_events (interval), mtbf_mttr
(MTBF, ISO 22400 MTBF, MTTR, availability, failure rate; overall or per
DST-correct calendar window), weibull_fit (censored MLE: beta, eta, MTTF,
B10, failure pattern) and reliability_at (conditional reliability and
hazard).
test: ISO 22400 OEE reference example (A x P x Q = 59.375 %).
October 14, 2026¤
add: ChangePointEvents (events/quality/change_point.py) -- offline
change-point detection: exact PELT (Killick et al. 2012) and binary
segmentation in plain numpy, Gaussian mean or mean+variance costs, BIC
penalty; detect_change_points (point) and segment_statistics (interval).
add: MultivariateSPCEvents (events/quality/multivariate_spc.py) -- Hotelling
T² with Phase I (beta) and Phase II (F) limits on a reference period,
per-variable contributions, and out-of-control runs with the top
contributor. Signals aligned backward with an optional max_gap.
fix: Gauge R&R follows the AIAG average-and-range method: AV subtracts the
repeatability share EV^2/(nr) (a negative radicand gives AV = 0), and AV
and PV use K2/K3 = 1/d2 (g = 1) instead of the large-sample d2. Before,
AV and PV were overstated (2 appraisers: by 25 %), and so were GRR and
%GRR. Checked against the AIAG worksheet constants.
add: EnergyPerformanceIndicatorEvents.enpi_vs_baseline(baseline="regression")
-- ISO 50006 energy baseline energy = a + b*units fitted on a fixed
baseline period (baseline_period= or the first baseline_window windows);
adds expected_energy_kwh and energy_savings_kwh. Default unchanged.
docs: every page now shows only names that exist (NumericFilter,
OutlierDetection, MetadataLoader, S3ProxyParquetLoader, NumericCalc and
wrong module paths replaced with the real API); tests/docs checks every
ts_shape import and attribute in the docs' code blocks. CI builds the docs
with mkdocs build --strict (38 warnings fixed). Python 3.14 classifier;
README and the development guide describe the real CI/release pipeline.
fix: eventlog static-shape event ids hashed the export time, so re-exporting
the same detector output gave different ocel:eid values; they are now
stable (ported from the open PR #60).
add: ts_shape.eventlog.describe("Class.method"), has_override() and
clear_overrides(); severity is coerced to the info/warn/critical
vocabulary (low/minor -> info, medium/major/warning -> warn,
high/alarm/error -> critical; anything else warns and becomes
October 13, 2026¤
Weekly screen of the non-production packs (see docs/gap_screening_other_packs.md). fix: CycleExtractor -- every process_* method returned cycle_end=NaT and is_complete=False; cycles now open on rising edges / step entries, never close at themselves, keep a tz-aware systime and ignore other uuids. fix: ToleranceDeviationEvents applied each measurement the next (future) tolerance; capability indices use the latest limits, a single tolerance is one-sided, and one measurement raises. fix: ControlLoopHealthEvents / DisturbanceRecoveryEvents align PV with the setpoint in force (backward as-of) instead of SP-left / nearest. fix: FailurePredictionEvents.remaining_useful_life no longer reports RUL 0 for a trend moving away from the threshold; NaN samples are skipped. fix: LeadTimeAnalysisEvents matches deliveries by order id when present. fix: EnergyEfficiencyEvents.efficiency_comparison summed raw counter readings. fix: tz-aware systime is preserved across quality/engineering/maintenance/ supplychain events (no more naive-UTC .values); DateTimeFilter accepts naive bounds on tz-aware columns. fix: MaterialBalanceEvents reported a zero-input window with output as balanced. fix: OutlierDetectionEvents -- zscore ignores NaN, MAD=0 falls back to mean absolute deviation, IsolationForest skips NaN. fix: SPC CUSUM with sigma 0/NaN returns no shifts (warning); steady-state windows with <2 samples are no longer "steady"; demand empty periods are not zero demand and calendar periods work in seasonality_summary. fix: setpoint oscillation crossings through an exact zero counted once; detect_startup_adaptive no longer flags a flat idle signal; track_startup_phases advances through non-overlapping phases. add: opt-in handle_resets (energy per-unit/EnPI/carbon/SEC, TimeGroupedStatistics 'diff'), handle_refills (inventory consumption_rate), interval_end="next_change" (threshold, signal quality, degradation, vibration, steady state, segments, low stock, correlation breakdown, time_above_threshold), time_weighted (material balance, idle energy), max_gap (error_integrals), missing_as_zero (material balance), group_by_uuid (outlier detection, boolean/string edge filters, TimeGroupedStatistics), inclusive (DateTimeFilter), ambiguous/nonexistent (TimezoneShift). Defaults unchanged. add: helpers utils.counters.counter_per_window, utils.intervals.interval_end_times, utils.time_weighted.time_weighted_resample. add: Base warns (DataQualityWarning) on NaT timestamps. fix: data_completeness / coverage_by_period use each window's real length (DST days are 23 h / 25 h); auto min_gap ignores duplicate timestamps. fix: lag_correlation / rolling_correlation lag and window in time on the regular grid instead of rows after dropna(). fix: detect_flatline starts a run at its first stuck sample; opt-in interval_end="next_change" for deadband historians. fix: GaugeRepeatabilityEvents.repeatability uses within operator x part ranges when operator_column is set. fix: overshoot_metrics undershoot is measured after the setpoint is reached. add: detect_warmup / detect_cooldown max_pause; detect_startup_adaptive baseline_window is now honoured (default None keeps the sample lookback).
August 20, 2026¤
add: PowerIntegrator (ts_shape.transform.calculator.power_integration) -- the missing kW -> kWh step. The events.energy detectors aggregate their input with sum(), i.e. they assume energy deltas in kWh; feeding an instantaneous active-power tag (e.g. *.Total_Active_Power-kW) in directly produced a number that scaled with the logging rate rather than with consumption, and a plain mean() was a sample-count average that over-weighted bursts. PowerIntegrator.energy_by_window integrates properly -- each sample weighted by how long it was valid, segments split at window boundaries (a hold from 00:55 to 01:05 books 5 minutes to each hour), locf or linear interpolation, max_gap to drop logging outages instead of billing phantom energy, power_unit for W/kW/MW tags, and per-signal integration before summing (energy adds across machines, power does not). Reports coverage per window and omits unmeasured windows rather than reporting them as 0 kWh. to_energy_deltas emits the result in the standard ts-shape schema so the energy pack can consume it; segment_energy exposes the per-sample audit trail. Exported at the top level as ts_shape.PowerIntegrator.
August 10, 2026¤
add: AssetHealthIndexEvents (events.maintenance.asset_health_index) -- fuses several degradation signals into one weighted 0-100 asset health index using the same drift/variance/trend penalty model as DegradationDetectionEvents.health_score. health_index reports the dominant failure mode and a confidence level (share of configured signal weight that had data); health_events emits warning/critical crossings; signal_contributions ranks the signals by the health they cost the asset; maintenance_forecast extrapolates to a critical threshold and withholds a date when the trend fit is weaker than min_confidence. Closes gap 3.1 of the manufacturing-operations research doc. add: ProductionScheduleAdherenceEvents (events.production.schedule_adherence) -- joins a planned schedule (start/end/planned_qty/order_id) against actual production from a monotonic counter. adherence_by_period reports adherence %, deviation units, an ahead/on_track/behind/critical_behind band, and the units/hour needed to recover in the time left in the period; deviation_events emits the breaches; adherence_summary rolls the horizon up weighted by planned quantity. Actuals are reset-aware by default (handle_resets=True). add: RootCauseCorrelationEvents (events.correlation.root_cause_correlation) -- directed, event-driven counterpart to AnomalyCorrelationEvents: takes another detector's events and ranks candidate signals by lagged correlation with the event onsets. Only non-negative lags are searched (a cause precedes its effect) and the winning lag's p-value is Bonferroni-corrected for the lag scan, so noise scanned over many lags is not promoted to a root cause. rank_causes / top_cause / lag_profile.
July 31, 2026¤
add: OEECalculator.calculate_oee now threads handle_resets to its performance and quality components and max_gap to its availability/performance components. Previously the top-level OEE could not benefit from reset handling, so a day with a counter reset silently dragged OEE toward zero; and availability booked a logging/overnight gap (last state = running) as run time. calculate_availability and calculate_performance gained a max_gap kwarg. Output schema unchanged. add: opt-in max_gap on RuntimeAccountingEvents.runtime_summary, runtime_per_window, and operating_hours_meter -- a gap to the next sample longer than max_gap is treated as a logging outage and excluded, so it no longer inflates run time, utilization, or the hour meter. fix: LineThroughputEvents.throughput_oee honored the documented availability_threshold parameter, which was previously accepted but ignored. A window now counts as available when its part count reaches availability_threshold x target_rate; the new default 0.0 reproduces the old "produced anything" behaviour. throughput_oee also gained handle_resets (threaded to count_parts). add: opt-in infer_dwell_from_next on the traceability timelines (OrderTraceabilityEvents.build_timeline / current_status / station_dwell_statistics, RoutingTraceabilityEvents.build_routing_timeline / station_statistics, MultiProcessTraceabilityEvents.build_timeline / station_statistics). A station that logs an identifier once on arrival otherwise reports a per-station dwell of 0; when set, each visit's end is the identifier's next station arrival (in multi_process, only for sequential visits -- parallel/overlapping visits keep their own span). Default unchanged. add: opt-in production_day extended to the remaining shift-grouping methods that share _assign_shift -- ScrapTracking.scrap_by_shift, ReworkTracking (rework_by_shift, rework_rate), QualityTracking (nok_by_shift, daily_quality_summary), OperatorPerformanceTracking.production_by_operator -- so an overnight shift is one contiguous (date, shift) group. Default (raw calendar date) unchanged. add: opt-in max_gap on DowntimeTracking.downtime_by_shift / availability_trend and max_cycle_gap on CycleTimeTracking.cycle_time_by_part and PerformanceLossTracking (performance_by_shift, slow_periods, performance_trend). A duration taken as next-time minus time otherwise bridges logging gaps and stoppages: a logger outage is booked as uptime, and a lunch break becomes one giant "cycle" that reads as a huge speed loss. Durations above the cap are excluded as "no data". Default (None) unchanged. add: opt-in time_weighted on BottleneckDetectionEvents.station_utilization (and detect_bottleneck / shifting_bottleneck / throughput_constraint_summary) and DutyCycleEvents.duty_cycle_per_window. resample().mean() averages sample counts, so on change-encoded/irregular signals a station up all hour but logged once reads 50-100% by row count; time_weighted weights each sample by the gap to the next sample. Default (sample mean) unchanged. fix: LineThroughputEvents.cycle_quality_check returned inf/NaN deviations when the expected cycle time was zero (explicit, or a degenerate zero median); it now returns the typed empty frame. add: ts_shape.utils.shifts (assign_shift, production_dates) -- shared shift assignment plus a "production day" that attributes an overnight shift's post-midnight readings to the shift's start date. Grouping a night shift (22:00->06:00) by raw calendar date splits it across two dates and, within a date, spans the whole day so last - first sweeps in other shifts' output (a night shift could report ~750% of target). add: opt-in production_day=True on TargetTracking.compare_to_target, ShiftReporting.shift_production, and ShiftHandover.generate_report so overnight shifts group as one contiguous interval. Default (calendar date) unchanged. add: opt-in require_all_stations=True on LineBalancingEvents.balance_metrics so a fully stopped station stays in the denominator (a dead station previously read as a perfectly balanced line); adds a stations_missing column. add: opt-in count_initial_active=False on AlarmManagementEvents.alarm_frequency to ignore an alarm already active at the start of the data window. add: ts_shape.utils.intervals.state_intervals -- shared helper that collapses a state signal into intervals and closes each one at the next transition when interval_end="next_change". The previous "end at the last sample carrying the state" logic collapses to zero duration on change-encoded (is_delta) signals -- one row per transition -- so downtime, micro-stop and duty-cycle analyses silently reported nothing on the library's normal data shape. add: opt-in interval_end="next_change" (with an optional data_end bound for the final open interval) on MachineStateEvents.detect_run_idle / state_quality_metrics and LongDowntimeEvents.detect_long_downtime, and as a constructor option on MicroStopEvents and DutyCycleEvents. Default ("last_sample") is unchanged. On change-encoded signals this recovers micro-stop lost time, multi-hour downtimes, and on/off durations that previously read as zero. (Traceability dwell shares the collapse but has distinct cross-station semantics and is a separate follow-up.) add: ts_shape.utils.counters (counter_quantity, counter_increments, count_resets) -- shared reset-aware handling for monotonic production counters that reset to zero at a shift/part change or PLC restart. A naive last - first loses all production in a window where a reset happened. add: opt-in handle_resets=True across the production pack so the reset-aware behaviour shipped in PartProductionTracking is available everywhere a quantity is derived from a counter: OEECalculator (calculate_performance, calculate_quality), LineThroughputEvents.count_parts, TargetTracking, ScrapTracking, ReworkTracking, QualityTracking, BatchTrackingEvents, OperatorPerformanceTracking, ContinuousProcessAlignment.segment_by_cut, ShiftReporting, ShiftHandover, and PeriodSummary. Default behaviour and column sets are unchanged; when enabled the result gains a resets column. For the by-reason / by-part methods this also corrects the over-count that last - first produces when categories alternate over a non-contiguous group. fix: DowntimeTracking.downtime_by_reason booked running time as downtime (it diffed timestamps after filtering to stopped rows, so a stop lasted until the next stop). Duration is now computed on the full state timeline before filtering, mirroring downtime_by_shift. fix: QualityTracking.daily_quality_summary returned NaN rates for a zero-total day (0/0); both rate divisions are now guarded to 0.0. fix: LineThroughputEvents.throughput_oee produced NaN/inf performance when the target rate was zero (flat counter or explicit 0); it now reports 0. fix: ShiftReporting.shift_targets produced inf achievement_pct for a zero target; now guarded to 0.0, matching ShiftHandover. add: ChangeoverEvents.detect_changeover gained include_initial (default True preserves the current behaviour of emitting the first reading; pass False to report only real value changes and drop the synthetic leading event). docs: docs/production_gap_screening.md -- a full functional-gap screen of the production pack, with the remaining themes (interval-duration on change-encoded signals, gap-spanning durations, time-weighted utilisation, overnight-shift attribution) lined out as scoped follow-ups.
June 2, 2026¤
changed: event-log output now trims entirely-empty extra columns. The 9
canonical core columns (ocel:eid, ocel:activity, ocel:timestamp,
ts_shape:start_timestamp, ts_shape:duration_s, ts_shape:detector,
ts_shape:pack, ts_shape:severity, ts_shape:value) are always emitted, so
every event log keeps an identical append-friendly core schema; per-detector
extras (
May 20, 2026¤
add: Pipeline -- the single declarative orchestrator for ts-shape. Chains transform and detector steps into one reusable definition: .transform() steps replace the working signal; .detect() steps store named event results. Supports $input/$prev sentinels for multi-DataFrame wiring, run_steps() for intermediates, describe() for previews, and PipelineResult.to_event_log() for combined OCEL export. BREAKING: removed FeaturePipeline (features.segment_analysis.feature_pipeline); Pipeline replaces it. Migration: FeaturePipeline(df)...run() becomes Pipeline()...run(df); .add_step(Cls.method, **kw) and .add_instance_step(Cls, call='method', **kw) both become .transform(Cls, 'method', **kw); .add_lambda_step(fn) becomes .transform(fn). $input/$prev sentinels and run_steps() are unchanged. add: UnitConverter -- engineering unit conversion (transform), a thin wrapper around the pint library. Optional extra: pip install ts-shape[units]. add: RuntimeAccountingEvents -- operating-hours accounting (total run time, start count, longest run, utilization, per-window runtime, hour-meter). add: LineBalancingEvents -- line balancing & takt analysis (station cycle times, balance efficiency/delay, smoothness index, theoretical minimum stations, Yamazumi station-loading table). add: FlowMetricsEvents -- flow analytics (time-weighted WIP, throughput, FIFO lead time, Little's Law consistency check, Process Cycle Efficiency). add: ts_shape.make_timeseries() -- public synthetic-data generator for trying detectors and transforms without real data or loaders. add: ts_shape.list_detectors() -- programmatic catalog of every top-level class, grouped by pack/category. add: Base.repr -- detector and instance classes now print a useful summary (row count + configured uuid/value_column). changed: OutlierDetectionEvents emits the canonical point shape (systime, uuid, source_uuid) via events/_output.py -- completes the May 14 output standardization. uuid carries the event id, source_uuid the source signal. changed: event detectors validate their configured UUID up front (Base._validate_uuid) -- a typo'd UUID now raises a clear error listing the available UUIDs instead of silently returning empty results. fix: DatapointAPI HTTP requests now send a timeout (default 30s) so an unresponsive server can no longer hang the loader. fix: TimescaleDBDataAccess uses bound SQL parameters instead of f-string interpolation. fix: CycleExtractor uses Base's sorted, defensive copy -- it no longer mutates the caller's DataFrame. fix: README quick-start and pack examples corrected to match real constructor signatures (SPC, ToleranceDeviationEvents, DataIntegratorHybrid, TimeGroupedStatistics).
May 14, 2026¤
BREAKING: event-detector outputs standardized across all packs (quality, production, engineering, maintenance, supplychain, energy, correlation). Every public DataFrame-returning method now emits one of three canonical shapes: point (systime), interval (start, end, duration_seconds), or summary (start, end, duration_seconds + aggregate columns).
Column renames applied uniformly: start_time, gap_start, window_start, period_start, disturbance_start -> start end_time, gap_end, window_end, period_end, disturbance_end -> end severity_score, severity_level -> severity OEECalculator: date -> start + end + duration_seconds (86400)
New helpers in src/ts_shape/events/_output.py (empty_event_df, finalize_point_df, finalize_interval_df, finalize_summary_df) define the canonical column constants and empty-frame schema.
ts_shape.eventlog.adapters.adapt no longer probes legacy column name variants -- it expects the canonical names. The taxonomy registry has been updated (severity_field="severity"). See docs/guides/eventlog.md for the simplified shape table.
Downstream code asserting old column names must be updated.
Sep 09, 2025¤
add: Azure blob storage container loader add: Metadata JSON loader added changed: development guide
Apr 06, 2025¤
add: quickstart guide added to docs
Dec 26, 2024¤
add: mkdocs material deployment with gh actions
Dec 25, 2024¤
add: pdoc docs exchanged with mkdocs material autodoc
Dec 23, 2024¤
add: library rename add: library structure change. loader, transform, feature, context, events
Dec 20, 2024¤
fix: closes #7
Nov 16, 2024¤
add: dev state docs for combine/integrator.py add: dev state for combine/integrator.py add: metadata loader improved
Nov 4, 2024¤
add: stats classes improved + feature table class added
Oct 29, 2024¤
add: timescaledb loader adjusted
Oct 28, 2024¤
add: loader classes adjusted add: classes for timestamp_converter added add: classes for s3, timescaledb, timezone_shift added
Oct 27, 2024¤
add: docs for time_stats added add: time_stats for numeric value columns added
Sep 11, 2024¤
add: methods refactored to execute without an instance
Sep 9, 2024¤
add: cycle methods refined and splitted to cycle processor and extractor
Sep 8, 2024¤
add: cycle method and metadata loader including tests for numeric filters add: additional methods added
Aug 25, 2024¤
fix: docs re-created fix: docs add: parquet loader, timestamp, string, numeric and boolean stats methods
May 4, 2024¤
change: typings added, first test added change: package folder moved init: pypi package structure for timeseries-shaper / internal project for my master thesis