Changelog¶
Releases, newest first. While the version is 0.x a minor release can change any interface, and the entries say which ones moved.
0.10.0 - 2026-09-30¶
Added¶
tsdive profilereports the longest constant run of the window: the longest stretch of GOOD samples that hold one value, its first and last sample, the time between them and the sample count. The Values section prints it asconstant run <start> -> <end> <duration> n=<samples>.--json,Profile.to_dict()and the MCPprofileanswer carry it asvalues.constant_runwithstart,end,duration_sandsamples, ornullwith no GOOD sample. A freeze that ended before the window end readsstall 0 sand shows here. The constant run sets no flag, because a tag archived on exception or compression settings also holds one value for hours. A SYNTHETIC row ofBENCHMARKS.mdplants a 400-sample freeze in 7 days at 300 s, and the runprofilereports equals it.- The tag table of
tsdive run, inledger.txtandreport.html, addsconstant, the longest constant run as its duration and sample count, anderrors, the steps that filed an error row for the tag. Eachtagsrow ofledger.jsoncarriesconstant_run_s,constant_run_samplesanderrors. - The MCP
screenandspctools takemax_runs, the runs to list per rule, 40 when left out.runs_droppedcounts the runs left out, at the top of ascreenanswer and on each rule of anspcanswer.
Changed¶
- Breaking:
WindowStatsintsdive.featurestakes a requiredconstant_runfield, aConstantRunorNone.TAG_COLUMNSintsdive.narrate.ledgeraddsconstantanderrors.
Fixed¶
- A single-tag ingest of an export whose tags sample on offset clocks,
such as tag A at :00, B at :20 and C at :40, raises
SchemaErrornaming the tag column and--tag-col. It wrote one archive of every tag's rows before, because no timestamp repeats and none runs backwards. The check takes an unread column whose series overlap in time, are each in time order, and alternate in more than half of the consecutive rows. A shift, batch or row id column does not qualify, and neither does a column of floats.ingest_longruns the same check on each tag's rows. - The MCP
screenandspcanswers list at most 40 runs per rule whenmax_runsis left out. They listed every run before. On two days at 60 s with a lone spike every fourth sample, thespcanswer holds 17,278 characters instead of 188,754, and thescreenanswer 9,376 instead of 142,808. On the switchback demo temperature, a 12 h baseline and a two-day window, thespcanswer holds 24,858 characters instead of 32,884 and lists 40 of its 74TREND_6runs.tsdive screen --jsonandtsdive spc --jsonkeep every run.
0.9.0 - 2026-09-29¶
Added¶
- CI tests Python 3.12 on Linux, Windows and macOS, and Python 3.13 and 3.14 on Linux. The reference case and the benchmarks run on Python 3.12 on Linux. The package classifiers list the three versions.
- A CI job installs the lowest version of each direct dependency that its range allows and runs the tests. It installs pandas 2.2.2, numpy 2.0.0, pyarrow 23.0.1 and pint 0.24.4.
- A weekly workflow locks the newest versions the ranges allow, then runs the tests, the reference case and the benchmarks. A failed run is the report.
- The release workflow installs the built wheel in a clean environment
and runs
tsdive demoandtsdive profilebefore it uploads.
Changed¶
- tsdive accepts pandas 2.2 to 3.x (
pandas>=2.2,<4) and pyarrow 23.0.1 to 25.x (pyarrow>=23.0.1,<26). The lock file installs pandas 3.0.6 and pyarrow 25.0.1. Under pandas 3,ingestreads the date order, the decimal mark and each tag's value type from text columns as under pandas 2. - pint needs 0.24.4 or newer (
pint>=0.24.4,<1). pint 0.24 to 0.24.3 fail to import next to flexparser 0.4. - Breaking: the
tsfmandtepextras are removed.pip install "tsdive[tsfm]"andpip install "tsdive[tep]"install tsdive alone. In a clone,uv sync --group tsfminstalls chronos-forecasting forexamples/studies/3w_chronos, anduv sync --group tepinstalls pyreadr forscripts/convert_tep.py. The library imports neither. - Breaking:
Backbone.tag_path,severity_floor_noteintsdive.features.window_features, anddim,greenandyellowintsdive.ui.termare removed. Nothing in the package called them. - The documentation build runs the switchback transcript of
docs/SWITCHBACK.mdon the demo data. A test runs each README transcript command on the demo data and fails when the output drops a line the README shows.
Fixed¶
- An archive with timestamps stored in microseconds or milliseconds
gives the same results as one stored in nanoseconds.
profile --flatlinefound no reference history on such an archive,compareread its change intervals 1000 times too short and could report a moving tag asfrozen, andreport-htmldrew its samples outside the plot. Under pandas 3,ingestwrites microsecond timestamps. - With no reference history, the flatline
time_since_last_actual_changefinding of a window whose value changed readsstall 120s; no reference history providedinstead ofno GOOD samples; signal not evaluable; no reference history provided. A window with one GOOD sample readsfewer than 2 GOOD samples; signal not evaluable.
0.8.0 - 2026-09-29¶
Added¶
- Every JSON document opens with
result_kindandtsdive_version: the--jsonoutput of each command that takes the flag, the refusal object, each MCP answer andledger.json.result_kindisevidencefor an analysis,refusal,ingest,planforswitchback plan --json, orledger.to_dict()returns the document without the two keys. tsdive ingest --jsonprints one object:form(single,wideorlong) andarchives, one entry per archive written withpath,tag,identity,rows,first,last,quality_source(columnorassumed) andassumed_quality. Under--init-metathe object liststemplates. A refused ingest prints the refusal object and exits 3.tsdive run --strictexits 2 when a step filed an error row, else 3 when a step filed a refusal row, else 0.ledger.jsoncarriestags, one row per archive read off its profile:coverage,good_share,censored,gaps,longest_gap_s,flatlineand the stepsrefusedfor it. Each finding carriesdata, the document the step prints under--json.ledger.txtandreport.htmlopen with the same table, andledger.txtholds every profile.ScreenAnalysis.to_dict()andSpcAnalysis.to_dict()carryruns: each stretch of consecutive flagged GOOD samples asstart,endandn, with itsruleinspc.- The MCP
screenandspctools takemax_events, the flagged timestamps or hits per rule to list, 0 when left out.flagged_droppedandhits_droppedcount the entries left out, andn_flagged,n_hitsand each rule'sncount every sample. On the switchback demo temperature, a 12 h baseline and a two-day window, thespcanswer holds 32,828 characters instead of 223,070 and thescreenanswer 8,094 instead of 53,974. make api-difflists the public API breaks since the lastv*tag with griffe.
Changed¶
ledger.jsonholds each refusal as an object (step,tags,error_type,cause) instead of a[ErrorName] step tags: messageline. A step that raisesValueErrororOSError(a rejected option, overlapping windows, a file the OS cannot read) files a row of theerrorslist instead of a refusal.tsdive runprints the row asERRORand addserrors Nto its headline. The default exit rule oftsdive runstays as it was.tsdive screenandtsdive spcprint consecutive flagged samples and rule hits as one line per run, with its span and sample count. Each section lists five runs and counts the rest as(+N more runs). A lone flag or hit prints as before.RUNS_SHOWNreplacesFLAGGED_SHOWNintsdive.analyses_render.- Breaking: the optional fields of these public dataclasses are
keyword-only, so a positional call raises
TypeError:TagMetafromunit_rawon,SamplingContract(aggregate_type,stepped),Profile(flatline),ScreenAnalysis(mode_path,provisional,regimes,alignment),CompareAnalysis(top),SwitchbackAnalysis(assumptions,covariate_checks),SwitchbackEstimate(estimate,p_value,lo,hi,reason,detail) andSwitchbackPlan(power). Pass each by name. A field added to one of them no longer moves another.
Fixed¶
- A path the OS cannot read, such as a directory passed as an archive,
exits 2 with one
error:line that names the path and carries the OS message, instead of a traceback and exit 1. The MCP server returns the same message as a tool error instead ofError executing tool.report-htmlnames the error class of each unreadable archive instead ofFileNotFoundErrorfor every one. mspcand the joint table ofcomparedo not assess SPE for a model that keeps as many components as tags. Its residual is zero up to rounding, and its empirical limit flagged rounding error: four independent tags reported 3 SPE breaches in 200 rows. The report printsSPE NOT ASSESSEDwith the reason, andmspcadds the--variancevalue that keeps one component fewer. The JSON carriesspe_breaches: nullandspe_not_assessed, the SPE limit is null, andmspcranks no contributors for such a model.
0.7.0 - 2026-09-29¶
Added¶
tsdive ingest --tag-col COLreads a long export, one row per tag and timestamp with the tag inCOL, and writes one archive per tag into--out. Metadata comes from--meta-dir,--init-meta DIRwrites one template per tag,--tagspicks a subset, and every check runs before the first archive is written.tsdive.ingest_longandtsdive.init_long_metaare the Python forms.tsdive ingest --sep,--decimaland--encoding, and thesep,decimalandencodingkeywords of every ingest and template function, read a CSV with another column separator, decimal mark or text encoding, such as the;-separated, comma-decimal cp1252 file of a German Excel. Given for a parquet file, they are a usage error (exit 2).ZeroSpreadBaseline, a refusal for a baseline whose GOOD values do not spread. The message names the tag, the baseline window, the count of distinct values and the most common value with its share.- A metadata template lists each string of a value column that holds
numbers and strings, such as a PI digital state, under
quality_codeswith no severity.
Changed¶
- The sdist lists the paths it holds: source, tests, docs, examples,
scripts and the top-level project files. A local build leaves out
files that one clone excludes from git in
.git/info/exclude. - Ingest parses a timestamp column in one pass. It parses one row at a time only a column whose rows carry different UTC offsets, and the rows the one pass cannot read. A 129,600-row export of one-minute samples ingests in 1.9 s instead of 99.6 s, and every archive the test suite writes is byte-identical.
- The
SchemaErrorfor strings in the value column lists every string with its row count, and its example maps each of them. mad_baseline,moving_range_baselineandregime_baselinestakelabel, the tag and window their refusal names.mspcand the joint table ofcomparedivide each tag by its baseline standard deviation before the PCA, so a tag's unit no longer sets its weight. On the demomspcreports 70 T2 breaches of 121 rows instead of 22 (SPE stays at 108), explained variance 0.9767 instead of 0.9839, and limits T2 3.759 and SPE 0.2859 instead of 4.052 and 0.03662.comparekeeps 0.5129 of the after variance instead of 0.2643, and its two SPE contributors carry 50% each instead of 79% and 21%.PcaModelcarries thescaleit applies.
Fixed¶
- A single-tag ingest of an export that holds several tags raises
SchemaError(exit 3) naming the tag column and--tag-col, instead of writing one archive that mixes every tag. The refusal applies when timestamps repeat or run backwards and a column the ingest leaves behind splits the rows into overlapping series, each in time order. - Ingest raises
NonMonotonicIndex(exit 3) for rows whose timestamps run backwards, instead of writing an archive every read refuses. - Ingest places the hour the clocks repeat in autumn by row order, first
pass at the summer offset, instead of refusing every export in local
time that crosses the change. A time in that hour the export holds
once, rows of it out of time order, and a spring time the clocks skip
raise
SchemaErrorwith a message for each case. screen,spcandscreen --moderaiseZeroSpreadBaseline(exit 3) for a baseline whose MAD or moving-range scale is 0, instead of limits of zero width that flag every sample off the center.mspcraises it for a tag whose baseline standard deviation is 0, andindividuals_limitsfor a sigma of 0. Incompare, the tag table printsno spread beforeas the flagged reason, and the joint table is refused with the error as its reason.
0.6.0 - 2026-09-29¶
Added¶
tsdive demo [DIR]andtsdive.write_demo_datawrite the demo archives, two tags for the walkthrough and three for the switchback trial, into a directory,tsdive-demo/by default. An archive that exists already is refused, and nothing is written.- The documentation site gains a getting-started tutorial, eleven concept pages, the annotated output of profile, screen, spc, mspc, compare and switchback analyze, six how-to guides, an errors and refusals reference, a glossary and a home page that starts from the reader's question. Every command on those pages runs on the demo data when the site is built, and every Python snippet runs as a test.
Changed¶
scripts/make_demo_archive.pyandexamples/switchback/make_trial.pycall the builders intsdive.demoand write the same bytes as before.- The README installs with
pip installand writes the demo data withtsdive demo data, so the transcripts need no clone.
Fixed¶
- The
SchemaErrorfor a date that reads day first and month first suggests a strptime format with the shape of the value it quotes, such as%d/%m/%Y %H:%Mfor01/02/2026 00:00, instead of always%d/%m/%Y %H:%M:%S. tsdive-mcpwithout themcpextra names the git and release-wheel installs with the extra, instead of a command that works only in a clone.
0.5.0 - 2026-09-28¶
Added¶
tsdive ingest --dayfirstand--timestamp-format, and thedayfirstandtimestamp_formatkeywords ofingestandingest_wide, state the date order of an export.tsdive ingest <export> --init-meta META.jsonandtsdive.init_tag_metawrite a metadata template for a single-tag export.retrieval_modein tag metadata,RECORDEDorINTERPOLATED, is stated in the sampling contract of every read of the archive.Profile.to_dict()returns the documenttsdive profile --jsonprints.switchback analyzetests each covariate's own difference between the settings and flags one the setting moves;--jsonlists the tests undercovariate_checks.compareprints each refused pair or joint table under the headline, and--jsonmaps them to their reasons underrefused_tables.
Changed¶
- A refusal (a typed
TSDiveError) exits with status 3 instead of 2. Usage errors and invalid input still exit 2, andtsdive runkeeps 0 and 2. - Under
--json, a refusal also prints the object the MCP server returns on stdout:result_kind,error_typeandcause. switchback analyzeexits with status 3 when its difference in means is refused.- A metadata key tsdive does not define, one end of the engineering
range without the other, or a span of 0 or less raises
SchemaErrorinstead of being dropped. - A date that reads both day first and month first raises
SchemaErrorat ingest unless the order is stated. - Errors raised from Python name keywords such as
rate_s=where the CLI names flags such as--rate-s. - The profile, segment, screen, spc and switchback
--jsondocuments carryrange_knownbesidecensored.
Fixed¶
- Reports print
censored unknown, and--jsonprintscensored: null, when no engineering range is declared and nothing is flagged, instead ofcensored no. - A profile of an empty window prints
clipped null (no samples)when the range is declared, instead ofeng range unknown. - A value-column string the tag's
quality_codesnames, such as PI'sI/O Timeout, is nulled at its declared severity instead of raisingSchemaError. - A file that is not a tsdive archive raises
SchemaErrornamingtsdive ingestinstead of a pyarrow error. ScheduleMismatchon an edited plan says to restore the plan file with the recorded digest instead of planning the trial again.- A refused power readout prints the history window that was passed and the span the schedule needs, instead of a span past the window.
- The
switchback plan --windowand--history-windowhelp states that bounds with a UTC offset are converted.
0.4.0 - 2026-09-28¶
Added¶
tsdive.switchback_planandtsdive.switchback_analyze: a balanced random schedule of settings A and B over one window, written as a plan file with a SHA-256 digest, and the difference between the settings on a target under that plan by randomization inference, with an adjusted estimate on declared covariates.SwitchbackPlan,SwitchbackAnalysis,SwitchbackEstimate,DesignTooSmallandScheduleMismatchare exported beside them.tsdive switchback planandtsdive switchback analyze, with--historyand--history-windowfor a power readout, repeatable--covariate, and--json. Atsdive runplan can listswitchbackas a step.tsdive-mcpservesswitchback_analyzeas a sixth tool.docs/SWITCHBACK.mdandexamples/switchback/make_trial.py, a synthetic trial for its transcripts.- Two benchmark rows: the switchback claim rate at a zero shift and its detection of a 0.5 sigma shift on seeded AR(1) records.
Changed¶
docs/SCOPE.mdstates no causal claims from observational data, withswitchback analyzeas the one exception, instead of no causal inference at all.
Fixed¶
comparepair intervals resample both periods with 1000 replicates instead of the after period with 200, so they are wider and fewer pairs clear.scripts/convert_tep.pylabels the first faulty sample 21 (training) and 161 (testing) instead of 20 and 160.
0.3.0 - 2026-09-03¶
Added¶
tsdive.eval: the evaluation protocol as an API.ranking_metricsreturns ROC-AUC, PR-AUC and precision at a recall floor and reports a one-class fold as a refusal;clock_controlscores a window by its position in its record;worst_baseline_threshold,fires,far_floorandover_floorcarry the alarm rule and its false-alarm floor;group_holdout,GroupSplitandGroupLeakageare re-exported.tsdive.eval:conformal_p_values,power_martingale,mixture_martingaleandmartingale_alarmbuild a conformal test martingale alarm whose false-alarm probability over a whole record is bounded bydeltawhen the calibration and stream scores are exchangeable.
Changed¶
tsdive.analyses_render.render_linesreplaces the private line splitter the plan runner imported from the CLI module.
0.2.0 - 2026-09-02¶
Added¶
tsdive.segment,tsdive.screen,tsdive.spc,tsdive.mspcandtsdive.comparereturn result objects withrender(),to_dict()andframe. The CLI prints the same text and JSON.tsdive ingest --widereads an export with one column per tag into one archive per tag.--quality-suffixnames the per-tag quality columns,--tagspicks columns, and--init-meta DIR --source-id IDwrites one metadata template per column.- Window arguments accept
START/DURATION,DURATION/ENDand a bare date standing for one UTC day, alongsideSTART/END. report-htmlandrundraw one SVG plot per tag: values, samples below GOOD, gaps and the engineering range. Inrunthe plot also carries the screen limits, the flagged samples and the SPC rule hits.tsdive segment --mode-out FILEwrites the segments as a MODE archive thatscreen --mode FILEreads as regimes.- A plan can set
beforeandafterand listcompareas a step. tsdive-mcp, a read-only MCP server overprofile,segment,screen,spcandcompare, installed with themcpextra.
Changed¶
--jsonand--no-colorare accepted before the command name as well as after it.
Fixed¶
- The refusal messages of regime baselines, unit resolution and time-weighted averaging name the defect they found.
0.1.0 - 2026-09-01¶
First release: parquet archives carrying tsdive.meta, the commands
ingest, profile, segment, screen, spc, mspc, compare, run
and report-html, the 3W and TEP converters, the benchmark rows and the
3W study reports.