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), andseed(integer-valued) before any random draw. Previouslyprop_random = -1was accepted silently,prop_item_missing = 2made every outcomeNA, andprop_attrition = 2failed 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.