Skip to content

stbl 0.3.0

Choose a tag to compare

@jonthegeek jonthegeek released this 04 Apr 14:51

Breaking changes

  • to_chr_scalar(), to_dbl_scalar(), to_fct_scalar(), to_int_scalar(), to_lgl_scalar(), stabilize_chr_scalar(), stabilize_dbl_scalar(), stabilize_fct_scalar(), stabilize_int_scalar(), stabilize_lgl_scalar(), specify_chr_scalar(), specify_dbl_scalar(), specify_fct_scalar(), specify_int_scalar(), and specify_lgl_scalar() (and their synonyms) now default to allow_null = FALSE and allow_zero_length = FALSE. Pass allow_null = TRUE or allow_zero_length = TRUE to restore the previous behavior (#189, #197).

Potential breaking changes

  • Several conditions that formerly included a subclass of "stbl-error-must" no longer include that subclass. This only occurs when "stbl-error-must" was not the most specific subclass (i.e., when a more specific subclass was already included), and therefore should not impact most if any code (#136).

New features

  • New long-form and British-spelling synonym functions for all class functions. For example, to_character() is a synonym for to_chr(), specify_logical() for specify_lgl(), and stabilise_*() for all stabilize_*() functions (#164, #167).
  • New expect_pkg_error_classes() checks that an error with the expected set of classes is thrown by pkg_abort(), and expect_pkg_error_snapshot() snapshot-tests the full error output in one step by combining expect_snapshot() with expect_pkg_error_classes() (#136, #188). New pkg_abort() throws errors with a standardized, opinionated collection of classes (#136).
  • New specification functions: specify_*() creates a "stbl_specified_fn", a call to the corresponding stabilize_*() function with arguments pre-filled. For example, stabilize_email <- specify_chr(regex = "^[^@]+@[^@]+\\.[^@]+$") creates a stabilize_email() function that validates email addresses (#147, #148, #149, #150, #151, #153, #161).
  • New stabilize_df() and specify_df() validate data frame structure and contents (#142).
  • New stabilize_lst() and specify_lst() validate list structure and contents and create pre-configured validators for nested validation (#110, #204).
  • New stabilize_present() validates that a value is non-NULL without imposing any type constraints (#110).
  • New to_df() (and synonym to_data_frame()) coerces compatible objects to a data frame, including named lists and named atomic vectors (e.g., to_df(letters)), with informative errors for incompatible inputs such as jagged lists (#142, #201, #203).
  • New to_lst() (and synonym to_list()) coerces an object to a list, with conditional checks for NULL and functions (#157, #166).

Other changes

  • Revised the "Getting started with stbl" vignette to clarify what happens at each step (#139, #143, #144).
  • Clarified error messages (#176, #177).

{qcthat} Reports

Milestone

✅ A qcthat issue test matrix with 1 milestone, 20 issues, and 182 tests
└─█─Milestone: v0.3.0 (20 issues, 182 tests)
  ├─☑️─Bug 204: bug: `stabilize_lst()` with nested list
  │ ├─✅─specify_df() accepts columns named 'x_arg', 'call', 'x_class' (#204)
  │ ├─✅─specify_lst() accepts elements named 'x_arg', 'call', 'x_class' (#204)
  │ └─✅─stabilize_lst() with nested specify_lst() propagates errors correctly (#204)
  ├─☑️─Feature 161: Show actual args in `specify_*()`
  │ ├─✅─specify_cls builds the expected function with at least one arg (#150, #161)
  │ ├─✅─specify_cls builds the expected function snapshot with at least one arg (#150, #161)
  │ └─✅─The function built via specify_cls errors informatively for duplicated args (#150, #153, #161)
  ├─☑️─Feature 157: Implement `to_list()`
  │ ├─✅─to_lst() works for lists (#157, #166)
  │ ├─✅─to_lst() works for NULL (#157)
  │ ├─✅─to_lst() respects allow_null (#157)
  │ ├─✅─to_lst() works for character vectors (#157)
  │ ├─✅─to_lst() errors by default for functions (#157)
  │ ├─✅─to_lst() works for functions with coerce_function = TRUE (#157)
  │ ├─✅─to_lst() errors informatively for primitives (#157)
  │ └─✅─to_list() exists (#157, #166)
  ├─☑️─Feature 153: Better handling of `...` in `specify_*()`
  │ └─✅─The function built via specify_cls errors informatively for duplicated args (#150, #153, #161)
  ├─☑️─Feature 151: Implement `specify_lgl()`
  │ ├─✅─specify_lgl can build a checker (#151)
  │ └─✅─specify_lgl_scalar can build a value checker (#151)
  ├─☑️─Feature 150: Implement `specify_fct()`
  │ ├─✅─specify_cls builds the expected function with no args (#150)
  │ ├─✅─specify_cls builds the expected function snapshot with no args (#150)
  │ ├─✅─specify_cls builds the expected function with at least one arg (#150, #161)
  │ ├─✅─specify_cls builds the expected function snapshot with at least one arg (#150, #161)
  │ ├─✅─The function built via specify_cls errors informatively for duplicated args (#150, #153, #161)
  │ ├─✅─specify_cls can build a scalar specifier (#150)
  │ ├─✅─specify_cls builds the expected scalar function snapshot (#150)
  │ ├─✅─specify_fct can build a level checker (#150)
  │ └─✅─specify_fct_scalar can build a level checker (#150)
  ├─☑️─Feature 149: Implement `specify_int()`
  │ ├─✅─specify_int can build a value checker (#149)
  │ └─✅─specify_int_scalar can build a value checker (#149)
  ├─☑️─Feature 148: Implement `specify_dbl()`
  │ ├─✅─specify_dbl can build a value checker (#148)
  │ └─✅─specify_dbl_scalar can build a value checker (#148)
  ├─☑️─Feature 147: Implement `specify_chr()`
  │ ├─✅─specify_chr can build a regex checker (#147)
  │ └─✅─specify_chr_scalar can build a regex checker (#147)
  ├─☑️─Feature 142: Implement `stabilize_df()`
  │ ├─✅─specify_df() creates a working validator (#142)
  │ ├─✅─specify_df() errors when required column is missing (#142)
  │ ├─✅─specify_df() passes through .min_rows, .max_rows (#142)
  │ ├─✅─specify_df() passes through .col_names (#142)
  │ ├─✅─specify_df() allows additional specs via ... (#142)
  │ ├─✅─specify_data_frame() exists (#142)
  │ ├─✅─stabilize_df() returns NULL for NULL input by default (#142)
  │ ├─✅─stabilize_df() respects .allow_null (#142)
  │ ├─✅─stabilize_df() errors for non-coercible input (#142)
  │ ├─✅─stabilize_df() coerces a named list to a data frame (#142)
  │ ├─✅─stabilize_df() returns a valid data frame unchanged (#142)
  │ ├─✅─stabilize_df() coerces compatible column types (#142)
  │ ├─✅─stabilize_df() errors when required column is missing (#142)
  │ ├─✅─stabilize_df() errors informatively when column fails validation (#142)
  │ ├─✅─stabilize_df() errors on extra columns by default (#142)
  │ ├─✅─stabilize_df() allows extra columns with .extra_cols (#142)
  │ ├─✅─stabilize_df() validates extra columns with .extra_cols (#142)
  │ ├─✅─stabilize_df() enforces .min_rows (#142)
  │ ├─✅─stabilize_df() enforces .min_rows (snapshot) (#142)
  │ ├─✅─stabilize_df() enforces .max_rows (#142)
  │ ├─✅─stabilize_df() enforces .max_rows (snapshot) (#142)
  │ ├─✅─stabilize_df() passes with valid row counts (#142)
  │ ├─✅─stabilize_df() enforces .col_names (#142)
  │ ├─✅─stabilize_df() enforces .col_names (snapshot) (#142)
  │ ├─✅─stabilize_df() allows .col_names alongside ... specs (#142)
  │ ├─✅─stabilize_df() preserves data frame class after column coercion (#142)
  │ ├─✅─stabilize_df() works with no column specs and .extra_cols (#142)
  │ ├─✅─stabilize_df() with unnamed specs errors informatively (#142)
  │ ├─✅─stabilise_df() exists (#142)
  │ ├─✅─stabilize_data_frame() exists (#142)
  │ └─✅─stabilise_data_frame() exists (#142)
  ├─☑️─Feature 136: Export error functions
  │ ├─✅─.compile_pkg_condition_classes() compiles condition class chains (#136)
  │ ├─✅─.compile_pkg_error_classes() compiles error class chains (#136)
  │ ├─✅─pkg_abort() throws the expected error (#136)
  │ ├─✅─pkg_abort() uses parent when provided (#136)
  │ ├─✅─pkg_abort() passes dots to cli_abort() (#136)
  │ ├─✅─pkg_abort() uses message_env when provided (#136)
  │ └─✅─expect_pkg_error_classes() tests expressions for classes (#136)
  ├─☑️─Feature 203: feat: better `to_df()`
  │ ├─✅─.check_all_named() works (#203)
  │ ├─✅─.check_not_jagged() works (#203)
  │ ├─✅─to_df() errors for an unnamed list (#203)
  │ ├─✅─to_df() coerces named vector types to a data frame (#203)
  │ └─✅─to_df() errors for inline vector expressions (#203)
  ├─☑️─Feature 110: Implement `stabilize_lst()`
  │ ├─✅─specify_lst() creates a working specifier (#110)
  │ ├─✅─specify_lst() respects pre-configured element specs (#110)
  │ ├─✅─specify_lst() supports element specs named 'x' and 'y' (#110)
  │ ├─✅─specify_lst() passes through additional element specs from ... (#110)
  │ ├─✅─specify_lst() respects .min_size (#110)
  │ ├─✅─specify_lst() respects .allow_null (#110)
  │ ├─✅─specify_list() exists (#110)
  │ ├─✅─stabilize_lst() returns NULL for NULL input by default (#110)
  │ ├─✅─stabilize_lst() respects .allow_null (#110)
  │ ├─✅─stabilize_lst() returns a valid list unchanged (#110)
  │ ├─✅─stabilize_lst() validates required named elements (#110)
  │ ├─✅─stabilize_lst() errors when required named element is missing (#110)
  │ ├─✅─stabilize_lst() errors informatively when element fails validation (#110)
  │ ├─✅─stabilize_lst() errors on extra named elements by default (#110)
  │ ├─✅─stabilize_lst() validates extra named elements with .named (#110)
  │ ├─✅─stabilize_lst() errors on unnamed elements by default (#110)
  │ ├─✅─stabilize_lst() validates unnamed elements with .unnamed (#110)
  │ ├─✅─stabilize_lst() handles mixed named/unnamed lists (#110)
  │ ├─✅─stabilize_lst() enforces .min_size (#110)
  │ ├─✅─stabilize_lst() enforces .max_size (#110)
  │ ├─✅─stabilize_lst() validates nested lists (#110)
  │ ├─✅─stabilize_lst() with unnamed specs errors informatively (#110)
  │ ├─✅─.check_duplicate_names(): errors on duplicate names by default (#110)
  │ ├─✅─.check_duplicate_names(): allows duplicates with .allow_duplicate_names = TRUE (#110)
  │ ├─✅─.check_duplicate_names(): reports all duplicate name groups (#110)
  │ ├─✅─.check_duplicate_names(): unnamed elements do not count as duplicates (#110)
  │ ├─✅─stabilize_list() exists (#110)
  │ ├─✅─stabilise_lst() exists (#110)
  │ ├─✅─stabilise_list() exists (#110)
  │ ├─✅─stabilize_present() returns any non-NULL value unchanged (#110)
  │ ├─✅─stabilize_present() errors for NULL (#110)
  │ └─✅─stabilize_present() works as an element spec in stabilize_lst() (#110)
  ├─☑️─Feature 201: feat: `to_df()`
  │ ├─✅─to_df() returns a data frame unchanged (#201)
  │ ├─✅─to_df() returns NULL for NULL input by default (#201)
  │ ├─✅─to_df() respects allow_null (#201)
  │ ├─✅─to_df() coerces a named list to a data frame (#201)
  │ ├─✅─to_df() coerces a list of equal-length vectors to a data frame (#201)
  │ ├─✅─to_df() errors for a list with incompatible column lengths (#201)
  │ ├─✅─to_df() errors for non-coercible types (#201)
  │ ├─✅─to_df.default() errors for non-coercible types (#201)
  │ └─✅─to_data_frame() exists (#201)
  ├─☑️─Bug 197: Update `specify_*_scalar()` defaults to match `stabilize_*_scalar()`
  │ ├─✅─specify_chr_scalar defaults to allow_null = FALSE (#197)
  │ ├─✅─specify_chr_scalar defaults to allow_zero_length = FALSE (#197)
  │ ├─✅─specify_dbl_scalar defaults to allow_null = FALSE (#197)
  │ ├─✅─specify_dbl_scalar defaults to allow_zero_length = FALSE (#197)
  │ ├─✅─specify_fct_scalar defaults to allow_null = FALSE (#197)
  │ ├─✅─specify_fct_scalar defaults to allow_zero_length = FALSE (#197)
  │ ├─✅─specify_int_scalar defaults to allow_null = FALSE (#197)
  │ ├─✅─specify_int_scalar defaults to allow_zero_length = FALSE (#197)
  │ ├─✅─specify_lgl_scalar defaults to allow_null = FALSE (#197)
  │ └─✅─specify_lgl_scalar defaults to allow_zero_length = FALSE (#197)
  ├─☑️─Feature 177: Don't mention levels/to_na in factor message?
  │ └─✅─to_fct() throws errors for bad levels (#62, #67, #177)
  ├─☑️─Feature 176: Better error messages
  │ ├─✅─stabilize_dbl() checks min_value (#23, #176)
  │ ├─✅─stabilize_dbl() checks max_value (#23, #176)
  │ ├─✅─stabilize_int() checks min_value (#2, #6, #176)
  │ └─✅─stabilize_int() checks max_value (#5, #176)
  ├─☑️─Feature 167: Add stabilise_*() aliases
  │ ├─✅─stabilise_chr() exists (#167)
  │ ├─✅─stabilise_character() exists (#167)
  │ ├─✅─stabilise_chr_scalar() exists (#167)
  │ ├─✅─stabilise_character_scalar() exists (#167)
  │ ├─✅─stabilise_dbl() exists (#167)
  │ ├─✅─stabilise_double() exists (#167)
  │ ├─✅─stabilise_dbl_scalar() exists (#167)
  │ ├─✅─stabilise_double_scalar() exists (#167)
  │ ├─✅─stabilise_fct() exists (#167)
  │ ├─✅─stabilise_factor() exists (#167)
  │ ├─✅─stabilise_fct_scalar() exists (#167)
  │ ├─✅─stabilise_factor_scalar() exists (#167)
  │ ├─✅─stabilise_int() exists (#167)
  │ ├─✅─stabilise_integer() exists (#167)
  │ ├─✅─stabilise_int_scalar() exists (#167)
  │ ├─✅─stabilise_integer_scalar() exists (#167)
  │ ├─✅─stabilise_lgl() exists (#167)
  │ ├─✅─stabilise_logical() exists (#167)
  │ ├─✅─stabilise_lgl_scalar() exists (#167)
  │ └─✅─stabilise_logical_scalar() exists (#167)
  ├─☑️─Task 166: Make to_lst() the primary spelling
  │ ├─✅─to_lst() works for lists (#157, #166)
  │ └─✅─to_list() exists (#157, #166)
  └─☑️─Feature 164: Add spelled-out aliases for all functions
    ├─✅─are_character_ish() exists (#164)
    ├─✅─is_character_ish() exists (#164)
    ├─✅─are_double_ish() exists (#164)
    ├─✅─is_double_ish() exists (#164)
    ├─✅─are_factor_ish() exists (#164)
    ├─✅─is_factor_ish() exists (#164)
    ├─✅─are_integer_ish() exists (#164)
    ├─✅─is_integer_ish() exists (#164)
    ├─✅─are_logical_ish() exists (#164)
    ├─✅─is_logical_ish() exists (#164)
    ├─✅─specify_character() exists (#164)
    ├─✅─stabilize_character_scalar() exists (#164)
    ├─✅─specify_double() exists (#164)
    ├─✅─stabilize_double_scalar() exists (#164)
    ├─✅─specify_factor() exists (#164)
    ├─✅─stabilize_factor_scalar() exists (#164)
    ├─✅─specify_integer() exists (#164)
    ├─✅─stabilize_integer_scalar() exists (#164)
    ├─✅─specify_logical() exists (#164)
    ├─✅─stabilize_logical_scalar() exists (#164)
    ├─✅─stabilize_character() exists (#164)
    ├─✅─stabilize_character_scalar() exists (#164)
    ├─✅─stabilize_double() exists (#164)
    ├─✅─stabilize_double_scalar() exists (#164)
    ├─✅─stabilize_factor() exists (#164)
    ├─✅─stabilize_factor_scalar() exists (#164)
    ├─✅─stabilize_integer() exists (#164)
    ├─✅─stabilize_integer_scalar() exists (#164)
    ├─✅─stabilize_logical() exists (#164)
    ├─✅─stabilize_logical_scalar() exists (#164)
    ├─✅─to_character() exists (#164)
    ├─✅─to_character_scalar() exists (#164)
    ├─✅─to_double() exists (#164)
    ├─✅─to_double_scalar() exists (#164)
    ├─✅─to_factor() exists (#164)
    ├─✅─to_factor_scalar() exists (#164)
    ├─✅─to_integer() exists (#164)
    ├─✅─to_integer_scalar() exists (#164)
    ├─✅─to_logical() exists (#164)
    └─✅─to_logical_scalar() exists (#164)
# Issue state: 📥 = open, ☑️ = closed (completed), ⛔ = closed (won't fix)
# Test disposition: ✅ = passed, ❌ = failed, 🚫 = skipped
✅ All tests passed

🟢 All issues have at least one test

🙈 7 issues with label "qcthat-nocov" were ignored


Completed Issues

✅ A qcthat issue test matrix with 3 milestones, 52 issues, and 389 tests
├─█─Milestone: v0.1 (17 issues, 93 tests)
│ ├─☑️─Feature 64: Explicitly error to_fct for list and data.frame
│ │ └─✅─to_fct() works for lists (#64)
│ ├─☑️─Feature 21: to_lgl()
│ │ ├─✅─to_lgl() works for lgls (#21)
│ │ ├─✅─to_lgl() works for NULL (#21)
│ │ ├─✅─to_lgl() respects allow_null (#21)
│ │ ├─✅─to_lgl() works for integers (#21)
│ │ ├─✅─to_lgl() works for doubles (#21)
│ │ ├─✅─to_lgl works for characters (#21)
│ │ ├─✅─to_lgl() errors for bad characters (#21)
│ │ ├─✅─to_lgl works for factors (#21)
│ │ ├─✅─to_lgl errors for bad factors (#21)
│ │ ├─✅─to_lgl() works for lists (#21)
│ │ └─✅─to_lgl() errors for other types (#21)
│ ├─☑️─Feature 14: coerce argument(s)
│ │ ├─✅─to_int() respects coerce_character (#14)
│ │ └─✅─to_int() respects coerce_factor (#14)
│ ├─☑️─Feature 12: Scalar
│ │ ├─✅─stabilize_arg_scalar() allows length-1 args through (#12)
│ │ ├─✅─stabilize_arg_scalar() errors for non-scalars (#12, #58)
│ │ ├─✅─stabilize_arg_scalar() respects allow_null (#12, #58)
│ │ ├─✅─stabilize_arg_scalar() errors on weird internal arg values (#12, #58)
│ │ ├─✅─stabilize_int_scalar() allows length-1 ints through (#12, #189)
│ │ ├─✅─stabilize_int_scalar() respects allow_null (#12, #189)
│ │ ├─✅─stabilize_int_scalar() errors on non-scalars (#12)
│ │ ├─✅─to_int_scalar() allows length-1 ints through (#12)
│ │ ├─✅─to_int_scalar() provides informative error messages (#12)
│ │ ├─✅─to_int_scalar() respects allow_null (#12, #189)
│ │ └─✅─to_int_scalar respects allow_zero_length (#12, #43, #45, #189)
│ ├─☑️─Feature 11: Rename then export .return_if_clear()
│ │ ├─✅─stabilize_arg() returns its inputs for default settings (#11)
│ │ ├─✅─stabilize_arg() complains about weird args (#11, #58, #99)
│ │ ├─✅─stabilize_arg() rejects NULLs when asked (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks NAs (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks size args (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks min_size (#11, #58, #99)
│ │ └─✅─stabilize_arg() checks max_size (#11, #58)
│ ├─☑️─Feature 6: to_int_simple() (or something)
│ │ ├─✅─stabilize_int() checks min_value (#2, #6, #176)
│ │ └─✅─to_int() works for ints (#2, #6)
│ ├─☑️─Feature 5: Implement allow_empty
│ │ └─✅─stabilize_int() checks max_value (#5, #176)
│ ├─☑️─Feature 4: Factors to int
│ │ ├─✅─to_int() works for factors (#4)
│ │ └─✅─to_int() errors informatively for bad factors (#4)
│ ├─☑️─Feature 2: Implement to_int()
│ │ ├─✅─stabilize_int() checks min_value (#2, #6, #176)
│ │ ├─✅─to_int() works for ints (#2, #6)
│ │ ├─✅─to_int() works for NULL (#2)
│ │ ├─✅─to_int() respects allow_null (#2)
│ │ ├─✅─to_int() works for lgls (#2)
│ │ ├─✅─to_int() works for dbls (#2)
│ │ ├─✅─to_int() errors for dbls that would lose precision (#2)
│ │ ├─✅─to_int() works for chrs (#2)
│ │ ├─✅─to_int() errors informatively for bad chrs (#2)
│ │ ├─✅─to_int() works for complexes (#2)
│ │ ├─✅─to_int() errors informatively for bad complexes (#2)
│ │ ├─✅─to_int() works for lists (#2)
│ │ └─✅─to_int() errors properly for other types (#2)
│ ├─☑️─Feature 62: stabilize_fct
│ │ ├─✅─stabilize_fct() works (#62)
│ │ ├─✅─stabilize_fct() throws errors for bad levels (#62, #67)
│ │ ├─✅─stabilize_fct_scalar() works (#62, #189)
│ │ ├─✅─stabilize_fct_scalar() respects allow_null (#62, #189)
│ │ ├─✅─stabilize_fct_scalar() errors for non-scalars (#62)
│ │ ├─✅─to_fct() works for fcts (#62)
│ │ ├─✅─to_fct() deals with levels of fcts (#62)
│ │ ├─✅─to_fct() throws errors for bad levels (#62, #67, #177)
│ │ ├─✅─to_fct() works for chrs (#62)
│ │ ├─✅─to_fct() works for NULL (#62)
│ │ ├─✅─to_fct() respects allow_null (#62)
│ │ ├─✅─to_fct() errors for things that can't be coerced (#62)
│ │ ├─✅─to_fct() treats numbers as text (#62)
│ │ ├─✅─to_fct_scalar() allows length-1 fcts through (#62)
│ │ ├─✅─to_fct_scalar() provides informative error messages (#62)
│ │ └─✅─to_fct_scalar respects allow_zero_length (#62, #43, #45, #189)
│ ├─☑️─Task 58: Error classes
│ │ ├─✅─stabilize_arg() complains about weird args (#11, #58, #99)
│ │ ├─✅─stabilize_arg() rejects NULLs when asked (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks NAs (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks size args (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks min_size (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks max_size (#11, #58)
│ │ ├─✅─stabilize_arg_scalar() errors for non-scalars (#12, #58)
│ │ ├─✅─stabilize_arg_scalar() respects allow_null (#12, #58)
│ │ └─✅─stabilize_arg_scalar() errors on weird internal arg values (#12, #58)
│ ├─☑️─Feature 45: empty vs NULL
│ │ ├─✅─to_chr_scalar respects allow_zero_length (#22, #43, #45, #189)
│ │ ├─✅─to_dbl_scalar respects allow_zero_length (#23, #43, #45, #189)
│ │ ├─✅─to_fct_scalar respects allow_zero_length (#62, #43, #45, #189)
│ │ └─✅─to_int_scalar respects allow_zero_length (#12, #43, #45, #189)
│ ├─☑️─Feature 43: Empty input
│ │ ├─✅─to_chr_scalar respects allow_zero_length (#22, #43, #45, #189)
│ │ ├─✅─to_dbl_scalar respects allow_zero_length (#23, #43, #45, #189)
│ │ ├─✅─to_fct_scalar respects allow_zero_length (#62, #43, #45, #189)
│ │ └─✅─to_int_scalar respects allow_zero_length (#12, #43, #45, #189)
│ ├─☑️─Feature 32: to_lgl_scalar()
│ │ ├─✅─to_lgl_scalar() allows length-1 lgls through (#32, #189)
│ │ ├─✅─to_lgl_scalar() errors for non-scalars (#32)
│ │ ├─✅─to_lgl_scalar() errors for bad characters (#32)
│ │ └─✅─to_lgl_scalar() respects allow_null (#32, #189)
│ ├─☑️─Feature 28: stabilize_lgl()
│ │ ├─✅─stabilize_lgl() works on happy path (#28)
│ │ ├─✅─stabilize_lgl() checks NAs (#28)
│ │ ├─✅─stabilize_lgl() checks min_size (#28)
│ │ ├─✅─stabilize_lgl() checks max_size (#28)
│ │ ├─✅─stabilize_lgl_scalar() allows length-1 lgls through (#28, #189)
│ │ ├─✅─stabilize_lgl_scalar() respects allow_null (#28, #189)
│ │ └─✅─stabilize_lgl_scalar() errors on non-scalars (#28)
│ ├─☑️─Feature 27: regex arg
│ │ ├─✅─stabilize_chr() works on happy path (#22, #27, #52)
│ │ ├─✅─stabilize_chr() errors for bad regex matches (#27, #52)
│ │ └─✅─stabilize_chr works with NA and regex pattern (#27, #52)
│ └─☑️─Feature 22: *_chr*()
│   ├─✅─stabilize_chr() works on happy path (#22, #27, #52)
│   ├─✅─stabilize_chr_scalar() allows length-1 chrs through (#22, #189)
│   ├─✅─stabilize_chr_scalar() respects allow_null (#22, #189)
│   ├─✅─stabilize_chr_scalar() errors for non-scalars (#22)
│   ├─✅─to_chr() works for chrs (#22)
│   ├─✅─to_chr() works for NULL (#22)
│   ├─✅─to_chr() respects allow_null (#22)
│   ├─✅─to_chr() works for other things (#22)
│   ├─✅─to_chr() tries to flatten lists (#22)
│   ├─✅─to_chr() fails gracefully for weird cases (#22)
│   ├─✅─to_chr_scalar() allows length-1 chrs through (#22, #189)
│   ├─✅─to_chr_scalar() errors for non-scalars (#22)
│   ├─✅─to_chr_scalar() errors for uncoerceable types (#22)
│   ├─✅─to_chr_scalar() respects allow_null (#22, #189)
│   └─✅─to_chr_scalar respects allow_zero_length (#22, #43, #45, #189)
├─█─Milestone: v0.2 (13 issues, 126 tests)
│ ├─☑️─Task 129: Rename `to_null()` to `.to_null()`
│ │ ├─✅─.to_null() works on the happy path (#129)
│ │ ├─✅─.to_null() errors when NULL isn't allowed (#129)
│ │ ├─✅─.to_null() coerces anything to NULL (#129)
│ │ ├─✅─.to_null() errors for bad allow_null (#129)
│ │ └─✅─.to_null() errors informatively for missing value (#129)
│ ├─☑️─Feature 67: to_fct: Enumerate options
│ │ ├─✅─stabilize_fct() throws errors for bad levels (#62, #67)
│ │ └─✅─to_fct() throws errors for bad levels (#62, #67, #177)
│ ├─☑️─Feature 52: regex error is useless
│ │ ├─✅─regex_must_match() works as expected (#52, #89)
│ │ ├─✅─regex_must_match() deals with characters for glue (#52, #89)
│ │ ├─✅─stabilize_chr() works on happy path (#22, #27, #52)
│ │ ├─✅─stabilize_chr() errors for bad regex matches (#27, #52)
│ │ ├─✅─stabilize_chr() works with complex url regex (#52)
│ │ ├─✅─stabilize_chr() allows for customized error messages (#52)
│ │ ├─✅─stabilize_chr() works with regex that contains braces (#52)
│ │ ├─✅─stabilize_chr works with NA and regex pattern (#27, #52)
│ │ └─✅─stabilize_chr_scalar() works with regex that contains braces (#52)
│ ├─☑️─Feature 30: to_lgl.character(): "0" and "1"
│ │ ├─✅─are_lgl_ish() works for characters (#93, #30)
│ │ ├─✅─are_lgl_ish() works for factors (#93, #30)
│ │ └─✅─are_lgl_ish() works for lists (#93, #30)
│ ├─☑️─Feature 23: dbl
│ │ ├─✅─are_dbl_ish() works for dbls (#23)
│ │ ├─✅─are_dbl_ish() works for ints (#23)
│ │ ├─✅─are_dbl_ish() works for NULL (#23)
│ │ ├─✅─are_dbl_ish() works for logicals (#23)
│ │ ├─✅─are_dbl_ish() works for characters (#23)
│ │ ├─✅─are_dbl_ish() respects coerce_character (#23)
│ │ ├─✅─are_dbl_ish() works for factors (#23)
│ │ ├─✅─are_dbl_ish() respects coerce_factor (#23)
│ │ ├─✅─are_dbl_ish() works for complex (#23)
│ │ ├─✅─are_dbl_ish() works for lists (#23)
│ │ ├─✅─are_dbl_ish() returns FALSE for non-vectors (#23)
│ │ ├─✅─is_dbl_ish() works (#23)
│ │ ├─✅─.to_cls_from_fct() works (#23)
│ │ ├─✅─.to_num_from_complex() works (#23)
│ │ ├─✅─stabilize_dbl() checks min_value (#23, #176)
│ │ ├─✅─stabilize_dbl() checks max_value (#23, #176)
│ │ ├─✅─stabilize_dbl_scalar() allows length-1 dbls through (#23, #189)
│ │ ├─✅─stabilize_dbl_scalar() respects allow_null (#23, #189)
│ │ ├─✅─stabilize_dbl_scalar() errors on non-scalars (#23)
│ │ ├─✅─to_dbl() works for dbls (#23)
│ │ ├─✅─to_dbl() works for ints (#23)
│ │ ├─✅─to_dbl() works for NULL (#23)
│ │ ├─✅─to_dbl() respects allow_null (#23)
│ │ ├─✅─to_dbl() works for lgls (#23)
│ │ ├─✅─to_dbl() works for chrs (#23)
│ │ ├─✅─to_dbl() respects coerce_character (#23)
│ │ ├─✅─to_dbl() errors informatively for bad chrs (#23)
│ │ ├─✅─to_dbl() works for complexes (#23)
│ │ ├─✅─to_dbl() errors informatively for bad complexes (#23)
│ │ ├─✅─to_dbl() works for factors (#23)
│ │ ├─✅─to_dbl() respects coerce_factor (#23)
│ │ ├─✅─to_dbl() errors informatively for bad factors (#23)
│ │ ├─✅─to_dbl() errors properly for other types (#23)
│ │ ├─✅─to_dbl_scalar() allows length-1 dbls through (#23)
│ │ ├─✅─to_dbl_scalar() provides informative error messages (#23)
│ │ ├─✅─to_dbl_scalar() respects allow_null (#23, #189)
│ │ └─✅─to_dbl_scalar respects allow_zero_length (#23, #43, #45, #189)
│ ├─☑️─Bug 128: Ensure `are_*_ish()` and `to_*()` are consistent
│ │ ├─✅─are_chr_ish() works for lists and data.frames (#93, #128)
│ │ ├─✅─are_int_ish() works for lists (#93, #128)
│ │ ├─✅─.to_cls_from_list() works (#128)
│ │ ├─✅─.to_cls_from_list() works for single-element lists (#128)
│ │ └─✅─to_dbl() works for lists (#128)
│ ├─☑️─Task 99: Standardize error class checks in all test files
│ │ ├─✅─stabilize_arg() complains about weird args (#11, #58, #99)
│ │ ├─✅─stabilize_arg() rejects NULLs when asked (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks NAs (#11, #58, #99)
│ │ ├─✅─stabilize_arg() checks size args (#11, #58, #99)
│ │ └─✅─stabilize_arg() checks min_size (#11, #58, #99)
│ ├─☑️─Task 95: Standardize Error Messages
│ │ ├─✅─.stbl_abort() throws the expected error (#95)
│ │ ├─✅─.stop_cant_coerce() throws the expected error (#95)
│ │ ├─✅─.stop_cant_coerce() uses additional_msg when provided (#95)
│ │ ├─✅─.stop_must() throws the expected error (#95)
│ │ ├─✅─.stop_must() handles subclasses (#95)
│ │ ├─✅─.stop_must() uses additional_msg when provided (#95)
│ │ ├─✅─.define_main_msg() works (#95)
│ │ ├─✅─.stop_null() throws the expected error (#95)
│ │ ├─✅─.stop_null() passes dots (#95)
│ │ ├─✅─.stop_incompatible() throws the expected error (#95)
│ │ ├─✅─.stop_incompatible() passes dots (#95)
│ │ ├─✅─.check_na() works (#95)
│ │ ├─✅─.check_size() works (#95)
│ │ ├─✅─.check_scalar() works (#95)
│ │ ├─✅─.check_x_no_more_than_y() works (#95)
│ │ └─✅─object_type returns expected types (#95)
│ ├─☑️─Feature 93: `are_*_ish()` functions
│ │ ├─✅─are_chr_ish() returns TRUE for every element of a chr (#93)
│ │ ├─✅─are_chr_ish() works for NULL (#93)
│ │ ├─✅─are_chr_ish() returns TRUE for every element of other atomics (#93)
│ │ ├─✅─are_chr_ish() works for lists and data.frames (#93, #128)
│ │ ├─✅─are_chr_ish() returns unnamed vectors (#93)
│ │ ├─✅─are_chr_ish() returns FALSE for non-vectors (#93)
│ │ ├─✅─is_chr_ish() returns a single TRUE for coercible objects (#93)
│ │ ├─✅─is_chr_ish() works for NULL (#93)
│ │ ├─✅─is_chr_ish() returns FALSE for uncoercibles (#93)
│ │ ├─✅─are_fct_ish() is TRUE for atomics when levels is NULL (#93)
│ │ ├─✅─are_fct_ish() works for NULL (#93)
│ │ ├─✅─are_fct_ish() works when levels are provided (#93)
│ │ ├─✅─are_fct_ish() works with to_na (#93)
│ │ ├─✅─.are_not_fct_ish_chr() works (#93)
│ │ ├─✅─are_fct_ish() works for lists (#93)
│ │ ├─✅─are_fct_ish() returns FALSE for non-vectors (#93)
│ │ ├─✅─are_fct_ish() deals with factor-ish S3 objects (#93)
│ │ ├─✅─is_fct_ish() works (#93)
│ │ ├─✅─are_int_ish() works for ints (#93)
│ │ ├─✅─are_int_ish() works for NULL (#93)
│ │ ├─✅─are_int_ish() works for logicals (#93)
│ │ ├─✅─are_int_ish() works for doubles (#93)
│ │ ├─✅─are_int_ish() works for characters (#93)
│ │ ├─✅─are_int_ish() respects coerce_character (#93)
│ │ ├─✅─are_int_ish() works for factors (#93)
│ │ ├─✅─are_int_ish() respects coerce_factor (#93)
│ │ ├─✅─are_int_ish() works for complex (#93)
│ │ ├─✅─are_int_ish() works for lists (#93, #128)
│ │ ├─✅─are_int_ish() returns FALSE for non-vectors (#93)
│ │ ├─✅─are_int_ish() returns FALSE for unhandled S3 objects (#93)
│ │ ├─✅─is_int_ish() works (#93)
│ │ ├─✅─are_lgl_ish() works for logicals (#93)
│ │ ├─✅─are_lgl_ish() works for NULL (#93)
│ │ ├─✅─are_lgl_ish() works for numerics (#93)
│ │ ├─✅─are_lgl_ish() works for characters (#93, #30)
│ │ ├─✅─are_lgl_ish() works for factors (#93, #30)
│ │ ├─✅─are_lgl_ish() works for lists (#93, #30)
│ │ ├─✅─are_lgl_ish() returns FALSE for non-vectors (#93)
│ │ ├─✅─are_lgl_ish() returns FALSE for unhandled S3 objects (#93)
│ │ ├─✅─is_lgl_ish() works (#93)
│ │ └─✅─.elements_are_cls_ish() works (#93)
│ ├─☑️─Feature 89: cli formatting of regex patterns in errors
│ │ ├─✅─regex_must_match() works as expected (#52, #89)
│ │ ├─✅─regex_must_match() deals with characters for glue (#52, #89)
│ │ ├─✅─regex_must_match() handles negation (#85, #89)
│ │ ├─✅─regex_must_not_match() works as expected (#85, #89)
│ │ └─✅─regex_must_not_match() doesn't freak out about pre-set negation (#85, #89)
│ ├─☑️─Feature 87: Support {stringr} pattern-modifier functions
│ │ ├─✅─stabilize_chr() works with stringr::fixed() (#87)
│ │ ├─✅─stabilize_chr() works with stringr::coll() (#87)
│ │ └─✅─stabilize_chr() works with stringr::regex() (#87)
│ ├─☑️─Feature 86: Allow `stabilize_chr()` to accept multiple regex rules
│ │ └─✅─stabilize_chr() accepts multiple regex rules (#86, #85)
│ └─☑️─Feature 85: regex_must_not_match
│   ├─✅─regex_must_match() handles negation (#85, #89)
│   ├─✅─regex_must_not_match() works as expected (#85, #89)
│   ├─✅─regex_must_not_match() doesn't freak out about pre-set negation (#85, #89)
│   ├─✅─stabilize_chr() accepts negated regex args (#85)
│   └─✅─stabilize_chr() accepts multiple regex rules (#86, #85)
├─█─Milestone: v0.3.0 (20 issues, 182 tests)
│ ├─☑️─Bug 204: bug: `stabilize_lst()` with nested list
│ │ ├─✅─specify_df() accepts columns named 'x_arg', 'call', 'x_class' (#204)
│ │ ├─✅─specify_lst() accepts elements named 'x_arg', 'call', 'x_class' (#204)
│ │ └─✅─stabilize_lst() with nested specify_lst() propagates errors correctly (#204)
│ ├─☑️─Feature 161: Show actual args in `specify_*()`
│ │ ├─✅─specify_cls builds the expected function with at least one arg (#150, #161)
│ │ ├─✅─specify_cls builds the expected function snapshot with at least one arg (#150, #161)
│ │ └─✅─The function built via specify_cls errors informatively for duplicated args (#150, #153, #161)
│ ├─☑️─Feature 157: Implement `to_list()`
│ │ ├─✅─to_lst() works for lists (#157, #166)
│ │ ├─✅─to_lst() works for NULL (#157)
│ │ ├─✅─to_lst() respects allow_null (#157)
│ │ ├─✅─to_lst() works for character vectors (#157)
│ │ ├─✅─to_lst() errors by default for functions (#157)
│ │ ├─✅─to_lst() works for functions with coerce_function = TRUE (#157)
│ │ ├─✅─to_lst() errors informatively for primitives (#157)
│ │ └─✅─to_list() exists (#157, #166)
│ ├─☑️─Feature 153: Better handling of `...` in `specify_*()`
│ │ └─✅─The function built via specify_cls errors informatively for duplicated args (#150, #153, #161)
│ ├─☑️─Feature 151: Implement `specify_lgl()`
│ │ ├─✅─specify_lgl can build a checker (#151)
│ │ └─✅─specify_lgl_scalar can build a value checker (#151)
│ ├─☑️─Feature 150: Implement `specify_fct()`
│ │ ├─✅─specify_cls builds the expected function with no args (#150)
│ │ ├─✅─specify_cls builds the expected function snapshot with no args (#150)
│ │ ├─✅─specify_cls builds the expected function with at least one arg (#150, #161)
│ │ ├─✅─specify_cls builds the expected function snapshot with at least one arg (#150, #161)
│ │ ├─✅─The function built via specify_cls errors informatively for duplicated args (#150, #153, #161)
│ │ ├─✅─specify_cls can build a scalar specifier (#150)
│ │ ├─✅─specify_cls builds the expected scalar function snapshot (#150)
│ │ ├─✅─specify_fct can build a level checker (#150)
│ │ └─✅─specify_fct_scalar can build a level checker (#150)
│ ├─☑️─Feature 149: Implement `specify_int()`
│ │ ├─✅─specify_int can build a value checker (#149)
│ │ └─✅─specify_int_scalar can build a value checker (#149)
│ ├─☑️─Feature 148: Implement `specify_dbl()`
│ │ ├─✅─specify_dbl can build a value checker (#148)
│ │ └─✅─specify_dbl_scalar can build a value checker (#148)
│ ├─☑️─Feature 147: Implement `specify_chr()`
│ │ ├─✅─specify_chr can build a regex checker (#147)
│ │ └─✅─specify_chr_scalar can build a regex checker (#147)
│ ├─☑️─Feature 142: Implement `stabilize_df()`
│ │ ├─✅─specify_df() creates a working validator (#142)
│ │ ├─✅─specify_df() errors when required column is missing (#142)
│ │ ├─✅─specify_df() passes through .min_rows, .max_rows (#142)
│ │ ├─✅─specify_df() passes through .col_names (#142)
│ │ ├─✅─specify_df() allows additional specs via ... (#142)
│ │ ├─✅─specify_data_frame() exists (#142)
│ │ ├─✅─stabilize_df() returns NULL for NULL input by default (#142)
│ │ ├─✅─stabilize_df() respects .allow_null (#142)
│ │ ├─✅─stabilize_df() errors for non-coercible input (#142)
│ │ ├─✅─stabilize_df() coerces a named list to a data frame (#142)
│ │ ├─✅─stabilize_df() returns a valid data frame unchanged (#142)
│ │ ├─✅─stabilize_df() coerces compatible column types (#142)
│ │ ├─✅─stabilize_df() errors when required column is missing (#142)
│ │ ├─✅─stabilize_df() errors informatively when column fails validation (#142)
│ │ ├─✅─stabilize_df() errors on extra columns by default (#142)
│ │ ├─✅─stabilize_df() allows extra columns with .extra_cols (#142)
│ │ ├─✅─stabilize_df() validates extra columns with .extra_cols (#142)
│ │ ├─✅─stabilize_df() enforces .min_rows (#142)
│ │ ├─✅─stabilize_df() enforces .min_rows (snapshot) (#142)
│ │ ├─✅─stabilize_df() enforces .max_rows (#142)
│ │ ├─✅─stabilize_df() enforces .max_rows (snapshot) (#142)
│ │ ├─✅─stabilize_df() passes with valid row counts (#142)
│ │ ├─✅─stabilize_df() enforces .col_names (#142)
│ │ ├─✅─stabilize_df() enforces .col_names (snapshot) (#142)
│ │ ├─✅─stabilize_df() allows .col_names alongside ... specs (#142)
│ │ ├─✅─stabilize_df() preserves data frame class after column coercion (#142)
│ │ ├─✅─stabilize_df() works with no column specs and .extra_cols (#142)
│ │ ├─✅─stabilize_df() with unnamed specs errors informatively (#142)
│ │ ├─✅─stabilise_df() exists (#142)
│ │ ├─✅─stabilize_data_frame() exists (#142)
│ │ └─✅─stabilise_data_frame() exists (#142)
│ ├─☑️─Feature 136: Export error functions
│ │ ├─✅─.compile_pkg_condition_classes() compiles condition class chains (#136)
│ │ ├─✅─.compile_pkg_error_classes() compiles error class chains (#136)
│ │ ├─✅─pkg_abort() throws the expected error (#136)
│ │ ├─✅─pkg_abort() uses parent when provided (#136)
│ │ ├─✅─pkg_abort() passes dots to cli_abort() (#136)
│ │ ├─✅─pkg_abort() uses message_env when provided (#136)
│ │ └─✅─expect_pkg_error_classes() tests expressions for classes (#136)
│ ├─☑️─Feature 203: feat: better `to_df()`
│ │ ├─✅─.check_all_named() works (#203)
│ │ ├─✅─.check_not_jagged() works (#203)
│ │ ├─✅─to_df() errors for an unnamed list (#203)
│ │ ├─✅─to_df() coerces named vector types to a data frame (#203)
│ │ └─✅─to_df() errors for inline vector expressions (#203)
│ ├─☑️─Feature 110: Implement `stabilize_lst()`
│ │ ├─✅─specify_lst() creates a working specifier (#110)
│ │ ├─✅─specify_lst() respects pre-configured element specs (#110)
│ │ ├─✅─specify_lst() supports element specs named 'x' and 'y' (#110)
│ │ ├─✅─specify_lst() passes through additional element specs from ... (#110)
│ │ ├─✅─specify_lst() respects .min_size (#110)
│ │ ├─✅─specify_lst() respects .allow_null (#110)
│ │ ├─✅─specify_list() exists (#110)
│ │ ├─✅─stabilize_lst() returns NULL for NULL input by default (#110)
│ │ ├─✅─stabilize_lst() respects .allow_null (#110)
│ │ ├─✅─stabilize_lst() returns a valid list unchanged (#110)
│ │ ├─✅─stabilize_lst() validates required named elements (#110)
│ │ ├─✅─stabilize_lst() errors when required named element is missing (#110)
│ │ ├─✅─stabilize_lst() errors informatively when element fails validation (#110)
│ │ ├─✅─stabilize_lst() errors on extra named elements by default (#110)
│ │ ├─✅─stabilize_lst() validates extra named elements with .named (#110)
│ │ ├─✅─stabilize_lst() errors on unnamed elements by default (#110)
│ │ ├─✅─stabilize_lst() validates unnamed elements with .unnamed (#110)
│ │ ├─✅─stabilize_lst() handles mixed named/unnamed lists (#110)
│ │ ├─✅─stabilize_lst() enforces .min_size (#110)
│ │ ├─✅─stabilize_lst() enforces .max_size (#110)
│ │ ├─✅─stabilize_lst() validates nested lists (#110)
│ │ ├─✅─stabilize_lst() with unnamed specs errors informatively (#110)
│ │ ├─✅─.check_duplicate_names(): errors on duplicate names by default (#110)
│ │ ├─✅─.check_duplicate_names(): allows duplicates with .allow_duplicate_names = TRUE (#110)
│ │ ├─✅─.check_duplicate_names(): reports all duplicate name groups (#110)
│ │ ├─✅─.check_duplicate_names(): unnamed elements do not count as duplicates (#110)
│ │ ├─✅─stabilize_list() exists (#110)
│ │ ├─✅─stabilise_lst() exists (#110)
│ │ ├─✅─stabilise_list() exists (#110)
│ │ ├─✅─stabilize_present() returns any non-NULL value unchanged (#110)
│ │ ├─✅─stabilize_present() errors for NULL (#110)
│ │ └─✅─stabilize_present() works as an element spec in stabilize_lst() (#110)
│ ├─☑️─Feature 201: feat: `to_df()`
│ │ ├─✅─to_df() returns a data frame unchanged (#201)
│ │ ├─✅─to_df() returns NULL for NULL input by default (#201)
│ │ ├─✅─to_df() respects allow_null (#201)
│ │ ├─✅─to_df() coerces a named list to a data frame (#201)
│ │ ├─✅─to_df() coerces a list of equal-length vectors to a data frame (#201)
│ │ ├─✅─to_df() errors for a list with incompatible column lengths (#201)
│ │ ├─✅─to_df() errors for non-coercible types (#201)
│ │ ├─✅─to_df.default() errors for non-coercible types (#201)
│ │ └─✅─to_data_frame() exists (#201)
│ ├─☑️─Bug 197: Update `specify_*_scalar()` defaults to match `stabilize_*_scalar()`
│ │ ├─✅─specify_chr_scalar defaults to allow_null = FALSE (#197)
│ │ ├─✅─specify_chr_scalar defaults to allow_zero_length = FALSE (#197)
│ │ ├─✅─specify_dbl_scalar defaults to allow_null = FALSE (#197)
│ │ ├─✅─specify_dbl_scalar defaults to allow_zero_length = FALSE (#197)
│ │ ├─✅─specify_fct_scalar defaults to allow_null = FALSE (#197)
│ │ ├─✅─specify_fct_scalar defaults to allow_zero_length = FALSE (#197)
│ │ ├─✅─specify_int_scalar defaults to allow_null = FALSE (#197)
│ │ ├─✅─specify_int_scalar defaults to allow_zero_length = FALSE (#197)
│ │ ├─✅─specify_lgl_scalar defaults to allow_null = FALSE (#197)
│ │ └─✅─specify_lgl_scalar defaults to allow_zero_length = FALSE (#197)
│ ├─☑️─Feature 177: Don't mention levels/to_na in factor message?
│ │ └─✅─to_fct() throws errors for bad levels (#62, #67, #177)
│ ├─☑️─Feature 176: Better error messages
│ │ ├─✅─stabilize_dbl() checks min_value (#23, #176)
│ │ ├─✅─stabilize_dbl() checks max_value (#23, #176)
│ │ ├─✅─stabilize_int() checks min_value (#2, #6, #176)
│ │ └─✅─stabilize_int() checks max_value (#5, #176)
│ ├─☑️─Feature 167: Add stabilise_*() aliases
│ │ ├─✅─stabilise_chr() exists (#167)
│ │ ├─✅─stabilise_character() exists (#167)
│ │ ├─✅─stabilise_chr_scalar() exists (#167)
│ │ ├─✅─stabilise_character_scalar() exists (#167)
│ │ ├─✅─stabilise_dbl() exists (#167)
│ │ ├─✅─stabilise_double() exists (#167)
│ │ ├─✅─stabilise_dbl_scalar() exists (#167)
│ │ ├─✅─stabilise_double_scalar() exists (#167)
│ │ ├─✅─stabilise_fct() exists (#167)
│ │ ├─✅─stabilise_factor() exists (#167)
│ │ ├─✅─stabilise_fct_scalar() exists (#167)
│ │ ├─✅─stabilise_factor_scalar() exists (#167)
│ │ ├─✅─stabilise_int() exists (#167)
│ │ ├─✅─stabilise_integer() exists (#167)
│ │ ├─✅─stabilise_int_scalar() exists (#167)
│ │ ├─✅─stabilise_integer_scalar() exists (#167)
│ │ ├─✅─stabilise_lgl() exists (#167)
│ │ ├─✅─stabilise_logical() exists (#167)
│ │ ├─✅─stabilise_lgl_scalar() exists (#167)
│ │ └─✅─stabilise_logical_scalar() exists (#167)
│ ├─☑️─Task 166: Make to_lst() the primary spelling
│ │ ├─✅─to_lst() works for lists (#157, #166)
│ │ └─✅─to_list() exists (#157, #166)
│ └─☑️─Feature 164: Add spelled-out aliases for all functions
│   ├─✅─are_character_ish() exists (#164)
│   ├─✅─is_character_ish() exists (#164)
│   ├─✅─are_double_ish() exists (#164)
│   ├─✅─is_double_ish() exists (#164)
│   ├─✅─are_factor_ish() exists (#164)
│   ├─✅─is_factor_ish() exists (#164)
│   ├─✅─are_integer_ish() exists (#164)
│   ├─✅─is_integer_ish() exists (#164)
│   ├─✅─are_logical_ish() exists (#164)
│   ├─✅─is_logical_ish() exists (#164)
│   ├─✅─specify_character() exists (#164)
│   ├─✅─stabilize_character_scalar() exists (#164)
│   ├─✅─specify_double() exists (#164)
│   ├─✅─stabilize_double_scalar() exists (#164)
│   ├─✅─specify_factor() exists (#164)
│   ├─✅─stabilize_factor_scalar() exists (#164)
│   ├─✅─specify_integer() exists (#164)
│   ├─✅─stabilize_integer_scalar() exists (#164)
│   ├─✅─specify_logical() exists (#164)
│   ├─✅─stabilize_logical_scalar() exists (#164)
│   ├─✅─stabilize_character() exists (#164)
│   ├─✅─stabilize_character_scalar() exists (#164)
│   ├─✅─stabilize_double() exists (#164)
│   ├─✅─stabilize_double_scalar() exists (#164)
│   ├─✅─stabilize_factor() exists (#164)
│   ├─✅─stabilize_factor_scalar() exists (#164)
│   ├─✅─stabilize_integer() exists (#164)
│   ├─✅─stabilize_integer_scalar() exists (#164)
│   ├─✅─stabilize_logical() exists (#164)
│   ├─✅─stabilize_logical_scalar() exists (#164)
│   ├─✅─to_character() exists (#164)
│   ├─✅─to_character_scalar() exists (#164)
│   ├─✅─to_double() exists (#164)
│   ├─✅─to_double_scalar() exists (#164)
│   ├─✅─to_factor() exists (#164)
│   ├─✅─to_factor_scalar() exists (#164)
│   ├─✅─to_integer() exists (#164)
│   ├─✅─to_integer_scalar() exists (#164)
│   ├─✅─to_logical() exists (#164)
│   └─✅─to_logical_scalar() exists (#164)
└─█─Milestone: <none> (2 issues, 24 tests)
  ├─☑️─Issue 189: feat: `to_*_scalar()` default arguments
  │ ├─✅─stabilize_chr_scalar() allows length-1 chrs through (#22, #189)
  │ ├─✅─stabilize_chr_scalar() respects allow_null (#22, #189)
  │ ├─✅─stabilize_dbl_scalar() allows length-1 dbls through (#23, #189)
  │ ├─✅─stabilize_dbl_scalar() respects allow_null (#23, #189)
  │ ├─✅─stabilize_fct_scalar() works (#62, #189)
  │ ├─✅─stabilize_fct_scalar() respects allow_null (#62, #189)
  │ ├─✅─stabilize_int_scalar() allows length-1 ints through (#12, #189)
  │ ├─✅─stabilize_int_scalar() respects allow_null (#12, #189)
  │ ├─✅─stabilize_lgl_scalar() allows length-1 lgls through (#28, #189)
  │ ├─✅─stabilize_lgl_scalar() respects allow_null (#28, #189)
  │ ├─✅─to_chr_scalar() allows length-1 chrs through (#22, #189)
  │ ├─✅─to_chr_scalar() respects allow_null (#22, #189)
  │ ├─✅─to_chr_scalar respects allow_zero_length (#22, #43, #45, #189)
  │ ├─✅─to_dbl_scalar() respects allow_null (#23, #189)
  │ ├─✅─to_dbl_scalar respects allow_zero_length (#23, #43, #45, #189)
  │ ├─✅─to_fct_scalar respects allow_zero_length (#62, #43, #45, #189)
  │ ├─✅─to_int_scalar() respects allow_null (#12, #189)
  │ ├─✅─to_int_scalar respects allow_zero_length (#12, #43, #45, #189)
  │ ├─✅─to_lgl_scalar() allows length-1 lgls through (#32, #189)
  │ └─✅─to_lgl_scalar() respects allow_null (#32, #189)
  └─☑️─Feature 188: feat: expect_pkg_error_snapshot()
    ├─✅─expect_pkg_error_snapshot() snapshots error class and message (#188)
    ├─✅─expect_pkg_error_snapshot() works with multiple class components (#188)
    ├─✅─expect_pkg_error_snapshot() works from an env without stbl attached (#188)
    └─✅─expect_pkg_error_classes() works from an env without stbl attached (#188)
# Issue state: 📥 = open, ☑️ = closed (completed), ⛔ = closed (won't fix)
# Test disposition: ✅ = passed, ❌ = failed, 🚫 = skipped
✅ All tests passed

🟢 All issues have at least one test

🙈 21 issues with label "qcthat-nocov" were ignored


This report was generated by this GitHub Actions run.

Last updated: 2026-04-04 14:52:58 UTC

Session Info ─ Session info ───────────────────────────────────────────────────────────────

setting value

version R version 4.5.3 (2026-03-11)

os Ubuntu 24.04.4 LTS

system x86_64, linux-gnu

ui X11

language (EN)

collate en_US.UTF-8

ctype en_US.UTF-8

tz UTC

date 2026-04-04

pandoc 3.1.3 @ /usr/bin/pandoc

quarto NA

─ Packages ───────────────────────────────────────────────────────────────────

package * version date (UTC) lib source

askpass 1.2.1 2024-10-04 [1] RSPM

astgrepr 0.1.1 2025-06-07 [1] RSPM

backports 1.5.1 2026-04-03 [1] RSPM

base * 4.5.3 2026-03-28 [2] local

base64enc 0.1-6 2026-02-02 [1] RSPM

boot 1.3-32 2025-08-29 [2] CRAN (R 4.5.3)

brew 1.0-10 2023-12-16 [1] RSPM

brio 1.1.5 2024-04-24 [1] RSPM

bslib 0.10.0 2026-01-26 [1] RSPM

cachem 1.1.0 2024-05-16 [1] RSPM

callr 3.7.6 2024-03-25 [1] RSPM

checkmate 2.3.4 2026-02-03 [1] RSPM

class 7.3-23 2025-01-01 [2] CRAN (R 4.5.3)

cli 3.6.5 2025-04-23 [1] RSPM

clipr 0.8.0 2022-02-22 [1] RSPM

cluster 2.1.8.2 2026-02-05 [2] CRAN (R 4.5.3)

codetools 0.2-20 2024-03-31 [2] CRAN (R 4.5.3)

commonmark 2.0.0 2025-07-07 [1] RSPM

compiler 4.5.3 2026-03-28 [2] local

covr 3.6.5 2025-11-09 [1] RSPM

crayon 1.5.3 2024-06-20 [1] RSPM

credentials 2.0.3 2025-09-12 [1] RSPM

curl 7.0.0 2025-08-19 [1] RSPM

datasets * 4.5.3 2026-03-28 [2] local

desc 1.4.3 2023-12-10 [1] RSPM

devtools 2.5.0 2026-03-14 [1] RSPM

diffobj 0.3.6 2025-04-21 [1] RSPM

digest 0.6.39 2025-11-19 [1] RSPM

docopt 0.7.2 2025-03-25 [1] RSPM (R 4.5.3)

downlit 0.4.5 2025-11-14 [1] RSPM

dplyr 1.2.1 2026-04-03 [1] RSPM

ellipsis 0.3.2 2021-04-29 [1] RSPM

emoji 16.0.0 2024-10-28 [1] RSPM

evaluate 1.0.5 2025-08-27 [1] RSPM

fansi 1.0.7 2025-11-19 [1] RSPM

fastmap 1.2.0 2024-05-15 [1] RSPM

fontawesome 0.5.3 2024-11-16 [1] RSPM

foreign 0.8-91 2026-01-29 [2] CRAN (R 4.5.3)

fs 2.0.1 2026-03-24 [1] RSPM

generics 0.1.4 2025-05-09 [1] RSPM

gert 2.3.1 2026-01-11 [1] RSPM

gh 1.5.0 2025-05-26 [1] RSPM

git2r 0.36.2 2025-03-29 [1] RSPM

gitcreds 0.1.2 2022-09-08 [1] RSPM

glue 1.8.0 2024-09-30 [1] RSPM

graphics * 4.5.3 2026-03-28 [2] local

grDevices * 4.5.3 2026-03-28 [2] local

grid 4.5.3 2026-03-28 [2] local

highr 0.12 2026-03-06 [1] RSPM

htmltools 0.5.9 2025-12-04 [1] RSPM

htmlwidgets 1.6.4 2023-12-06 [1] RSPM

httpuv 1.6.17 2026-03-18 [1] RSPM

httr 1.4.8 2026-02-13 [1] RSPM

httr2 1.2.2 2025-12-08 [1] RSPM

ini 0.3.1 2018-05-20 [1] RSPM

jquerylib 0.1.4 2021-04-26 [1] RSPM

jsonlite 2.0.0 2025-03-27 [1] RSPM

KernSmooth 2.23-26 2025-01-01 [2] CRAN (R 4.5.3)

knitr 1.51 2025-12-20 [1] RSPM

later 1.4.8 2026-03-05 [1] RSPM

lattice 0.22-9 2026-02-09 [2] CRAN (R 4.5.3)

lifecycle 1.0.5 2026-01-08 [1] RSPM

littler 0.3.22 2026-02-04 [1] RSPM (R 4.5.3)

magick 2.9.1 2026-02-28 [1] RSPM

magrittr 2.0.4 2025-09-12 [1] RSPM

MASS 7.3-65 2025-02-28 [2] CRAN (R 4.5.3)

Matrix 1.7-4 2025-08-28 [2] CRAN (R 4.5.3)

memoise 2.0.1 2021-11-26 [1] RSPM

methods * 4.5.3 2026-03-28 [2] local

mgcv 1.9-4 2025-11-07 [2] CRAN (R 4.5.3)

mime 0.13 2025-03-17 [1] RSPM

miniUI 0.1.2 2025-04-17 [1] RSPM

nlme 3.1-168 2025-03-31 [2] CRAN (R 4.5.3)

nnet 7.3-20 2025-01-01 [2] CRAN (R 4.5.3)

openssl 2.3.5 2026-02-26 [1] RSPM

otel 0.2.0 2025-08-29 [1] RSPM

pak 0.9.2 2025-12-22 [1] RSPM (R 4.5.0)

parallel 4.5.3 2026-03-28 [2] local

pillar 1.11.1 2025-09-17 [1] RSPM

pkgbuild 1.4.8 2025-05-26 [1] RSPM

pkgconfig 2.0.3 2019-09-22 [1] RSPM

pkgdown 2.2.0 2025-11-06 [1] RSPM

pkgload 1.5.1 2026-04-01 [1] RSPM

praise 1.0.0 2015-08-11 [1] RSPM

prettyunits 1.2.0 2023-09-24 [1] RSPM

processx 3.8.7 2026-04-01 [1] RSPM

profvis 0.4.0 2024-09-20 [1] RSPM

promises 1.5.0 2025-11-01 [1] RSPM

ps 1.9.2 2026-03-31 [1] RSPM

purrr 1.2.1 2026-01-09 [1] RSPM

qcthat 1.1.2 2026-04-04 [1] Github (Gilead-Public/qcthat@d0958dc)

R6 2.6.1 2025-02-15 [1] RSPM

ragg 1.5.2 2026-03-23 [1] RSPM

rappdirs 0.3.4 2026-01-17 [1] RSPM

rcmdcheck 1.4.0 2021-09-27 [1] RSPM

Rcpp 1.1.1 2026-01-10 [1] RSPM

rex 1.2.2 2026-03-28 [1] RSPM

rlang 1.1.7 2026-01-09 [1] RSPM

rmarkdown 2.31 2026-03-26 [1] RSPM

roxygen2 7.3.3 2025-09-03 [1] RSPM

rpart 4.1.24 2025-01-07 [2] CRAN (R 4.5.3)

rprojroot 2.1.1 2025-08-26 [1] RSPM

rrapply 1.2.8 2025-11-25 [1] RSPM

rstudioapi 0.18.0 2026-01-16 [1] RSPM

rversions 3.0.0 2025-10-09 [1] RSPM

sass 0.4.10 2025-04-11 [1] RSPM

sessioninfo 1.2.3 2025-02-05 [1] RSPM

shiny 1.13.0 2026-02-20 [1] RSPM

sourcetools 0.1.7-2 2026-03-28 [1] RSPM

spatial 7.3-18 2025-01-01 [2] CRAN (R 4.5.3)

splines 4.5.3 2026-03-28 [2] local

stats * 4.5.3 2026-03-28 [2] local

stats4 4.5.3 2026-03-28 [2] local

stbl 0.3.0 2026-04-04 [1] local

stringi 1.8.7 2025-03-27 [1] RSPM

stringr 1.6.0 2025-11-04 [1] RSPM

survival 3.8-6 2026-01-16 [2] CRAN (R 4.5.3)

sys 3.4.3 2024-10-04 [1] RSPM

systemfonts 1.3.2 2026-03-05 [1] RSPM

tcltk 4.5.3 2026-03-28 [2] local

testthat 3.3.2 2026-01-11 [1] RSPM

textshaping 1.0.5 2026-03-06 [1] RSPM

tibble 3.3.1 2026-01-11 [1] RSPM

tidyr 1.3.2 2025-12-19 [1] RSPM

tidyselect 1.2.1 2024-03-11 [1] RSPM

tinytex 0.59 2026-03-28 [1] RSPM

tools 4.5.3 2026-03-28 [2] local

urlchecker 1.0.1 2021-11-30 [1] RSPM

usethis 3.2.1 2025-09-06 [1] RSPM

utf8 1.2.6 2025-06-08 [1] RSPM

utils * 4.5.3 2026-03-28 [2] local

vctrs 0.7.2 2026-03-21 [1] RSPM

waldo 0.6.2 2025-07-11 [1] RSPM

whisker 0.4.1 2022-12-05 [1] RSPM

withr 3.0.2 2024-10-28 [1] RSPM

xfun 0.57 2026-03-20 [1] RSPM

xml2 1.5.2 2026-01-17 [1] RSPM

xopen 1.0.1 2024-04-25 [1] RSPM

xtable 1.8-8 2026-02-22 [1] RSPM

yaml 2.3.12 2025-12-10 [1] RSPM

zip 2.3.3 2025-05-13 [1] RSPM

[1] /usr/local/lib/R/site-library

[2] /usr/local/lib/R/library

[3] /__w/_temp/Library

  • ── Packages attached to the search path.

──────────────────────────────────────────────────────────────────────────────