readmit

readmit creates editable, user-owned Readmission Risk Pool (RRP) projects. Each project includes configuration, source-mapping and risk-provider scripts, branding, and its own Shiny application. Persistent history can be initialized explicitly, rrp_run() retains completed assessments, and status and history inspection are available. rrp_refresh_products() writes analytical CSVs from retained history. The project app displays an interactive Current Risk Pool, a selected episode's recorded risk trajectory, and a snapshot-level Overview.

Create and open a project

After installing readmit, create a project at a new destination:

library(readmit)

project <- rrp_project_init(
  path = "my-rrp-project",
  project_id = "my-project"
)

rrp_project_validate(project)

The path is relative to your current working directory unless you supply an absolute path. Its parent directory must already exist, and the destination must not exist, even as an empty directory. The generated files belong to you: edit rrp-project.dcf, rrp-authoring.dcf, _brand.yml, R/produce-canonical.R, and R/calculate-risk.R for your project. rrp_project_validate() checks that the configuration and both authoring functions load; it does not run them. Both generated functions begin as deliberate stubs, so the untouched project passes this structural check. Implement the source mapper to return the canonical discharge episodes and terminal events described in the project README, and implement the risk provider for eligible episodes. Validate again after editing. Validation checks that the scripts load; it does not establish that their data or predictions will work during a run.

Then initialize persistent history and run at an explicit UTC analytical time:

rrp_state_init(project)
assessment <- rrp_run(
  project, as.POSIXct("2026-01-10 12:00:00", tz = "UTC")
)
rrp_project_status(project)
rrp_inspect_history(project, run_id = assessment$run_id)
rrp_refresh_products(project)

This creates empty state/history.duckdb tables in the project and refuses to overwrite existing state. State initialization does not run either authoring function. Each rrp_run() call obtains canonical facts, assesses eligible episodes through the provider, and atomically appends the completed run and its episode outcomes. It returns the run ID and accepted, failed, and ineligible counts. rrp_project_status() also works before state initialization; rrp_inspect_history() requires state. Both read retained information without sourcing your scripts. A provider failure is retained for its episode while other eligible episodes continue. Completed runs append history; later event knowledge does not rewrite earlier results. After at least one completed run, rrp_refresh_products() reads history and writes state/products/current-remaining-risk.csv, remaining-risk-trajectory.csv, and operational-scope-summary.csv. It selects the run with the greatest analytical time, which may differ from the most recently executed run. Supply the complete relevant discharge population for operational assessments: a later partial run replaces the earlier population in current products. The package determines clinical eligibility. Eligible provider-failure episodes stay in the current-risk file with a missing probability; earlier estimates are not substituted. The trajectory contains recorded accepted estimates for current eligible episodes. Read the generated files with ordinary CSV tools, such as read.csv(file.path(project, "state/products/current-remaining-risk.csv")). Refresh does not rerun your scripts, change history, or edit the app. The three-file replacement is staged but is not fully atomic if a filesystem error occurs during final replacement.

The application uses shiny, bslib, reactable, plotly, and yaml in the environment where it runs. Install them there, then launch the app directly from the same working directory used in the example:

install.packages(c("shiny", "bslib", "reactable", "plotly", "yaml"))
shiny::runApp("my-rrp-project/app")

The app opens with Current Risk Pool and Overview navigation. Before products exist, it shows a clear empty state. After refresh, Current Risk Pool displays accepted and failed eligible episodes with search, sorting, numeric-range filtering, and row selection. Failed predictions remain visible under numeric filtering and show Unavailable rather than zero risk. Selecting an episode shows its current estimate separately from accepted historical assessments in an interactive point chart and exact-observation table; compact sparklines appear in the pool. Overview summarizes operational counts and the minimum, median, and maximum of accepted current estimates, independent of pool filters. The app's Reload Data control rereads existing CSVs; it does not generate products.