v0.4.4 — Quality release (DW-Production v0.4.3.1 fanout findings)
v0.4.4 (2026-05-29)
Quality release. Three v0.4.4 milestone issues land in one cycle (PRs
#39,
#41,
#43). All three
surfaced empirically during the DW-Production v0.4.3.1 fanout audit
(IM / WS / HVA install + reviewer-mode runs on 2026-05-28). No public
API breaks; the bumped-default behaviour stays backwards-compatible
for v0.4.3.1 consumers.
Follow-up issue #42
tracks the remaining un-prefixed exports for a single naming-cleanup
PR (proposed v0.4.5).
Three carry-forward bugs + dw_-prefix aliases (issue #36)
Closes two of the three sub-fixes flagged on #36 during the HVA
scaffold-install Copilot review on 2026-05-28. The third (a value-arg
propagation bug in dw_regions.R) is moot — dw_regions is being
redesigned to consume the new unicef-drp/Country-and-Region-Metadata-API
package in #40 (v0.5.0); the affected code path is removed.
Sub-fix 1: aggregate_data_v2.R is now safe to source standalone
Pre-fix, aggregate_data_v2.R called .cso_require() from zzz.R.
Sourcing aggregate_data_v2.R directly (without sourcing zzz.R
first) left .cso_require undefined; the first call to
aggregate_data_v2(...) errored with could not find function .cso_require.
The file now defines a local fallback for .cso_require() at source
time, gated by exists(".cso_require", mode = "function", inherits = TRUE).
When zzz.R has already been sourced into .GlobalEnv, the shared
helper wins and nothing is redefined; when only aggregate_data_v2.R
is sourced, the local fallback provides the same behaviour.
Sub-fix 2: create_sector_script() profile sentinel check relaxed (and aligned with create_profile())
Pre-fix, the generated 00_run_<sector>.R template checked
isTRUE(profile_DW_Production). The DW-Production profile
(profile_DW-Production.R) does not set profile_DW_Production, so
the generated script errored at the sentinel check even after the
profile was sourced successfully.
The check is now relaxed from isTRUE(<name>) to !is.null(<name>),
which accepts any non-null value — character paths, numeric values,
or the boolean sentinel that create_profile("DW-Production") emits
(profile_DW_Production <- TRUE). The default profile_name stays at
"profile_DW_Production" so the documented scaffold flow
(create_profile() → create_dw_sector_script()) works out of the
box without additional configuration.
The new error message names the missing variable so future
profile-vs-template mismatches surface a concrete fix. The roxygen
@param doc also clarifies that the generated template uses
projectFolder directly for input/output paths, so the profile MUST
set projectFolder for the runner to do useful work — the sentinel
check only confirms the profile was sourced.
For DW-Production consumers (whose existing profile_DW-Production.R
doesn't set the sentinel), the one-line profile_DW_Production <- TRUE
must be added to the profile. Tracked as a separate DW-Production-side
follow-up PR.
dw_-prefixed canonical aliases for the two touched exports
Toolkit-export naming consolidates around the dw_ prefix in v0.4.x;
the non-prefixed names predate that convention. While in this PR's
files anyway, added:
dw_aggregate_data_v2(alias foraggregate_data_v2)dw_create_sector_script(alias forcreate_sector_script)
Both names point to the same function and share the same \\code{\\link{}} man page (via roxygen @rdname). The non-prefixed names continue to work — no breaking change. Follow-up issue tracks the rest of the un-prefixed exports (aggregate_data, generate_markdown_report, apply_time_window, generate_agg_footnote, create_profile, review_profile, test_scripts, create_dw_sector_script) as a single cleanup PR.
dw_default_unicef_allowlist() helper for consumers (issue #37)
New exported helper returns a character vector of ^...-anchored
regex patterns covering UNICEF DRP GitHub-raw and repository URLs.
Consumers seed dw_url_allowlist from this constant instead of
re-deriving the patterns per project:
# In profile_<consumer>.R
dw_url_allowlist <- c(
dw_default_unicef_allowlist(),
# Project-specific extras:
"^https://yourorg\\.github\\.io/"
)Surfaced empirically by the DW-Production reviewer-mode audit on
2026-05-28 (IM 01_immunization.R): every URL-using sector script
hand-wrote the same ^https://raw\\.githubusercontent\\.com/unicef-drp/
pattern. The helper consolidates the duplication and lets future
UNICEF-DRP additions land in one place upstream rather than in each
consumer's profile.
Purely additive — consumers must opt in by composing the helper into
their dw_url_allowlist. The URL-freeze safety contract is unchanged
(no URL is fetchable without explicit ratification).
.dw_frozen_root() resolution is now discoverable (issue #38)
.dw_frozen_root() falls through a 3-tier resolution chain when
locating the URL-freeze cache root:
dw_frozen_rootglobal (opt-in; preferred)<githubFolder>/_frozen(fallback)<getwd()>/_frozen(last-resort fallback)
Pre-v0.4.4 the helper resolved silently — consumers whose project
layout didn't match the fallback heuristic had to grep dw_io.R to
discover why dw_use("https://...") couldn't find their frozen file.
v0.4.4 adds two discoverability improvements:
- A new internal helper
.dw_frozen_root_resolved()returns a
(path, source)pair so downstream callers can surface the chosen
tier in messages and error envelopes. .dw_frozen_root_notify_once()emits a session-scoped notice the
first time the helper falls back beyond tier #1:
message()for tier #2 (<githubFolder>/_frozen),
warning()for tier #3 (<getwd()>/_frozen).
Consumers that explicitly setdw_frozen_rootget no notice.
The missing-frozen-copy error envelope in .resolve_remote_url()
now includes the resolution tier so consumers see which fallback
fired (or that the explicit global picked the path that's wrong):
[cso_toolkit.dw_use:remote] Reviewer mode forbids fetching from the network.
Missing frozen copy: <path>
URL: <url>
Frozen-root resolution: <chosen-root> (<tier-name>)
Fix:
1. If the path above is wrong, set `dw_frozen_root <- '<your-canonical-frozen-path>'` in your profile.
2. Otherwise, a producer must call dw_use(...) once and commit the frozen file + sidecar.
Surfaced empirically by the DW-Production IM reviewer-mode audit on
2026-05-28: the fallback resolved to <githubFolder>/_frozen instead
of DW-Production's convention of <projectFolder>/01_dw_prep/011_rawdata/_frozen/.
Three runs (75+ min of slow Teams network) were needed to diagnose
what a single message could have surfaced at session start.
No public-API changes. The internal .dw_frozen_root() (path-only)
is preserved for backward compatibility with v0.4.3.1 callers.