Thanks for helping. The most useful contributions are a bug report with a reprex, a new engine, and a measurement that shows a claim in the docs is wrong. This page covers all three.
🐛 Reporting a bug
Open an issue with the bug template. Include a reprex, packageVersion("ggchangepoint") and the engine’s version (fit$versions on any result shows both). If the answer is wrong rather than an error, say what you expected and why: a wrong answer that runs is the kind of bug this package most needs to hear about.
🔌 Adding an engine
Every wrapper has the same five steps, and the registry does the rest.
| Step | Where |
|---|---|
| 1. Check the input and load the engine |
validate_data(x), then need_pkg("engine")
|
| 2. Call the engine | inside the wrapper; cpt_detect() adds the engine-error handling |
| 3. Extract the changepoints as the last observation before each change | convert if the engine reports the first observation after ("right") |
| 4. Build the result | ggcpt_build(x, cp, method =, change_in =, penalty =, fit =, call = match.call()) |
| 5. Register it | a row in builtin_registry_core() in R/registry.R
|
Rscript data-raw/use_cpt_wrapper.R <method> <package> <function> writes a skeleton wrapper, a test file and the registry row to paste.
Then fill in what the registry derives everything else from:
-
Capabilities: the flags in the registry row (
ci,fitted,posterior,statistic,path, …).cpt_methods()shows them, and a flag that isTRUEmust be backed by a column in the result. -
Vocabulary (
R/vocabulary.R): the families it can fit (family_rows_explicit()), its modelling-choice arguments and their legal values (method_choices()), the argument a minimum segment length becomes (min_segment_args()), and its upstream changepoint convention when it is not"left"(upstream_conventions()). -
Citation: a row in
cpt_references()(R/cite.R), which is whatcpt_cite()prints, and a BibTeX entry ininst/REFERENCES.bibfor the wrapper’s help page (\insertRef{}). -
Measurements: run the engine through
data-raw/na_handling.R(what it does with a missing value) anddata-raw/measure_engines.R(runtime, invariances, noise regimes, data types, null size), thendata-raw/build_measured_data.R. The measured columns ofcpt_methods()andcpt_recommend()’s scores come from those tables, never from a hand-written list.
The convention test, the change-type contract sweep and the boundary-input matrix in tests/testthat/ run every registered engine automatically, so a new wrapper is checked against the contract the moment its row exists.
✍️ Code conventions
-
Errors and warnings are classed. Use
cpt_abort(..., class = )andcpt_warn(..., class = ), neverstop()orwarning(): the classes in?ggchangepoint-conditionsare API. A meta-test enforces it. -
Choices are validated by name.
cpt_match_arg(), which suggests the nearest valid value, notmatch.arg(). - Comments say why. The code says what. A guard that exists because an engine misbehaved on some input names the input and what it did.
-
A slow test (0.2 seconds or more) starts with
skip_on_cran(); one that runs an engine checksengine_usable()first.
✅ Before a pull request
Rscript -e 'devtools::document()'
NOT_CRAN=true Rscript -e 'devtools::test()'
R CMD build . && R CMD check --as-cran ggchangepoint_*.tar.gzAdd a line to NEWS.md under the development version.
📜 Stability
Anything in the contract (exported arguments, result slots, condition classes, the JSON schema) changes only through the deprecation cycle in the stability article.
