This patch addresses CRAN review of examples, console output and global workspace changes. Dependencies and exported signatures are unchanged.
weasel_example() help example runs normally
instead of using \dontrun{}.options(weasel.verbose = FALSE) also
suppresses explicit table display while retaining the formatted return
value.seed = NULL, the separate process draws and reports
its own seed; repeated calls can produce different panels. Each call
incurs process startup time, and its temporary files are removed on
exit, including errors.This patch release strengthens input validation, saved-plan data checks and generated explanations, and corrects dummy-data and duplicate-pair edge cases. Runtime dependencies and exported function signatures are unchanged.
weasel_data_mismatch) on
structural drift, retaining the saved scenario IDs without replanning or
changing the plan. Existing saved fingerprints without an encoding
version retain their historical checks and encoding limitations;
rebuilding from verified original data creates a new fingerprint.
Unsupported encoding versions raise
weasel_error_fingerprint_version rather than choosing a
legacy encoding.weasel_selectivity() now preserves a common finite
covariate value when all non-missing values in a duplicated
respondent-wave pair are identical. Rounding while averaging copies
could previously create artificial spread and a huge finite SMD when
both comparison groups were constant. Constant pairs also retain their
finite value when their sum would overflow; later mean,
standard-deviation and SMD calculations still have their existing
floating-point limits, so extreme-value SMDs can remain incorrect.scenarios tables no
longer inherit default characterizations through matching scenario
names. Explicit copies of the default rules also count as custom input;
omitted or NULL scenarios retain the default descriptions.
Selection, scores and stored notes in existing saved plans are
unchanged.generate_weasel_dummy_data() now restores the caller’s
complete RNGkind() configuration when no
.Random.seed existed before the call. Previously a
non-default kind (for example sample.kind = "Rounding") was
replaced by the generator’s pinned Mersenne-Twister/Inversion/Rejection
configuration on both successful and failed calls, while the absent seed
was correctly left absent. Every setting RNGkind() reports
is restored, including settings added by later R versions such as
R-devel’s binom.kind. Seeded output, seed reporting and
behaviour with an existing .Random.seed are unchanged. The
help page now also records R’s own limitation that a pending Box-Muller
normal deviate is not carried by .Random.seed.block_duration_range endpoints in
generate_weasel_dummy_data() now produce the requested
fixed duration, clipped at the final scheduled wave. Previously a
shorter duration could be sampled. Long durations also clip without
integer overflow. Seeded output for ordinary ranges containing multiple
durations is unchanged.waves in
generate_weasel_dummy_data() now reject labels outside
-2147483647 to 2147483647 with a clear weasel_error before
integer conversion and random draws. This prevents coercion warnings and
silently shortened schedules. Valid schedule normalization, seeded
output and caller RNG state are preserved.size argument of
set_weasel_scope() now takes its minimum before integer
conversion. Larger nonminimum values no longer cause coercion warnings
or reject a valid minimum. An unrepresentable minimum fails with a clear
weasel_error; explicit min_present precedence
is preserved.weasel_sensitivity() now rejects tolerance values above
2147483647 with a parameter-naming weasel_error before
integer conversion. This prevents coercion warnings, generic errors and
incomplete sweeps from mixed vectors. Valid tolerances, deprecated-alias
precedence and separate scenario-table support for Inf and
large finite values are preserved.weasel_error before generation. Ordinary seeded output and
RNG behavior are unchanged.weasel_error before conversion. This prevents coercion
warnings, missing-value table output and invalid stored scope settings.
Existing parameter defaults, near-integer rounding, generator RNG
behavior and separate scenario-table tolerances are preserved.weasel_error before conversion. This prevents coercion
warnings and loss of out-of-range wave values, including outside the
selected window and when reusing saved plans. Missing values and
near-integer rounding retain their existing behavior; Inf
scenario tolerances remain supported.This patch release corrects generated explanations and duplicate warnings, shares participation preparation across the selection workflows, and improves cross-platform verification. Respondent selection and saved-plan compatibility are preserved, with no new runtime dependencies or public API changes.
weasel_plan() now detects duplicate respondent-wave
pairs after the same wave rounding used for participation. Accepted
near-integer values no longer hide duplicates, including those outside
the selected window. Selection, fingerprints, and returned data are
unchanged.weasel_justify_subset() output now reports the
recorded planning population and retention denominator, consistently
with the methods and extended styles. Saved plans work without attached
data; older plans without population metadata continue to omit this
description. Selection is unchanged.weasel_justify_subset() now preserves unlimited
(Inf) tolerances and describes each unlimited dimension
without integer-coercion warnings or dropped gap constraints. Finite
constraints still appear in mixed cases, and large finite limits no
longer overflow during text generation. Existing finite-limit wording,
missing-metadata fallbacks, and respondent selection are preserved.weasel_justify_subset() styles now describe
analysis-window selection from the recorded rule. Explicit bounds are
user-supplied without an inferred a-priori decision; full spans use the
full wave grid; core spans maximize distinct respondent-wave coverage
among equal-length contiguous grid windows, with the earliest window
chosen on ties. The descriptions no longer imply that window selection
establishes sample stability or methodological superiority. Respondent
selection is unchanged.A correctness release driven by an external adjustment report whose findings were independently reproduced before any change (and by a cross-examination of that report). Two defects could silently produce wrong analytical results; both are fixed with regression tests locked in before the fixes.
tools::md5sum(); the new tools import has base
priority, so the package remains dependency-free). All three reunion
paths (weasel_apply(),
weasel_summarize_subset(),
weasel_selectivity()) compare it and warn
(weasel_data_mismatch) on any change to the incidence
structure, with a message that distinguishes count changes from pure
assignment changes. Plans saved by earlier versions carry no digest and
keep their documented acceptance behavior; the guard continues to apply
only to explicitly re-supplied data.weasel_summarize_subset() no longer corrupts summaries
for factor ids with unused levels. Grouping previously went through
split() on the raw id column, so every unused factor level
became a phantom respondent with zero observed waves, deflating
mean_present, endpoint_rate, and
min_present and inflating the missingness distribution
while n_ids stayed correct. Grouping now runs through
match() against the scenario’s retained ids, making
summaries invariant to the id representation (character, factor, factor
with unused or reordered levels, integer); an internal denominator
assertion raises a classed error (weasel_error_internal) if
the grouped count ever disagrees with the plan.c("0", "1") previously became thresholds 1
and 2, silently loosening the selection rules; it now stays 0 and 1, and
uninterpretable values are rejected with an error naming the column and
the offending value.require_endpoints is strictly validated in both entry
points. Scenario tables accept logicals, the imported labels
"TRUE"/"FALSE"/"T"/"F",
and the exact numbers 0/1; anything else (for example 2,
previously coerced to TRUE by as.logical()) is
rejected. weasel_sensitivity() accepts actual logical
values only.generate_weasel_dummy_data() validates all five
probability parameters (single numbers in [0, 1]),
attention_scale (finite, > 0),
attention_center (finite), and seed
(integer-valued) before any random draw. Previously
prop_random = -1 was accepted silently,
prop_item_missing = 2 made every outcome NA,
and prop_attrition = 2 failed later inside base R’s sampler
with an unrelated message.weasel_compare_scenarios() enforces the documented
scalar contract for tie_tolerance: vectors (previously
reduced to their first element) and character values (previously
converted silently) are rejected.core_len values outside the feasible window range
(below 2, or above the number of grid waves) were already clamped into
range, but silently; the clamp is now reported in a verbose-mode
message, in line with the package’s rule that no automatic decision is
silent. The clamped result itself is unchanged.max_gap_max as a required column while the
adjacent code correctly used max_gap_len; corrected.extended style “adds sensitivity framing”, which the
generated text does not contain; it now says the style adds a fuller
design rationale, and the section demonstrates the zero-argument
automatic citation alongside the existing
author/year override.weasel_compare_scenarios() documents that zero and
negative weights are accepted deliberately (a zero weight removes a
term, a negative weight inverts its direction).v3/, update_github_repo.sh,
publish-weasel.sh) removed from .Rbuildignore
and .gitignore.common$pattern[1]) with an
explicit empty-table guard, instead of
weasel_get_data_by_row(1) after filtering, and its table
title says ids >= 5 (the filter is on respondents per
pattern, not on observed waves n). The recipe notes teach
the row-position versus stable-id distinction.tools/check-guide-semantics.R, wired into the
guide-snippets workflow): the pattern the bounded recipe displays must
equal the pattern it extracts, and the title must label the filtered
column correctly. Snippet execution alone cannot detect that class of
drift.release-coherence workflow (on release publication
and manual dispatch, deliberately not on push): the released tag must
have a NEWS section, the current-version surfaces must agree, and the
latest-release endpoint may never be ahead of DESCRIPTION..Rbuildignore excludes the new tools/
directory from the package build.A consolidation release: corrections, honesty on imperfect input, one constraint vocabulary, and transparency for every automatic decision. No new modelling features. Results on clean panels with default arguments are unchanged except where noted below; every behavioural change is guarded by the expanded test suite (240 to 480 assertions).
min_present, max_missing,
n_gap_max, max_gap_len,
require_endpoints. In set_weasel_scope(),
size (its minimum), gap, and
n_gap are deprecated aliases of min_present,
max_gap_len, and n_gap_max; scenario tables
use max_gap_len in place of max_gap_max, and
weasel_sensitivity() renames its argument and output column
accordingly. All old names keep working through the 0.x series with
classed warnings (weasel_deprecated); an explicit new-name
argument always wins over its alias, and plans saved by older versions
remain readable.min_present = 1: exploration shows every respondent with at
least one observed wave instead of silently dropping those with fewer
than three. Set min_present = 3 to reproduce the old
default."strict" for
anchored_strict) no longer match.gap/max_gap_len,
n_gap/n_gap_max, min_present,
lower, upper, core_len,
sensitivity tolerances, scenario columns with Inf still
meaning “no constraint”, digits/n in
weasel_print_table(), generator counts and
waves). Fractional values are rejected instead of silently
truncated (previously gap = 1.9 acted as 1) or
rounded (previously lower = 2.6 acted as
3).id and wave must name different columns;
rows dropped from participation analysis (missing id, missing wave,
outside the span) are counted in a verbose-mode message in both
pipelines.weasel_justify_subset() refuses scenarios that retain
no respondents, and weasel_compare_to_sentence() states
plainly when no scenario is recommendable instead of naming one (both
classed; weasel_error_empty_scenario where
applicable).$span absent,
$ partial matching picked up span_reason, its
"full"/"core" label coerced to
NA, and weasel_apply(),
weasel_summarize_subset(), and
weasel_selectivity() silently returned zero rows. Exact
[["span"]] indexing fixes it, with an end-to-end regression
test.weasel_selectivity() was row-order dependent under
duplicated (id, wave) rows with at = "first" and
double-counted duplicated rows with at = "mean". Covariate
values are now averaged within each duplicated pair, a classed warning
(weasel_duplicates) is emitted, and the diagnostic is
order-invariant.weasel_apply() and
weasel_summarize_subset() warn when the returned data still
contain duplicated (id, wave) rows and document the contract: selection
metrics count each pair once, output rows are returned as-is.lower/upper bounds on
weasel_plan(): the window is recorded as an a-priori
decision (span_reason = "explicit") and the justification
text reports it as such instead of crediting an automatic rule.plan$span_candidates, the objective
(total deduplicated respondent-wave coverage, earliest window on ties)
is documented, and exact coverage ties raise a classed warning
(weasel_tied_windows).weasel_compare_scenarios()
gains tie_tolerance and a near_tie column; the
active weights and the per-scenario score decomposition are attached as
attributes ("weights", "score_components");
documentation and generated sentences state that the score is a
comparison-relative heuristic (“highest composite score under the
declared weights”).observed_in_span) is printed, documented, and stated in
the generated justification text.weasel_apply(), weasel_summarize_subset(), and
weasel_selectivity() check explicitly supplied data against
it and warn on mismatch (weasel_data_mismatch), guarding
saved plans against silent reunion with the wrong data.pattern id
column that survives filtering; weasel_get_data_by_row()
accepts pattern ids or pattern strings, so extraction after filtering
can no longer target the wrong pattern.max_missing and
require_endpoints constraints, mirroring plan scenarios
exactly (locked by cross-pipeline equivalence tests).n description, the
weasel_example() return listing, and the footer
installation command (GitHub, not CRAN). All snippets start with
library(weasel) and run as pasted. The plan recipes include
both diagnostics; result notes cover recommendation semantics, candidate
windows, explicit bounds, keep_data and the fingerprint
guard, the planning population, and grid = "observed". The
homepage gains a key-definitions glossary and a “Decisions the package
does not make” section.inst/CITATION so
citation("weasel") matches CITATION.cff with
the version read from DESCRIPTION at build time.guide-snippets workflow executes every guide code
example against the installed package on each push; the
version-coherence workflow additionally checks
CITATION.cff; .Rbuildignore and
.gitignore exclude local development artifacts
(v3/, update_github_repo.sh), so local builds
match CI builds.Coherence and reproducibility release. No behavioural changes for correct inputs other than the RNG pinning noted below.
generate_weasel_dummy_data() now pins the RNG
configuration
(RNGkind("Mersenne-Twister", "Inversion", sample.kind = "Rejection"),
the R >= 3.6 defaults) inside its seed-preserving block, so a given
seed reproduces the same panel regardless of the caller’s
RNGkind() setting. The caller’s RNG state, including a
non-default kind, is restored on exit. Previously a caller using
sample.kind = "Rounding" obtained different data from the
same seed. A regression test asserts both the invariance and the
restoration.NEWS.md is now tracked in the repository. It was
previously listed in .gitignore, so no changelog was under
version control and the v0.3.0 release carried no notes.version-coherence GitHub Actions workflow: the
version displayed by the documentation site
(docs/index.html) and the top NEWS.md heading
must both match Version in DESCRIPTION, so the
published site can no longer drift silently behind the released
version.2942bc5, previously unreleased).This release predates the tracked NEWS.md; the entries
below were compiled retrospectively from the release history.
grid argument on weasel_plan() and
set_weasel_scope(): grid = "observed"
evaluates presence over the observed wave schedule, fixing a critical
bug where non-consecutive schedules (for example biennial panels)
silently returned zero respondents.weasel_ prefix
(weasel_reshape_to_wide(),
weasel_summarize_waves(),
weasel_filter_wave_summary(),
weasel_get_data_by_row(), weasel_logo()). The
old names remain as deprecated forwarding aliases that emit a classed
warning (weasel_deprecated).weasel_plan S3 class with a
compact print() method, plus a keep_data
argument so the full data set need not be attached to the plan
object.weasel_sensitivity() (tolerance
sweeps), weasel_selectivity() (retained-versus-excluded
covariate comparison via standardized mean differences), and
weasel_scope_info() (active scope state).weasel_plan() runtime dropped from about 10 s to about 0.9
s. Deduplication is order-based instead of paste-based.NA values in the weights of
weasel_compare_scenarios() raise an error instead of
propagating NA scores; weasel_print_table()
validates digits and n (rejecting
NA and negative values) with a clean package error;
duplicated (id, wave) rows warn once with a classed warning and are
counted once.LICENSE.md.