Version 2026.8.6
Licensing
-
DESCRIPTIONAuthors@Rnow declares Richard Aubrey White as the copyright holder, withrole = "cph". It declared none at all, and neither did any other package in the fleet. Nothing inR CMD checkreports that. - The copyright year is unchanged at 2026, and is now confirmed correct.
-
CLAUDE.mdnow carries a Licensing section, so the year gets checked rather than silently ageing.
Bug fixes
- The
README.mdquick start could not run. It calledcp$load(d), andloadis not a public method: the class exposes 21 methods andloadis not among them. Data enters throughCohortPipeline$new(dt). The example now readsCohortPipeline$new(d). - The same example printed the wrong numbers. Six rows survive the three root exclusions, and four of them are male, so
Not femaleexcludes four and leaves two. The README claimed one excluded and five included. Both the print block and the consort table now carry output captured from a real run.
Documentation
- All roxygen prose in
R/cohort_pipeline.R, plusvignettes/cohort.Rmd,README.mdandindex.md, now follows ASD-STE100 (Simplified Technical English). Every sentence in those four files runs to 25 words or fewer. The change splits long sentences, prefers the active voice, and removes idiom.
Version 2026.8.3
Documentation
Documentation only. No behaviour changed, and no runtime message, warning or error string changed.
-
index.mdis now listed in.Rbuildignore, so the pkgdown home page body no longer ships in the source tarball. It is not a fileR CMD checkrecognises, and--as-cranraised “Non-standard file/directory found at top level: ‘index.md’” on every run. -
?CohortPipelinenow carries a\seealsonamingvignette("cohort")and saying what the vignette works through: branching, cached artifacts, schemas and CONSORT diagrams. # Version 2026.7.27
Bug fixes
-
$list_artifacts()now returnscharacter(0)for a cohort with no artifacts. It previously returnedNULL, which broke the documented “character vector” contract and any caller indexing the result. -
$list_cohorts()on an empty pipeline now returns a zero-rowdata.tablecarrying the eight documented columns (name,parent,n_total,n_included,n_excluded,n_own_steps,n_artifacts,frozen). It previously returned a zero-row, zero-column table, so column access on an empty pipeline failed. This matches$consort(), which already returned a typed empty table.
Version 2026.6.23
Bug fixes
-
exclude_and_track()now errors when a predicate evaluates to a non-logical result (character, numeric, factor, or a logical matrix) instead of silently coercing it withas.logical(). A numeric predicate previously excluded every non-zero row and a character predicate logged a phantom exclusion, corrupting the audit trail. The documented contract – predicates returnTRUE/FALSE,NAmeans keep – is now enforced. - Warm-cache replay: changing a non-root cohort’s later own exclusion no longer retains the stale step.
.invalidate_from()treated its cursor as a branch-local count while the caller passed an absolute log index, double-counting the inherited prefix so the truncation under-removed. Root cohorts were unaffected (zero prefix). - Warm-cache replay: moving
$new_cohort()before a parent exclusion (an order that errors on a cold run via the freeze rule) now errors instead of silently reusing the child’s stale post-exclusion snapshot. The parent’s replay position is checked against the child’s branch point; on mismatch you are directed to$invalidate()(or to delete the cache).
Version 2026.5.10
Initial release.
Display labels and API simplification
-
load()is no longer a public method; the constructor is the only way to install the base data. UseCohortPipeline$new(dt)(with optionalcache_file). -
CohortPipeline$new()and$new_cohort()accept alabel =argument: a human-readable display label used by CONSORT diagrams and$list_cohorts(). Cohort identifiers ("root","adults_female") remain how you reference cohorts in code; labels are presentation only. - Re-issuing
$new_cohort()with a different label silently updates the field without invalidating the cache.
Cache integrity
- The cache now stores a
digest::digest(dt, algo = "spookyhash")hash of the base table alongside the operation log. On warm load with a supplieddt, the hash is recomputed and compared; a mismatch warns loudly and rebuilds from scratch. Catches silent data updates that would otherwise produce wrong results from stale cached state. AddsdigesttoImports. - Cache schema version bumped to 3.
Incremental caching (new)
-
CohortPipeline$new()accepts acache_file =argument. When the file exists, the pipeline is restored from it and operations replay against the cached log; matching operations are no-ops (cache hits), divergent operations recompute only the affected cohort and its descendants.cp$save()writes the current state to the cache file. -
set_artifact()gains anargsetparameter and accepts the new 3-argument fn signaturefunction(dt, sib, argset). The cache key is(name, from, body(fn), argset). The legacyfunction(dt, sib)signature is still accepted (compat shim). - New
cp$invalidate(cohort, artifact)to manually drop a cached cohort or artifact when a helper changes that the cache key cannot detect. -
$new_cohort(name, from)is now idempotent on identical (name, parent) pairs (required for cache replay). It still errors loudly if the same name is reissued with a different parent.
Branding
- Hex sticker logo at
man/figures/logo.png, generated bydata-raw/logo.Rand matching the house style of sibling packages (plnr, attrib, org).
Features
-
CohortPipelineR6 class for cohort construction with full provenance:- Branched cohort trees via
$new_cohort(name, from). - Per-step exclusion logging via
$exclude_and_track(branch, reason, expr_str). - Cached derived artifacts via
$set_artifact(name, from, fn). - Schema validation via
$declare_schema()and$validate(). - CONSORT diagram generation via
$plot()(auto-discovered) or$draw_consort_panels()(manual layouts).
- Branched cohort trees via
The freeze rule
A cohort becomes frozen the first time another cohort branches from it, or the first time an artifact is set on it. After freezing, $exclude_and_track() on that cohort errors. The rule guarantees a cohort’s name maps to exactly one definition forever and that cached artifacts stay consistent with the included rows that produced them. Multi-way forks are unaffected.
Implementation notes
- Shared base table + per-branch integer index of included rows. Branching never copies the data values.
- Integer status codes (per branch) replace in-band string status columns. The user’s data table is never mutated.
- Exclusion logs accumulate in a list and materialize on read, avoiding quadratic
rbindgrowth. -
$get_included()always returns an independent copy. -
$get_everyone()reconstructs a per-branch full view (rows + a.cohort_statuscolumn) so the returned object is meaningful for any branch in the tree. -
$plot()defaults to plotting every cohort regardless of freeze state, so unfrozen leaf cohorts (the typical analytic endpoint) are always shown. - CONSORT rendering is now implemented directly in
gridinstead of via theconsortpackage. Arrows now terminate exactly at side-box edges (theconsortrendering placed them inside the box), and multi-panel layouts top-align panel content. Theconsortpackage has been dropped fromImports.
