This document defines a suite of specialized LLM-based agents designed to streamline and enhance the development, testing, documentation, and maintenance of Jamovi modules, specifically:
Each agent encapsulates a focused set of responsibilities and expertise, enabling efficient collaboration with Large Language Models (LLMs) for code generation, debugging, documentation, quality assurance, refactoring, and domain-specific analysis.
<module_name>
, <function_name>
, <description>
) with context-specific details.| Agent Name | Primary Responsibilities |
| ------------------------ | --------------------------------------------------------------------------------------------------------- |
| ModuleArchitectAgent | Scaffolding module structure, YAML configuration, metadata, dependencies, import/export logic |
| RFunctionGenAgent | Generating robust, idiomatic R functions for statistical analyses and data manipulation |
| DocumentationAgent | Creating or updating .R
, .u.yaml
, .r.yaml
, .a.yaml
files with clear comments and user-facing help |
| PlotDesignAgent | Designing and coding statistical plots (ggplot2, Jamovi plotting conventions, bslib themes) |
| TestQAAgent | Writing unit tests (testthat
) and integration tests; validating existing functions for edge cases |
| YAMLConfigAgent | Drafting and validating YAML specification files for Jamovi modules (.u.yaml
, .r.yaml
, .a.yaml
) |
| RefactorAgent | Refactoring and optimizing existing code for readability, performance, and style compliance |
| BugTrackerAgent | Identifying, reproducing, and proposing fixes for bugs based on user error messages or failing tests |
| CIIntegrationAgent | Configuring GitHub Actions, CI pipelines, and automated checks for module builds, linting, and testing |
| DomainExpertAgent | Providing domain-specific insights (e.g., clinical decision thresholds, interpretation of survival plots) |
| VisualizationUXAgent | Enhancing UI/UX: table layouts (DT), tooltips, theme toggles, and accessibility |
| ReleaseManagerAgent | Drafting release notes, version bump logic, changelog generation, packaging (tarball, zip) |
Each agent is described in detail below.
ClinicoPath statistical modules (meddecide, jjstatsplot, ClinicoPathDescriptives, jsurvival) follow a consistent structure, treating each analysis as an agent with defined inputs, processing logic, and outputs. These agents are implemented as R6 classes (in .b.R
files) and configured by YAML files (.a.yaml
, .u.yaml
, .r.yaml
). This design cleanly separates the user interface, analysis options, and result definitions.
Function Calls Using private$
: Agents delegate tasks to private helper methods (e.g., .prepareData()
, .computeMetrics()
, .buildTable()
) defined within the private = list()
block of the R6 class.
Use of self$options
and self$results
:
self$options
: Holds inputs defined in .a.yaml
. Access values directly (e.g., self$options$outcome
, self$options$alpha
).
self$results
: Contains output objects defined in .r.yaml
. Populate outputs using $setContent()
, $setRow()
, $addRow()
, and $setState()
.
YAML Files Relationship:
.a.yaml
: Defines options (names, types, defaults, constraints) and registers the analysis.
.u.yaml
: Describes UI layout (controls, labels, grouping) by referencing options in .a.yaml
..r.yaml
: Specifies result objects (tables, plots, text), renderFun
for images, visibility conditions, and dependencies (clearWith
).
Jamovi Developer Guidelines Integration:
Based on Jamovi Module Authoring, modules include:
DESCRIPTION
file: Lists dependencies (e.g., Imports: jmvcore, survival
).jamovi-module.yml
manifest: Registers version, dependencies, and jmvcore compatibility.man/
folder: Contains Rd documentation generated from roxygen2 comments in R.R/
folder: Contains .b.R
(implementation), .h.R
(auto-generated base), and other supporting functions.resources/
folder: Provides icons or additional JS/CSS for custom UI if needed.tests/testthat/
for unit tests; ensure R CMD check passes and CI workflows validate builds.By examining real-world examples and official guidelines, we see how inputs flow from UI to R code and how outputs are formatted for display.
.a.yaml
)Purpose: Register the analysis, define options and defaults, and group in the menu.
Pattern Example (meddecide/kappaSizeCI.a.yaml):
analysis-name: kappaSizeCI
class: kappaSizeCIClass
package: meddecide
requiresData: false
title: "Kappa Sample Size Calculation"
menu:
- name: "Interobserver Analysis"
sub-menu:
- name: "Kappa Sample Size"
options:
- name: outcome
type: list
values: ["2", "3", "4", "5"]
default: "2"
title: "Number of Outcome Levels"
- name: kappa0
type: number
default: 0.60
minimum: 0.01
maximum: 0.99
title: "Null Kappa (K<sub>0</sub>)"
description: "Expected kappa under null hypothesis"
- name: kappaL
type: number
default: 0.40
minimum: 0.01
maximum: 0.99
title: "Lower Bound of Kappa (K<sub>L</sub>)"
description: "Lower limit of clinically acceptable kappa"
- name: kappaU
type: number
default: 0.80
minimum: 0.01
maximum: 0.99
title: "Upper Bound of Kappa (K<sub>U</sub>)"
description: "Upper limit of clinically acceptable kappa"
- name: props
type: string
default: "0.20, 0.80"
title: "Category Proportions"
description: "Comma-separated proportions for each outcome level"
- name: raters
type: integer
default: 2
minimum: 2
maximum: 10
title: "Number of Raters"
- name: alpha
type: number
default: 0.05
minimum: 0.01
maximum: 0.10
title: "Significance Level (α)"
refs:
- ClinicoPathJamoviModule
- kappaSize
Notes:
option.name
must match a field in the R6 class (self$options$name
).refs:
section ensures citations appear in output.analysis-name
and class
fields must align with R6 class names..u.yaml
)Purpose: Organize controls, labels, and grouping for the user interface.
Pattern Example (meddecide/kappaSizeCI.u.yaml):
- type: label
title: "Kappa Sample Size"
text: "Calculate sample size for desired kappa precision."
footnote: "Based on Donner & Eliasziw (1992)."
- type: group
title: "Outcome Settings"
content:
- type: combobox
name: outcome
title: "Number of Outcome Levels"
values: $(options.outcome.values)
- type: textbox
name: props
title: "Category Proportions"
placeholder: "e.g., 0.20, 0.80"
- type: group
title: "Kappa Parameters"
content:
- type: textbox
name: kappa0
title: "Null Kappa (K0)"
- type: textbox
name: kappaL
title: "Lower Bound (KL)"
- type: textbox
name: kappaU
title: "Upper Bound (KU)"
- type: group
title: "Study Design"
content:
- type: spinner
name: raters
title: "Number of Raters"
min: 2
max: 10
- type: textbox
name: alpha
title: "Alpha (α)"
placeholder: "0.05"
Notes:
name
must match an option in .a.yaml
.combobox
, textbox
, spinner
, checkbox
, etc.)..r.yaml
)Purpose: Define output objects, rendering functions, visibility conditions, and dependencies.
Pattern Example (meddecide/kappaSizeCI.r.yaml):
refs:
- ClinicoPathJamoviModule
- kappaSize
output:
- name: text1
type: "preformatted"
title: "Required Sample Size"
clearWith: [outcome, kappa0, kappaL, kappaU, props, raters, alpha]
visible: true
- name: text2
type: "preformatted"
title: "Study Explanation"
clearWith: [outcome, kappa0, kappaL, kappaU, props, raters, alpha]
visible: true
Pattern Example (meddecide/decision.r.yaml):
refs:
- ClinicoPathJamoviModule
- epiR
- FaganNomogram
- pROC
output:
# Pre-populated Count Table
- name: cTable
type: table
title: "Test vs Gold Standard"
rows: 0
columns:
- name: newtest
type: text
title: "Test Result"
- name: GoldPos
type: number
title: "Gold Positive"
- name: GoldNeg
type: number
title: "Gold Negative"
- name: Total
type: number
title: "Total"
clearWith: [gold, newtest]
# Single-row summary
- name: nTable
type: table
title: "Basic Counts"
rows: 1
columns:
- name: TotalPop
type: integer
title: "Total Population"
- name: Diseased
type: integer
title: "Diseased"
- name: Healthy
type: integer
title: "Healthy"
- name: TP
type: integer
title: "True Positive"
- name: FP
type: integer
title: "False Positive"
- name: FN
type: integer
title: "False Negative"
- name: TN
type: integer
title: "True Negative"
clearWith: [gold, newtest]
# Ratio Table (Conditional on CI)
- name: epirTable_ratio
type: table
title: "Effect Estimates (Ratio)"
rows: 0
columns:
- name: statsnames
type: text
title: "Statistic"
- name: est
type: number
title: "Estimate"
- name: lower
type: number
title: "Lower 95% CI"
- name: upper
type: number
title: "Upper 95% CI"
visible: (ci)
clearWith: [gold, newtest, ci]
# Numeric Counts Table (Conditional)
- name: epirTable_number
type: table
title: "Effect Estimates (Numbers)"
rows: 0
columns:
- name: statsnames
type: text
title: "Statistic"
- name: value
type: integer
title: "Value"
visible: (ci)
clearWith: [gold, newtest, ci]
# Fagan Nomogram Plot
- name: plot1
type: image
title: "Fagan Nomogram"
renderFun: .plot1
width: 600
height: 450
visible: (fagan)
requiresData: true
clearWith: [gold, newtest, fagan]
# ROC Curve Plot
- name: plot2
type: image
title: "ROC Curve"
renderFun: .plot2
width: 600
height: 450
visible: (roc)
requiresData: true
clearWith: [gold, newtest, roc]
Key Points:
clearWith
: Lists options that invalidate the output when changed.visible
: Controls conditional display (e.g., (ci)
, (roc)
).renderFun
: Connects to private plot methods in the R6 class.jamovi-module.yml
): Must match analysis names and specify version and compatible jmvcore versions..b.R
)Each agent’s computation is implemented in an R6 class, inheriting from a generated base class (from .h.R
) that provides active bindings for all options
and results
. The .b.R
file extends this base and implements the analysis logic.
MyAnalysisClass
inherits from MyAnalysisBase
(auto-generated).if (requireNamespace("jmvcore", quietly = TRUE)) { ... }
ensures the Jamovi environment is present.Private List: Contains methods:
.init()
: Pre-configures results.
.run()
: Performs main computations..plot1()
, .plot2()
, etc.: Generates plots..prepareData()
, .computeMetrics()
, .buildTableRows()
.Example Skeleton:
kappaSizeCIClass <- R6::R6Class(
"kappaSizeCIClass",
inherit = kappaSizeCIBase,
private = list(
.init = function() {
# e.g., set initial visibility or pre-populate table rows
},
.run = function() {
# 1. Validate inputs
# 2. Access inputs: outcome <- self$options$outcome
# 3. Compute sample size via kappaSize package
# 4. text1 <- ...; text2 <- ...
# 5. Populate outputs:
# self$results$text1$setContent(text1)
# self$results$text2$setContent(text2)
},
.plot1 = function(image, ggtheme) {
# Retrieve data: plotData <- image$state
# Build ggplot object
# print(plot)
TRUE
}
)
)
.init
)cTable$addRow(rowKey = "Test Positive", values = list(newtest = "Test Positive"))
).self$results$myOutput$setVisible(FALSE)
based on initial conditions (e.g., no data loaded yet).Example (meddecide/decision.b.R):
.decisionClass.init <- function() {
# Pre-populate cTable with row labels
cTable <- self$results$cTable
cTable$addRow(rowKey = 1, values = list(newtest = "Test Positive"))
cTable$addRow(rowKey = 2, values = list(newtest = "Test Negative"))
cTable$addRow(rowKey = 3, values = list(newtest = "Total"))
}
.run
)r
outcome <- self$options$outcome
kappa0 <- self$options$kappa0
props <- self$options$props
raters <- self$options$raters
alpha <- self$options$alpha
Data Validation: Check self$data
or required options. If missing, display instructions via a “todo” output and return()
early.
Split, Convert, Compute: For string inputs (e.g., props
), split with strsplit()
and convert to numeric.
Call External Packages: E.g., kappaSize::CIBinary()
, epiR::epi.tests()
, survival::survfit()
, tableone::CreateTableOne()
.
Store Intermediate Results: For complex or heavy plots, store data in the image’s state:
r
plotData <- list(Sens = sens, Spec = spec)
self$results$plot1$setState(plotData)
* Populate Results:
self$results$text1$setContent(text1)
.self$results$irrtable$setRow(rowNo = 1, values = list(Method = "Kappa", Value = kappaVal))
.Table (dynamic rows):
r
df <- someDataFrame
for (i in seq_len(nrow(df))) {
self$results$myTable$addRow(rowKey = i, values = c(df[i, ]))
}
* Clear or Hide Instructions: After populating outputs, clear the “todo” message:
r
self$results$todo$setContent("")
.plotX
)r
plotData <- image$state
Construct Plot: Use ggplot2 or helper functions (e.g., nomogrammer(plotData$Prevalence, plotData$Sens, ...)
).
Apply Theme: Use ggtheme
or jmvcore::theme()
for consistency with Jamovi.
* Print Plot: print(p)
and return TRUE
.
Example (meddecide/decision.b.R):
.decisionClass.plot1 <- function(image, ggtheme) {
plotData <- image$state
p <- nomogrammer(
prevalence = plotData$Prevalence,
sens = plotData$Sens,
spec = plotData$Spec,
plr = plotData$Plr,
nlr = plotData$Nlr
) + ggtheme
print(p)
TRUE
}
Common helpers:
.prepareData()
: Subset data, rename variables, handle factor levels.
.computeMetrics()
: Calculate statistics (e.g., sensitivity, specificity, hazard ratios)..buildTableRows()
: Convert result objects into data frames ready for table insertion.Example (jsurvival/survival.b.R):
.survivalClass.getData <- function() {
data <- self$data
timeVar <- self$options$time
eventVar <- self$options$status
groupVar <- self$options$group
# Convert factor levels if needed
data[[eventVar]] <- as.numeric(data[[eventVar]] == "Yes")
# Return list of cleaned data and variable names
list(
data = data,
timeVar = timeVar,
eventVar = eventVar,
groupVar = groupVar
)
}
.survivalClass.run <- function() {
args <- private$.getData()
survObj <- survival::Surv(time = args$data[[args$timeVar]],
event = args$data[[args$eventVar]])
fit <- survival::survfit(survObj ~ args$data[[args$groupVar]], data = args$data)
# Populate KM plot state
self$results$survPlot$setState(list(fit = fit, data = args$data, group = args$groupVar))
# Other outputs: median survival table
medians <- summary(fit)$table
for (i in seq_along(medians)) {
self$results$medianTable$addRow(rowKey = i, values = list(
Group = medians$group[i],
Median = medians$median[i]
))
}
}
Context: Computes required sample size for an inter-rater agreement study.
.a.yaml
:
Defines options: outcome
, kappa0
, kappaL
, kappaU
, props
, raters
, alpha
.
Includes references: ClinicoPathJamoviModule
, kappaSize
.
.u.yaml
:
Groups: “Outcome Settings”, “Kappa Parameters”, “Study Design”.
Controls: ComboBox outcome
, TextBoxes kappa0
, kappaL
, kappaU
, Spinner raters
, TextBox alpha
.
.r.yaml
:
Outputs: text1
(Required Sample Size) and text2
(Study Explanation).
Properties: both visible: true
, clearWith: [all inputs]
.
kappaSizeCI.b.R
:
.init: (No pre-population needed).
.run:
outcome
, kappa0
, kappaL
, kappaU
, props
, raters
, alpha
.props
string to numeric vector: propsVec <- as.numeric(strsplit(props, ",")[[1]])
.outcome
: if "2"
, call kappaSize::CIBinary()
, else call kappaSize::CI3Cats()
, etc.text1 <- paste0("Required N = ", res$N)
; text2 <- paste0("To estimate kappa0 = ", kappa0, " with ...")
.self$results$text1$setContent(text1)
; self$results$text2$setContent(text2[1])
.Outcome: The module displays the computed sample size and an explanatory message illustrating parameter choices.
Context: Computes diagnostic test accuracy metrics, populates count tables, and renders plots (Fagan nomogram, ROC curve).
.a.yaml
:
Options: gold
, newtest
(both variables), ci
(checkbox), fagan
(checkbox), roc
(checkbox).
References: ClinicoPathJamoviModule
, epiR
, FaganNomogram
, pROC
.
.u.yaml
:
Controls grouped under “Data Selection” (variable pickers) and “Options” (checkboxes for CI, Fagan, ROC).
.r.yaml
:
cTable
: Pre-populated with 3 rows in .init
.
nTable
: Single-row summary.epirTable_ratio
: Ratio table (visible if ci
is true).epirTable_number
: Numeric counts table (visible if ci
is true).plot1
: Fagan nomogram (render function .plot1
, visible if fagan
is true).plot2
: ROC curve (render function .plot2
, visible if roc
is true).
decision.b.R
:
.init:
r
cTable <- self$results$cTable
cTable$addRow(rowKey = 1, values = list(newtest = "Test Positive"))
cTable$addRow(rowKey = 2, values = list(newtest = "Test Negative"))
cTable$addRow(rowKey = 3, values = list(newtest = "Total"))
.run:
gold
or newtest
is not selected, display a “todo” instruction and return.df <- self$data[, c(self$options$gold, self$options$newtest)]
.epiR::epi.tests()
.nTable
:r
self$results$nTable$setRow(
1,
values = list(
TotalPop = N,
Diseased = sum(...),
Healthy = sum(...),
TP = tp,
FP = fp,
FN = fn,
TN = tn
)
)
* Populate cTable
:
r
self$results$cTable$setRow(
rowNo = 1,
values = list(GoldPos = tp, GoldNeg = fp, Total = tp + fp)
)
# Similarly for rows 2 and 3
* If ci
is true, compute effect estimates:
r
epir_ratio_df <- epiR::epi.2by2(..., conf.level = 0.95)
for (i in seq_len(nrow(epir_ratio_df))) {
self$results$epirTable_ratio$addRow(rowKey = i, values = c(epir_ratio_df[i, ]))
}
# Repeat for epirTable_number
* If fagan
is true, compute Fagan nomogram parameters and store state:
r
plotData1 <- list(
Prevalence = prior,
Sens = sens,
Spec = spec,
Plr = plr,
Nlr = nlr
)
self$results$plot1$setState(plotData1)
* If roc
is true, compute ROC object and store:
r
rocObj <- pROC::roc(response = ..., predictor = ...)
self$results$plot2$setState(rocObj)
* Clear any “todo” instructions: self$results$todo$setContent("")
.
.plot1:
r
plotData <- image$state
p <- nomogrammer(
prevalence = plotData$Prevalence,
sens = plotData$Sens,
spec = plotData$Spec,
plr = plotData$Plr,
nlr = plotData$Nlr
) + ggtheme
print(p)
TRUE
.plot2:
r
rocObj <- image$state
p <- ggroc(rocObj) + ggtheme + ggtitle("ROC Curve")
print(p)
TRUE
Context: Generates a descriptive summary table (“Table One”) in multiple formats: tableone, gtsummary, arsenal, or janitor.
.a.yaml
(excerpt):```yaml options: - name: vars type: variable-list title: "Variables to Summarize"
- name: excl
type: boolean
default: false
title: "Exclude Missing Values"
- name: sty
type: list
values: ["t1", "t2", "t3", "t4"]
default: "t1"
title: "Table Style"
refs: - ClinicoPathJamoviModule - tableone - gtsummary - arsenal - janitor ```
.u.yaml
(excerpt):```yaml - type: label title: "Table One" text: "Generate descriptive statistics for selected variables."
type: variables name: vars title: "Select Variables (up to 10)"
type: checkbox name: excl title: "Exclude Missing Values"
type: combobox name: sty title: "Table Style" values: ["t1", "t2", "t3", "t4"] display: ["TableOne", "gtSummary", "Arsenal", "Janitor"] ```
.r.yaml
:
```yaml refs: - ClinicoPathJamoviModule - tableone - gtsummary - arsenal - janitor
output: - name: todo type: html title: "Instructions" visible: (vars:empty)
- name: tablestyle1
type: preformatted
title: "TableOne Output"
visible: (sty:t1)
clearWith: [vars, excl]
- name: tablestyle2
type: html
title: "gtSummary Output"
visible: (sty:t2)
clearWith: [vars, excl]
- name: tablestyle3
type: html
title: "Arsenal Output"
visible: (sty:t3)
clearWith: [vars, excl]
- name: tablestyle4
type: html
title: "Janitor Output"
visible: (sty:t4)
clearWith: [vars, excl]
```
tableone.b.R
:
.run:
```r if (is.null(self$options$vars) || length(self$options$vars) == 0) { todo_msg <- "
self$results$todo$setContent("")
data <- self$data[, self$options$vars, drop = FALSE] if (self$options$excl) data <- jmvcore::naOmit(data)
style <- self$options$sty if (style == "t1") { tbl <- tableone::CreateTableOne(vars = self$options$vars, data = data) self$results$tablestyle1$setContent(tbl) } else if (style == "t2") { tbl <- gtsummary::tbl_summary(data = data) htmlTbl <- gtsummary::as_kable_extra(tbl) self$results$tablestyle2$setContent(htmlTbl) } else if (style == "t3") { tbl <- arsenal::tableby(~ ., data = data) htmlTbl <- arsenal::summary.tbl(by = tbl, text = FALSE) self$results$tablestyle3$setContent(htmlTbl) } else if (style == "t4") { df <- janitor::tabyl(data) htmlTbl <- knitr::kable(df, format = "html") self$results$tablestyle4$setContent(htmlTbl) } ```
Notes:
todo
output informs users until they select variables.visible: (sty:tx)
).Consistent Naming and Inheritance
R6 classes: AnalysisClass
inherits from AnalysisBase
.
Base classes auto-generated from YAML provide self$options
and self$results
.
Option Access and Types
Access inputs with self$options$varName
(matching .a.yaml
).
Immediately assign to local variables and apply transformations (e.g., as.integer
, as.numeric
, strsplit
).
Result Access and Modification
Text outputs: self$results$name$setContent(value)
.
self$results$name$setRow(rowNo, values = list(...))
.self$results$name$addRow(rowKey, values = c(...))
.self$results$name$setState(list(...))
.Visibility overrides: self$results$name$setVisible(TRUE/FALSE)
.
UI Guidance via Outputs
Use a todo
HTML output to guide users when required inputs are missing.
Clear the message once inputs are valid: self$results$todo$setContent("")
.
ClearWith and Dependencies
List all relevant options in clearWith
to prevent stale outputs.
For images or tables depending on multiple inputs (e.g., gold
, newtest
, ci
), include all in clearWith
.
Visible Conditions
Use visible: (option)
or visible: (option:value)
in .r.yaml
to control output display.
(ci)
, (fagan)
, (roc)
, (sty:t1)
, (vars:empty)
.Keeps the interface uncluttered by showing only relevant outputs.
Citing Sources
Add external references in refs:
under .a.yaml
or .r.yaml
.
Ensure proper attribution for statistical methods (e.g., epiR
, survival
, kappaSize
, gtsummary
).
Coding Style and Comments
Use comment headers (e.g., # ----
) to separate logical sections (data prep, error handling, computations, output).
Adhere to a consistent code style (tidyverse or base R) as per project guidelines.
Private Helper Functions
Encapsulate reusable logic in private methods (private$.functionName()
).
Examples: .getData()
, .computeMetrics()
, .preparePlotData()
, .buildTableRows()
.
Storage of Plot Data
image$setState()
in .run
to store data for plotting..plotX()
methods to retrieve and visualize image$state
.New Feature: Add Decision Curve Analysis to meddecide
Use YAMLConfigAgent
to draft the UI (.u.yaml
) for computeDecisionCurve
, defining inputs: data
, outcome
, predicted_prob
, threshold_seq
, plotROC
.
RFunctionGenAgent
to implement computeDecisionCurve
in R/decision_curve.R
: validate inputs, calculate net benefit at each threshold, return a jmvcore::Table
and a Plot
.PlotDesignAgent
to generate a net benefit vs. threshold plot with ggplot2
, matching Jamovi’s style.TestQAAgent
to write tests for net benefit computation (using a toy dataset with known expected values).DocumentationAgent
to add roxygen2 comments and update .r.yaml
and .a.yaml
accordingly.CIIntegrationAgent
to ensure tests run on CI/CD and update the GitHub Actions workflow as needed.Use ReleaseManagerAgent
to draft release notes for the new function.
Bug Fix: Handle Single-Level Group Error in jsurvival
Provide the error message and relevant code snippet to BugTrackerAgent
.
BugTrackerAgent
diagnoses the issue (single-level grouping) and proposes a guard clause.RefactorAgent
to insert the guard clause, handle the edge case gracefully, and refactor code for clarity.TestQAAgent
to write a test ensuring the edge case no longer errors.DocumentationAgent
to update help text: note that grouping variables must have at least two levels, or else return a descriptive message.jmvcore Basics:
requirePackage()
to ensure dependencies.
jmvcore::Options
subclasses to collect user options.jmvcore::Analysis
subclasses that define init()
, run()
, and results
.Use jmvcore::preprocessData()
, jmvcore::table()
, and jmvcore::plot()
for standard functionality.
YAML File Structure:
.u.yaml
: Defines UI elements. Example:
yaml
- type: choices
name: group
label: "Grouping Variable"
options:
- var1
- var2
- type: integer
name: alpha
label: "Significance Level"
default: 0.05
* .r.yaml
: Maps UI options to R function parameters. Example:
yaml
- function-name: computeSurvival
parameters:
group: group
time: time_col
status: status_col
* .a.yaml
: Registers analyses. Example:
yaml
- analysis-name: SurvivalAnalysis
class: AnalysisClass
package: jsurvival
requires-data: true
allows-multiple-dependencies: false
title: "Survival Analysis"
Testing Conventions:
Place tests in tests/testthat/
.
test-<function>.R
.Example structure:
r
test_that("computeSurvival handles single-group edge case", {
data <- data.frame(time = c(1,2,3), status = c(1,0,1), group = c('A','A','A'))
expect_error(computeSurvival(data), "group must have at least two levels")
})
Plot Export:
Jamovi expects plots returned via jmvcore::Image$new()
with a render()
method that returns a ggplot
object or grid.
Example:
r
results$plot <- jmvcore::Image$new(
plot = function() {
p <- ggplot(data, aes(x = ..., y = ...)) + geom_line()
return(p)
},
width = 400,
height = 300
)
This AGENTS.md
file is versioned at v1.0.2. Future updates should follow semantic versioning, reflecting changes to agent responsibilities, new agents, or prompt guidelines.
End of AGENTS.md
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.