add-parsnip-model — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited add-parsnip-model (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Create entirely new model specifications for the parsnip package. This skill covers creating new model types (like linear_reg(), boost_tree()) with their constructors, registration, and engine implementations.
Use this skill when: Creating a fundamentally new model type for parsnip.
For adding engines to existing models: See add-parsnip-engine skill instead.
--------------------------------------------------------------------------------
Before creating a new parsnip model, ensure you have:
R Package Development:
Required for extension packages
iteration practices
Parsnip Architecture:
parsnip concepts
fundamentals
--------------------------------------------------------------------------------
Before diving into implementation, determine the complexity of your model:
Simple Model:
→ Follow streamlined approach: Focus on getting the basics right, avoid over-engineering
Complex Model:
→ Reference detailed guides for multi-mode handling, encoding options, and advanced patterns
Target files regardless of complexity:
acceptable to reach 4-6 if needed
docs); acceptable to reach 5-8 if needed
Start here: Model Constructor Design
Decide on:
sparse_reg())This step defines the user-facing API.
Review: Model Specification System
Learn how parsnip's registration system works:
Follow: Registration Sequence
Complete registration in the correct order: 1. set_new_model() - Declare model exists 2. set_model_mode() - Declare supported modes 3. set_model_engine() - Register each engine 4. set_dependency() - Package requirements 5. set_model_arg() - Argument translation 6. set_fit() - Fitting method 7. set_encoding() - Data conversion (if needed) 8. set_pred() - Each prediction type
Plan carefully: Argument Design
Create standardized arguments that:
Core implementation: Fit and Predict Methods
For each engine:
Standardize output: Prediction Types
Implement appropriate prediction types for each mode:
numeric, conf_int, pred_intclass, probtime, survival, hazard, linear_predquantileIf multi-mode: Mode Handling
For models supporting multiple modes:
For matrix/xy interfaces: Encoding Options
Configure how formulas are converted:
--------------------------------------------------------------------------------
Essential tests:
Test each engine separately:
test_that("lm engine works", {
skip_if_not_installed("lm_package")
spec <- my_model() |> set_engine("lm")
fit <- fit(spec, y ~ x, data = data)
expect_s3_class(fit, "model_fit")
preds <- predict(fit, data)
expect_named(preds, ".pred")
})--------------------------------------------------------------------------------
For PRs to tidymodels/parsnip:
Additional resources for source development:
Parsnip-specific patterns
issues
Comprehensive tests
Key differences from extensions:
:::)R/[model].R, R/[model]_data.R)--------------------------------------------------------------------------------
sparse_reg()Hypothetical new model for sparse regression:
Note: This example shows extension development patterns. For source development, omit parsnip:: prefixes and use internal functions as shown in source-guide.md.R/sparse_reg.R): sparse_reg <- function(mode = "regression",
penalty = NULL,
sparsity_threshold = NULL,
engine = "glmnet") {
args <- list(
penalty = rlang::enquo(penalty),
sparsity_threshold = rlang::enquo(sparsity_threshold)
)
parsnip::new_model_spec(
"sparse_reg",
args = args,
eng_args = NULL,
mode = mode,
user_specified_mode = FALSE,
method = NULL,
engine = engine,
user_specified_engine = !missing(engine)
)
}.onLoad() or package setup): # Declare model
parsnip::set_new_model("sparse_reg")
parsnip::set_model_mode("sparse_reg", "regression")
# Register glmnet engine
parsnip::set_model_engine("sparse_reg", "regression", "glmnet")
parsnip::set_dependency("sparse_reg", "glmnet", "glmnet", "regression")
# Translate arguments
parsnip::set_model_arg(
model = "sparse_reg",
eng = "glmnet",
parsnip = "penalty",
original = "lambda",
func = list(pkg = "dials", fun = "penalty"),
has_submodel = TRUE
)
# Fit method
parsnip::set_fit(
model = "sparse_reg",
eng = "glmnet",
mode = "regression",
value = list(
interface = "matrix",
protect = c("x", "y"),
func = c(pkg = "glmnet", fun = "glmnet"),
defaults = list(family = "gaussian")
)
)
# Predictions
parsnip::set_pred(
model = "sparse_reg",
eng = "glmnet",
mode = "regression",
type = "numeric",
value = list(
pre = NULL,
post = NULL,
func = c(fun = "predict"),
args = list(
object = rlang::expr(object$fit),
newx = rlang::expr(as.matrix(new_data)),
type = "response"
)
)
) test_that("sparse_reg constructor works", {
spec <- sparse_reg()
expect_s3_class(spec, "sparse_reg")
expect_equal(spec$mode, "regression")
expect_equal(spec$engine, "glmnet")
})
test_that("sparse_reg fits and predicts", {
skip_if_not_installed("glmnet")
spec <- sparse_reg(penalty = 0.1) |> set_engine("glmnet")
fit <- fit(spec, mpg ~ ., data = mtcars)
expect_s3_class(fit, "model_fit")
preds <- predict(fit, mtcars[1:5, ])
expect_s3_class(preds, "tbl_df")
expect_named(preds, ".pred")
expect_equal(nrow(preds), 5)
})--------------------------------------------------------------------------------
Prioritize correctness over structure. Focus on getting the implementation right before worrying about file organization.
Code correctness issues (fix first): 1. Incorrect column names - Follow .pred naming conventions strictly (.pred, .pred_class, .pred_lower) 2. Wrong interface type - Match engine's expected input format (formula vs matrix vs xy) 3. Inconsistent argument naming - Use tidymodels standards (penalty, mixture), not engine names 4. Missing prediction post-processing - Ensure output format matches parsnip conventions
Implementation completeness (fix second): 5. Incomplete registration - Must complete full sequence for each engine (set_new_model → set_model_mode → set_model_engine → set_dependency → set_model_arg → set_fit → set_pred) 6. Missing mode registration - Must register modes explicitly with set_model_mode() 7. No argument translation - Main arguments must map to engine arguments via set_model_arg() 8. Insufficient testing - Test all modes, engines, prediction types, and both fit() and fit_xy()
Structural concerns (address last): 9. Too many files - Keep to 2-3 files for extensions, 2-4 for source (see File Discipline section)
--------------------------------------------------------------------------------
INSTRUCTIONS FOR CLAUDE:
Before implementing, verify this is truly a NEW model type. If the user requests:
boost_tree") → Stop. Politely explain this should use the add-parsnip-engine skill instead
Suggest using engine-specific arguments rather than creating a new model
the existing model
Only proceed with implementation if it's genuinely a new model type that doesn't exist in parsnip.
Create a new model when:
Don't create a new model when:
add-parsnip-engine instead
arguments instead
Examples:
survival_reg() - New outcome type (censored data)naive_bayes() - Distinct algorithm familyrand_forest()linear_reg()--------------------------------------------------------------------------------
Keep implementations focused and avoid creating unnecessary files.
Target file counts:
Extension development:
R/[model_name].R - Model constructortests/testthat/test-[model_name].R - TestsREADME.md - Only if needed for package usersSource development:
R/[model_name].R - Model constructorR/[model_name]_data.R - Engine registrationstests/testthat/test-[model_name].R - Testsman/rmd/[model_name]_[engine].Rmd - Engine docs (optional)Do not create:
IMPLEMENTATION_SUMMARY.md)
Instead:
@examples tags@details tags--------------------------------------------------------------------------------
engines to your new model
parameters for model arguments
fitting
predictions with custom metrics
After creating your model:
For questions or contributions, see:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.