{
  "IssueTestMatrix": [
    {
      "Milestone": "v1.0.0",
      "Issue": 40,
      "Title": "Sync to safety.viz v1.2.0 and add Widget_HepExplorer (eDISH)",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 21:40 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: jwildfire -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Unblocked by the safety.viz v1.2.0 release (hepExplorer shipped via safety.viz PR #44)\n\n## Summary\n\nSync gsm.safety to safety.viz v1.2.0: upgrade the vendored bundle and add `Widget_HepExplorer`, the eDISH hepatic-safety explorer htmlwidget — the seventh renderer, completing parity with the released safety.viz module set.\n\n## Proposed Solution\n\n- Re-vendor the bundle at `inst/htmlwidgets/lib/safety.viz-1.2.0/` (the six existing `Widget_*.yaml` dependency blocks move to the new path/version; the v1.1.0 module APIs are unchanged in v1.2.0).\n- `Widget_HepExplorer()` R function + `inst/htmlwidgets/Widget_HepExplorer.js`/`.yaml` on the established pattern: `BuildWidgetPayload()` validation against the vendored `hep-explorer.json` data contract, module lifecycle driven from `renderValue`/`resize`.\n- Report workflow `inst/workflow/3_reports/hep_explorer.yaml`, runner `inst/examples/hep-explorer.R`, pkgdown example page, and qcthat-linked tests, mirroring the other six lanes.\n- Example settings follow the safety.viz demo: `measure_values` mapped to the dataset's liver-measure TEST strings (ALT/AST/TB/ALP) and `studyday_col = \"VISITNUM\"` standing in for study day.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue in the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example + evidence pages published as RC evidence\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/40",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-13",
      "Assignees": ["jwildfire"],
      "Test": "Widget_HepExplorer returns an htmlwidget carrying the hep-explorer payload (#40)",
      "File": "test-hep-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 40,
      "Title": "Sync to safety.viz v1.2.0 and add Widget_HepExplorer (eDISH)",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 21:40 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: jwildfire -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Unblocked by the safety.viz v1.2.0 release (hepExplorer shipped via safety.viz PR #44)\n\n## Summary\n\nSync gsm.safety to safety.viz v1.2.0: upgrade the vendored bundle and add `Widget_HepExplorer`, the eDISH hepatic-safety explorer htmlwidget — the seventh renderer, completing parity with the released safety.viz module set.\n\n## Proposed Solution\n\n- Re-vendor the bundle at `inst/htmlwidgets/lib/safety.viz-1.2.0/` (the six existing `Widget_*.yaml` dependency blocks move to the new path/version; the v1.1.0 module APIs are unchanged in v1.2.0).\n- `Widget_HepExplorer()` R function + `inst/htmlwidgets/Widget_HepExplorer.js`/`.yaml` on the established pattern: `BuildWidgetPayload()` validation against the vendored `hep-explorer.json` data contract, module lifecycle driven from `renderValue`/`resize`.\n- Report workflow `inst/workflow/3_reports/hep_explorer.yaml`, runner `inst/examples/hep-explorer.R`, pkgdown example page, and qcthat-linked tests, mirroring the other six lanes.\n- Example settings follow the safety.viz demo: `measure_values` mapped to the dataset's liver-measure TEST strings (ALT/AST/TB/ALP) and `studyday_col = \"VISITNUM\"` standing in for study day.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue in the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example + evidence pages published as RC evidence\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/40",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-13",
      "Assignees": ["jwildfire"],
      "Test": "Widget_HepExplorer passes width, height, and elementId through (#40)",
      "File": "test-hep-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 40,
      "Title": "Sync to safety.viz v1.2.0 and add Widget_HepExplorer (eDISH)",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 21:40 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: jwildfire -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Unblocked by the safety.viz v1.2.0 release (hepExplorer shipped via safety.viz PR #44)\n\n## Summary\n\nSync gsm.safety to safety.viz v1.2.0: upgrade the vendored bundle and add `Widget_HepExplorer`, the eDISH hepatic-safety explorer htmlwidget — the seventh renderer, completing parity with the released safety.viz module set.\n\n## Proposed Solution\n\n- Re-vendor the bundle at `inst/htmlwidgets/lib/safety.viz-1.2.0/` (the six existing `Widget_*.yaml` dependency blocks move to the new path/version; the v1.1.0 module APIs are unchanged in v1.2.0).\n- `Widget_HepExplorer()` R function + `inst/htmlwidgets/Widget_HepExplorer.js`/`.yaml` on the established pattern: `BuildWidgetPayload()` validation against the vendored `hep-explorer.json` data contract, module lifecycle driven from `renderValue`/`resize`.\n- Report workflow `inst/workflow/3_reports/hep_explorer.yaml`, runner `inst/examples/hep-explorer.R`, pkgdown example page, and qcthat-linked tests, mirroring the other six lanes.\n- Example settings follow the safety.viz demo: `measure_values` mapped to the dataset's liver-measure TEST strings (ALT/AST/TB/ALP) and `studyday_col = \"VISITNUM\"` standing in for study day.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue in the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example + evidence pages published as RC evidence\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/40",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-13",
      "Assignees": ["jwildfire"],
      "Test": "Widget_HepExplorer rejects invalid inputs via the hep-explorer contract (#40)",
      "File": "test-hep-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 40,
      "Title": "Sync to safety.viz v1.2.0 and add Widget_HepExplorer (eDISH)",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 21:40 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: jwildfire -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Unblocked by the safety.viz v1.2.0 release (hepExplorer shipped via safety.viz PR #44)\n\n## Summary\n\nSync gsm.safety to safety.viz v1.2.0: upgrade the vendored bundle and add `Widget_HepExplorer`, the eDISH hepatic-safety explorer htmlwidget — the seventh renderer, completing parity with the released safety.viz module set.\n\n## Proposed Solution\n\n- Re-vendor the bundle at `inst/htmlwidgets/lib/safety.viz-1.2.0/` (the six existing `Widget_*.yaml` dependency blocks move to the new path/version; the v1.1.0 module APIs are unchanged in v1.2.0).\n- `Widget_HepExplorer()` R function + `inst/htmlwidgets/Widget_HepExplorer.js`/`.yaml` on the established pattern: `BuildWidgetPayload()` validation against the vendored `hep-explorer.json` data contract, module lifecycle driven from `renderValue`/`resize`.\n- Report workflow `inst/workflow/3_reports/hep_explorer.yaml`, runner `inst/examples/hep-explorer.R`, pkgdown example page, and qcthat-linked tests, mirroring the other six lanes.\n- Example settings follow the safety.viz demo: `measure_values` mapped to the dataset's liver-measure TEST strings (ALT/AST/TB/ALP) and `studyday_col = \"VISITNUM\"` standing in for study day.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue in the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example + evidence pages published as RC evidence\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/40",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-13",
      "Assignees": ["jwildfire"],
      "Test": "Widget_HepExplorer renders standalone HTML with the SafetyViz bundle and data (#40)",
      "File": "test-hep-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 40,
      "Title": "Sync to safety.viz v1.2.0 and add Widget_HepExplorer (eDISH)",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 21:40 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: jwildfire -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Unblocked by the safety.viz v1.2.0 release (hepExplorer shipped via safety.viz PR #44)\n\n## Summary\n\nSync gsm.safety to safety.viz v1.2.0: upgrade the vendored bundle and add `Widget_HepExplorer`, the eDISH hepatic-safety explorer htmlwidget — the seventh renderer, completing parity with the released safety.viz module set.\n\n## Proposed Solution\n\n- Re-vendor the bundle at `inst/htmlwidgets/lib/safety.viz-1.2.0/` (the six existing `Widget_*.yaml` dependency blocks move to the new path/version; the v1.1.0 module APIs are unchanged in v1.2.0).\n- `Widget_HepExplorer()` R function + `inst/htmlwidgets/Widget_HepExplorer.js`/`.yaml` on the established pattern: `BuildWidgetPayload()` validation against the vendored `hep-explorer.json` data contract, module lifecycle driven from `renderValue`/`resize`.\n- Report workflow `inst/workflow/3_reports/hep_explorer.yaml`, runner `inst/examples/hep-explorer.R`, pkgdown example page, and qcthat-linked tests, mirroring the other six lanes.\n- Example settings follow the safety.viz demo: `measure_values` mapped to the dataset's liver-measure TEST strings (ALT/AST/TB/ALP) and `studyday_col = \"VISITNUM\"` standing in for study day.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue in the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example + evidence pages published as RC evidence\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/40",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-13",
      "Assignees": ["jwildfire"],
      "Test": "hep_explorer workflow renders an HTML report from ExampleData (#40, #38)",
      "File": "test-hep-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_delta_delta workflow renders an HTML report from ExampleData (#33, #38)",
      "File": "test-delta-delta.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "hep_explorer workflow renders an HTML report from ExampleData (#40, #38)",
      "File": "test-hep-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_outlier_explorer workflow renders an HTML report from ExampleData (#35, #38)",
      "File": "test-outlier-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "every widget ships its htmlwidgets binding, dependency yaml, schema, and report workflow (#31, #38)",
      "File": "test-package.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_results_over_time workflow renders an HTML report from ExampleData (#34, #38)",
      "File": "test-results-over-time.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_shift_plot workflow renders an HTML report from ExampleData (#32, #38)",
      "File": "test-shift-plot.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "ae_timelines workflow renders an HTML report from ExampleData (#36, #38)",
      "File": "test-workflow-ae-timelines.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 38,
      "Title": "Modernize report workflows to the Widget_* renderers",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the six Widget_* sub-issues\n\n## Summary\n\nModernize the report workflows: rewrite the `inst/workflow/3_reports/` scaffolds against the new `Widget_*()` renderers so each safety.viz chart has a runnable gsm-idiom workflow, and retire the safetyCharts-era scaffolds.\n\n## Proposed Solution\n\n- One report workflow YAML per shipped renderer (histogram, shift plot, delta-delta, results over time, outlier explorer, AE timelines) following the gsm `meta`/`spec`/`steps` idiom, ending in a `Widget_X()` + `htmlwidgets::saveWidget()` render step.\n- Runnable via `gsm.core::RunWorkflow()` against the vendored demo extracts; a runnable script per workflow lands in `inst/examples/`.\n- The `ae_explorer`/`hep_explorer` safetyCharts scaffolds are removed (hepExplorer returns as a widget when safety.viz ships it — tracked as safety.viz PR #44).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/38",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_histogram workflow renders an HTML report from ExampleData (#30, #38)",
      "File": "test-workflow-safety-histogram.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 37,
      "Title": "Ship canonical pharmaverseadam demo data (adbds/adae) for examples and QC",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Data per hub #25 (canonical pharmaverseadam demo data)\n\n## Summary\n\nShip the canonical pharmaverseadam-derived demo extracts (`adbds`, `adae`) as gsm.safety package data, so widget examples, workflows, tests, and QC fixtures exercise identical inputs on both sides of the R/JS boundary.\n\n## Proposed Solution\n\n- `inst/extdata/adbds.csv` + `inst/extdata/adae.csv` vendored byte-identical from safety.viz v1.1.0 `site/data/` (the extracts the JS demos render).\n- Exported accessor — e.g. `ExampleData(\"adbds\")` — returning the parsed data.frame, used by every roxygen `@examples`, report workflow, and qcthat-linked test.\n- No package-level dependency on pharmaverseadam itself; the extracts are static per hub #25.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/37",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "ExampleData reads the adbds example data with sensible types (#37)",
      "File": "test-ExampleData.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 37,
      "Title": "Ship canonical pharmaverseadam demo data (adbds/adae) for examples and QC",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Data per hub #25 (canonical pharmaverseadam demo data)\n\n## Summary\n\nShip the canonical pharmaverseadam-derived demo extracts (`adbds`, `adae`) as gsm.safety package data, so widget examples, workflows, tests, and QC fixtures exercise identical inputs on both sides of the R/JS boundary.\n\n## Proposed Solution\n\n- `inst/extdata/adbds.csv` + `inst/extdata/adae.csv` vendored byte-identical from safety.viz v1.1.0 `site/data/` (the extracts the JS demos render).\n- Exported accessor — e.g. `ExampleData(\"adbds\")` — returning the parsed data.frame, used by every roxygen `@examples`, report workflow, and qcthat-linked test.\n- No package-level dependency on pharmaverseadam itself; the extracts are static per hub #25.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/37",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "ExampleData reads the adae example data with sensible types (#37)",
      "File": "test-ExampleData.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 37,
      "Title": "Ship canonical pharmaverseadam demo data (adbds/adae) for examples and QC",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Data per hub #25 (canonical pharmaverseadam demo data)\n\n## Summary\n\nShip the canonical pharmaverseadam-derived demo extracts (`adbds`, `adae`) as gsm.safety package data, so widget examples, workflows, tests, and QC fixtures exercise identical inputs on both sides of the R/JS boundary.\n\n## Proposed Solution\n\n- `inst/extdata/adbds.csv` + `inst/extdata/adae.csv` vendored byte-identical from safety.viz v1.1.0 `site/data/` (the extracts the JS demos render).\n- Exported accessor — e.g. `ExampleData(\"adbds\")` — returning the parsed data.frame, used by every roxygen `@examples`, report workflow, and qcthat-linked test.\n- No package-level dependency on pharmaverseadam itself; the extracts are static per hub #25.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/37",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "ExampleData converts blank numeric fields to NA without warnings (#37)",
      "File": "test-ExampleData.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 37,
      "Title": "Ship canonical pharmaverseadam demo data (adbds/adae) for examples and QC",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Data per hub #25 (canonical pharmaverseadam demo data)\n\n## Summary\n\nShip the canonical pharmaverseadam-derived demo extracts (`adbds`, `adae`) as gsm.safety package data, so widget examples, workflows, tests, and QC fixtures exercise identical inputs on both sides of the R/JS boundary.\n\n## Proposed Solution\n\n- `inst/extdata/adbds.csv` + `inst/extdata/adae.csv` vendored byte-identical from safety.viz v1.1.0 `site/data/` (the extracts the JS demos render).\n- Exported accessor — e.g. `ExampleData(\"adbds\")` — returning the parsed data.frame, used by every roxygen `@examples`, report workflow, and qcthat-linked test.\n- No package-level dependency on pharmaverseadam itself; the extracts are static per hub #25.\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/37",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "ExampleData defaults to adbds and rejects unknown datasets (#37)",
      "File": "test-ExampleData.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 36,
      "Title": "Add Widget_AeTimelines htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_AeTimelines`, an interactive per-participant adverse event timeline, rendered by the safety.viz `aeTimelines` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_AeTimelines.js` + `Widget_AeTimelines.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_AeTimelines()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/ae-timelines.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adae`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_AeTimelines(\n  dfResults = ExampleData(\"adae\"),\n  lSettings = list(\n    # settings keys per the ae-timelines data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/36",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_AeTimelines returns an htmlwidget carrying the ae-timelines payload (#36)",
      "File": "test-Widget_AeTimelines.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 36,
      "Title": "Add Widget_AeTimelines htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_AeTimelines`, an interactive per-participant adverse event timeline, rendered by the safety.viz `aeTimelines` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_AeTimelines.js` + `Widget_AeTimelines.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_AeTimelines()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/ae-timelines.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adae`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_AeTimelines(\n  dfResults = ExampleData(\"adae\"),\n  lSettings = list(\n    # settings keys per the ae-timelines data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/36",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_AeTimelines passes width, height, and elementId through (#36)",
      "File": "test-Widget_AeTimelines.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 36,
      "Title": "Add Widget_AeTimelines htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_AeTimelines`, an interactive per-participant adverse event timeline, rendered by the safety.viz `aeTimelines` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_AeTimelines.js` + `Widget_AeTimelines.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_AeTimelines()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/ae-timelines.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adae`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_AeTimelines(\n  dfResults = ExampleData(\"adae\"),\n  lSettings = list(\n    # settings keys per the ae-timelines data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/36",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_AeTimelines rejects invalid inputs via the ae-timelines contract (#36)",
      "File": "test-Widget_AeTimelines.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 36,
      "Title": "Add Widget_AeTimelines htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_AeTimelines`, an interactive per-participant adverse event timeline, rendered by the safety.viz `aeTimelines` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_AeTimelines.js` + `Widget_AeTimelines.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_AeTimelines()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/ae-timelines.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adae`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_AeTimelines(\n  dfResults = ExampleData(\"adae\"),\n  lSettings = list(\n    # settings keys per the ae-timelines data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/36",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_AeTimelines renders standalone HTML with the SafetyViz bundle and data (#36)",
      "File": "test-Widget_AeTimelines.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 36,
      "Title": "Add Widget_AeTimelines htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_AeTimelines`, an interactive per-participant adverse event timeline, rendered by the safety.viz `aeTimelines` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_AeTimelines.js` + `Widget_AeTimelines.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_AeTimelines()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/ae-timelines.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adae`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_AeTimelines(\n  dfResults = ExampleData(\"adae\"),\n  lSettings = list(\n    # settings keys per the ae-timelines data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/36",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "ae_timelines workflow renders an HTML report from ExampleData (#36, #38)",
      "File": "test-workflow-ae-timelines.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 35,
      "Title": "Add Widget_OutlierExplorer htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_OutlierExplorer`, an interactive participant-level outlier explorer for safety results, rendered by the safety.viz `outlierExplorer` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_OutlierExplorer.js` + `Widget_OutlierExplorer.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_OutlierExplorer()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/outlier-explorer.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_OutlierExplorer(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the outlier-explorer data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/35",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_OutlierExplorer returns an htmlwidget carrying the outlier-explorer payload (#35)",
      "File": "test-outlier-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 35,
      "Title": "Add Widget_OutlierExplorer htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_OutlierExplorer`, an interactive participant-level outlier explorer for safety results, rendered by the safety.viz `outlierExplorer` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_OutlierExplorer.js` + `Widget_OutlierExplorer.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_OutlierExplorer()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/outlier-explorer.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_OutlierExplorer(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the outlier-explorer data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/35",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_OutlierExplorer passes width, height, and elementId through (#35)",
      "File": "test-outlier-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 35,
      "Title": "Add Widget_OutlierExplorer htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_OutlierExplorer`, an interactive participant-level outlier explorer for safety results, rendered by the safety.viz `outlierExplorer` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_OutlierExplorer.js` + `Widget_OutlierExplorer.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_OutlierExplorer()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/outlier-explorer.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_OutlierExplorer(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the outlier-explorer data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/35",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_OutlierExplorer rejects invalid inputs via the outlier-explorer contract (#35)",
      "File": "test-outlier-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 35,
      "Title": "Add Widget_OutlierExplorer htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_OutlierExplorer`, an interactive participant-level outlier explorer for safety results, rendered by the safety.viz `outlierExplorer` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_OutlierExplorer.js` + `Widget_OutlierExplorer.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_OutlierExplorer()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/outlier-explorer.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_OutlierExplorer(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the outlier-explorer data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/35",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_OutlierExplorer renders standalone HTML with the SafetyViz bundle and data (#35)",
      "File": "test-outlier-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 35,
      "Title": "Add Widget_OutlierExplorer htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_OutlierExplorer`, an interactive participant-level outlier explorer for safety results, rendered by the safety.viz `outlierExplorer` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_OutlierExplorer.js` + `Widget_OutlierExplorer.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_OutlierExplorer()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/outlier-explorer.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_OutlierExplorer(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the outlier-explorer data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/35",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_outlier_explorer workflow renders an HTML report from ExampleData (#35, #38)",
      "File": "test-outlier-explorer.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 34,
      "Title": "Add Widget_ResultsOverTime htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ResultsOverTime`, an interactive longitudinal view of safety results by visit, rendered by the safety.viz `resultsOverTime` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ResultsOverTime.js` + `Widget_ResultsOverTime.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ResultsOverTime()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/results-over-time.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ResultsOverTime(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the results-over-time data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/34",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ResultsOverTime returns an htmlwidget carrying the payload (#34)",
      "File": "test-results-over-time.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 34,
      "Title": "Add Widget_ResultsOverTime htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ResultsOverTime`, an interactive longitudinal view of safety results by visit, rendered by the safety.viz `resultsOverTime` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ResultsOverTime.js` + `Widget_ResultsOverTime.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ResultsOverTime()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/results-over-time.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ResultsOverTime(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the results-over-time data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/34",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ResultsOverTime passes width, height, and elementId through (#34)",
      "File": "test-results-over-time.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 34,
      "Title": "Add Widget_ResultsOverTime htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ResultsOverTime`, an interactive longitudinal view of safety results by visit, rendered by the safety.viz `resultsOverTime` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ResultsOverTime.js` + `Widget_ResultsOverTime.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ResultsOverTime()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/results-over-time.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ResultsOverTime(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the results-over-time data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/34",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ResultsOverTime rejects invalid inputs via the results-over-time contract (#34)",
      "File": "test-results-over-time.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 34,
      "Title": "Add Widget_ResultsOverTime htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ResultsOverTime`, an interactive longitudinal view of safety results by visit, rendered by the safety.viz `resultsOverTime` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ResultsOverTime.js` + `Widget_ResultsOverTime.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ResultsOverTime()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/results-over-time.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ResultsOverTime(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the results-over-time data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/34",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ResultsOverTime renders standalone HTML with the SafetyViz bundle and data (#34)",
      "File": "test-results-over-time.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 34,
      "Title": "Add Widget_ResultsOverTime htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ResultsOverTime`, an interactive longitudinal view of safety results by visit, rendered by the safety.viz `resultsOverTime` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ResultsOverTime.js` + `Widget_ResultsOverTime.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ResultsOverTime()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/results-over-time.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ResultsOverTime(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the results-over-time data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/34",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_results_over_time workflow renders an HTML report from ExampleData (#34, #38)",
      "File": "test-results-over-time.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 33,
      "Title": "Add Widget_DeltaDelta htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_DeltaDelta`, an interactive delta-delta view comparing per-participant change across two measures, rendered by the safety.viz `deltaDelta` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_DeltaDelta.js` + `Widget_DeltaDelta.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_DeltaDelta()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/delta-delta.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_DeltaDelta(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the delta-delta data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/33",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_DeltaDelta returns an htmlwidget carrying the delta-delta payload (#33)",
      "File": "test-delta-delta.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 33,
      "Title": "Add Widget_DeltaDelta htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_DeltaDelta`, an interactive delta-delta view comparing per-participant change across two measures, rendered by the safety.viz `deltaDelta` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_DeltaDelta.js` + `Widget_DeltaDelta.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_DeltaDelta()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/delta-delta.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_DeltaDelta(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the delta-delta data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/33",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_DeltaDelta passes width, height, and elementId through (#33)",
      "File": "test-delta-delta.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 33,
      "Title": "Add Widget_DeltaDelta htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_DeltaDelta`, an interactive delta-delta view comparing per-participant change across two measures, rendered by the safety.viz `deltaDelta` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_DeltaDelta.js` + `Widget_DeltaDelta.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_DeltaDelta()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/delta-delta.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_DeltaDelta(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the delta-delta data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/33",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_DeltaDelta rejects invalid inputs via the delta-delta contract (#33)",
      "File": "test-delta-delta.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 33,
      "Title": "Add Widget_DeltaDelta htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_DeltaDelta`, an interactive delta-delta view comparing per-participant change across two measures, rendered by the safety.viz `deltaDelta` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_DeltaDelta.js` + `Widget_DeltaDelta.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_DeltaDelta()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/delta-delta.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_DeltaDelta(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the delta-delta data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/33",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_DeltaDelta renders standalone HTML with the SafetyViz bundle and data (#33)",
      "File": "test-delta-delta.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 33,
      "Title": "Add Widget_DeltaDelta htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_DeltaDelta`, an interactive delta-delta view comparing per-participant change across two measures, rendered by the safety.viz `deltaDelta` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_DeltaDelta.js` + `Widget_DeltaDelta.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_DeltaDelta()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/delta-delta.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_DeltaDelta(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the delta-delta data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/33",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_delta_delta workflow renders an HTML report from ExampleData (#33, #38)",
      "File": "test-delta-delta.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 32,
      "Title": "Add Widget_ShiftPlot htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ShiftPlot`, an interactive baseline-versus-comparison shift view of safety results with linked participant detail, rendered by the safety.viz `shiftPlot` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ShiftPlot.js` + `Widget_ShiftPlot.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ShiftPlot()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/shift-plot.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ShiftPlot(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the shift-plot data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/32",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ShiftPlot returns an htmlwidget carrying the shift-plot payload (#32)",
      "File": "test-shift-plot.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 32,
      "Title": "Add Widget_ShiftPlot htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ShiftPlot`, an interactive baseline-versus-comparison shift view of safety results with linked participant detail, rendered by the safety.viz `shiftPlot` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ShiftPlot.js` + `Widget_ShiftPlot.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ShiftPlot()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/shift-plot.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ShiftPlot(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the shift-plot data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/32",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ShiftPlot passes width, height, and elementId through (#32)",
      "File": "test-shift-plot.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 32,
      "Title": "Add Widget_ShiftPlot htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ShiftPlot`, an interactive baseline-versus-comparison shift view of safety results with linked participant detail, rendered by the safety.viz `shiftPlot` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ShiftPlot.js` + `Widget_ShiftPlot.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ShiftPlot()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/shift-plot.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ShiftPlot(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the shift-plot data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/32",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ShiftPlot rejects invalid inputs via the shift-plot contract (#32)",
      "File": "test-shift-plot.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 32,
      "Title": "Add Widget_ShiftPlot htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ShiftPlot`, an interactive baseline-versus-comparison shift view of safety results with linked participant detail, rendered by the safety.viz `shiftPlot` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ShiftPlot.js` + `Widget_ShiftPlot.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ShiftPlot()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/shift-plot.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ShiftPlot(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the shift-plot data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/32",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "Widget_ShiftPlot renders standalone HTML with the SafetyViz bundle and data (#32)",
      "File": "test-shift-plot.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 32,
      "Title": "Add Widget_ShiftPlot htmlwidget consuming the safety.viz bundle",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement · Depends on the vendored safety.viz v1.1.0 bundle (bundle/infrastructure sub-issue)\n\n## Summary\n\nAdd `Widget_ShiftPlot`, an interactive baseline-versus-comparison shift view of safety results with linked participant detail, rendered by the safety.viz `shiftPlot` module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_ShiftPlot.js` + `Widget_ShiftPlot.yaml` on the vendored `inst/htmlwidgets/lib/safety.viz-1.1.0/` bundle (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_ShiftPlot()` R function maps a long data.frame plus a settings list onto the module's JSON data contract (`src/data/schema/shift-plot.json` in safety.viz), then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n- Roxygen `@examples` and the matching report workflow use the canonical pharmaverseadam demo extract (`adbds`) vendored with the package.\n\n## Example Usage\n\n```r\nWidget_ShiftPlot(\n  dfResults = ExampleData(\"adbds\"),\n  lSettings = list(\n    # settings keys per the shift-plot data contract\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/32",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "safety_shift_plot workflow renders an HTML report from ExampleData (#32, #38)",
      "File": "test-shift-plot.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "package metadata is available (#31)",
      "File": "test-package.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "gsm.safety exports the seven safety.viz widgets plus data and report helpers (#31)",
      "File": "test-package.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "every widget ships its htmlwidgets binding, dependency yaml, schema, and report workflow (#31, #38)",
      "File": "test-package.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "the legacy safetyCharts bridge is fully retired (#31)",
      "File": "test-package.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "BuildWidgetPayload returns the htmlwidget x payload for valid input (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "BuildWidgetPayload serializes empty settings as a JSON object (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "BuildWidgetPayload errors when a schema-default column is missing (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "BuildWidgetPayload errors when a settings override names a missing column (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "BuildWidgetPayload checks nested object settings like ae-timelines color (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "BuildWidgetPayload validates its inputs (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "SaveWidgetReport writes a self-contained HTML report and returns its path (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 31,
      "Title": "Vendor the safety.viz v1.1.0 bundle and shared htmlwidget infrastructure",
      "Body": "<!-- STATUS: Drafted on 2026-07-12 18:20 EDT -->\n<!-- GITHUB_PROPERTIES: Milestone: v1.0.0, Labels: enhancement, Assignee: @me -->\n\nParent: jwildfire/obot.roadmap#28 · Design: inline Design section on the parent requirement\n\n## Summary\n\nVendor the safety.viz v1.1.0 `dist/` bundle into gsm.safety and stand up the shared htmlwidget infrastructure all six `Widget_*()` bindings build on; retire the legacy safetyCharts/Tendril bridge in the same move.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/lib/safety.viz-1.1.0/safety.viz.js` vendored byte-identical from the safety.viz v1.1.0 release bundle, pinned by version-suffixed directory (the gsm.kri `gsm.viz-2.3.0` precedent).\n- Shared R helpers for the bindings: settings/payload construction, required-column validation against the module JSON data contracts, and a common `createWidget()` wrapper so the six bindings stay thin and consistent.\n- Retire `RenderSafetyChartsWidget()` and drop `safetyCharts` + `Tendril` from Imports/Remotes; DESCRIPTION refreshed (version 1.0.0, jwildfire URLs, trimmed dependencies).\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — qcthat-linked testthat coverage (test names reference this issue per the v1.0.0 qualification matrix)\n- [ ] User Tests (e.g. visual comparison) — rendered example page published as RC evidence on the hub\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/31",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-07-12",
      "Assignees": ["jwildfire"],
      "Test": "SaveWidgetReport keeps an existing .html extension and validates inputs (#31)",
      "File": "test-utils-widget.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 30,
      "Title": "Add Widget_Histogram htmlwidget consuming the safety.viz bundle",
      "Body": "\nParent: jwildfire/obot.roadmap#2 (slice ③) · [Design document](https://jwildfire.github.io/obot.roadmap/requirements/design/2_design.html) · Depends on the safety.viz histogram module (slice ②) shipping a `dist/` bundle\n\n## Summary\n\nAdd `Widget_Histogram`, the first safetyGraphics-replacement htmlwidget in gsm.safety: an interactive lab-results distribution view (normal-range overlays + linked participant listing) rendered by the safety.viz histogram module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_Histogram.js` + `Widget_Histogram.yaml`, with the safety.viz bundle vendored at `inst/htmlwidgets/lib/safety.viz-{version}/` (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_Histogram()` R function maps a long lab-results data.frame (`subjid`-keyed, per gsm column conventions) plus a settings list onto the module's JSON data contract, then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n\n## Example Usage\n\n```r\nWidget_Histogram(\n  dfResults = dfLabs,           # long format: one record per measurement\n  lSettings = list(\n    strMeasureCol = \"lbtest\",\n    strResultCol  = \"lbstresn\",\n    strIDCol      = \"subjid\"\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — testthat coverage of the R-side data/settings → JSON contract mapping\n- [ ] User Tests (e.g. visual comparison) — pkgdown example page provides the rendered artifact for review\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/30",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 2,
      "CreatedAt": "2026-07-04",
      "Assignees": ["jwildfire"],
      "Test": "Widget_Histogram returns an htmlwidget carrying the histogram payload (#30)",
      "File": "test-Widget_Histogram.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 30,
      "Title": "Add Widget_Histogram htmlwidget consuming the safety.viz bundle",
      "Body": "\nParent: jwildfire/obot.roadmap#2 (slice ③) · [Design document](https://jwildfire.github.io/obot.roadmap/requirements/design/2_design.html) · Depends on the safety.viz histogram module (slice ②) shipping a `dist/` bundle\n\n## Summary\n\nAdd `Widget_Histogram`, the first safetyGraphics-replacement htmlwidget in gsm.safety: an interactive lab-results distribution view (normal-range overlays + linked participant listing) rendered by the safety.viz histogram module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_Histogram.js` + `Widget_Histogram.yaml`, with the safety.viz bundle vendored at `inst/htmlwidgets/lib/safety.viz-{version}/` (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_Histogram()` R function maps a long lab-results data.frame (`subjid`-keyed, per gsm column conventions) plus a settings list onto the module's JSON data contract, then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n\n## Example Usage\n\n```r\nWidget_Histogram(\n  dfResults = dfLabs,           # long format: one record per measurement\n  lSettings = list(\n    strMeasureCol = \"lbtest\",\n    strResultCol  = \"lbstresn\",\n    strIDCol      = \"subjid\"\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — testthat coverage of the R-side data/settings → JSON contract mapping\n- [ ] User Tests (e.g. visual comparison) — pkgdown example page provides the rendered artifact for review\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/30",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 2,
      "CreatedAt": "2026-07-04",
      "Assignees": ["jwildfire"],
      "Test": "Widget_Histogram passes width, height, and elementId through (#30)",
      "File": "test-Widget_Histogram.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 30,
      "Title": "Add Widget_Histogram htmlwidget consuming the safety.viz bundle",
      "Body": "\nParent: jwildfire/obot.roadmap#2 (slice ③) · [Design document](https://jwildfire.github.io/obot.roadmap/requirements/design/2_design.html) · Depends on the safety.viz histogram module (slice ②) shipping a `dist/` bundle\n\n## Summary\n\nAdd `Widget_Histogram`, the first safetyGraphics-replacement htmlwidget in gsm.safety: an interactive lab-results distribution view (normal-range overlays + linked participant listing) rendered by the safety.viz histogram module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_Histogram.js` + `Widget_Histogram.yaml`, with the safety.viz bundle vendored at `inst/htmlwidgets/lib/safety.viz-{version}/` (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_Histogram()` R function maps a long lab-results data.frame (`subjid`-keyed, per gsm column conventions) plus a settings list onto the module's JSON data contract, then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n\n## Example Usage\n\n```r\nWidget_Histogram(\n  dfResults = dfLabs,           # long format: one record per measurement\n  lSettings = list(\n    strMeasureCol = \"lbtest\",\n    strResultCol  = \"lbstresn\",\n    strIDCol      = \"subjid\"\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — testthat coverage of the R-side data/settings → JSON contract mapping\n- [ ] User Tests (e.g. visual comparison) — pkgdown example page provides the rendered artifact for review\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/30",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 2,
      "CreatedAt": "2026-07-04",
      "Assignees": ["jwildfire"],
      "Test": "Widget_Histogram rejects invalid inputs via the histogram contract (#30)",
      "File": "test-Widget_Histogram.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 30,
      "Title": "Add Widget_Histogram htmlwidget consuming the safety.viz bundle",
      "Body": "\nParent: jwildfire/obot.roadmap#2 (slice ③) · [Design document](https://jwildfire.github.io/obot.roadmap/requirements/design/2_design.html) · Depends on the safety.viz histogram module (slice ②) shipping a `dist/` bundle\n\n## Summary\n\nAdd `Widget_Histogram`, the first safetyGraphics-replacement htmlwidget in gsm.safety: an interactive lab-results distribution view (normal-range overlays + linked participant listing) rendered by the safety.viz histogram module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_Histogram.js` + `Widget_Histogram.yaml`, with the safety.viz bundle vendored at `inst/htmlwidgets/lib/safety.viz-{version}/` (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_Histogram()` R function maps a long lab-results data.frame (`subjid`-keyed, per gsm column conventions) plus a settings list onto the module's JSON data contract, then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n\n## Example Usage\n\n```r\nWidget_Histogram(\n  dfResults = dfLabs,           # long format: one record per measurement\n  lSettings = list(\n    strMeasureCol = \"lbtest\",\n    strResultCol  = \"lbstresn\",\n    strIDCol      = \"subjid\"\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — testthat coverage of the R-side data/settings → JSON contract mapping\n- [ ] User Tests (e.g. visual comparison) — pkgdown example page provides the rendered artifact for review\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/30",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 2,
      "CreatedAt": "2026-07-04",
      "Assignees": ["jwildfire"],
      "Test": "Widget_Histogram renders standalone HTML with the SafetyViz bundle and data (#30)",
      "File": "test-Widget_Histogram.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 30,
      "Title": "Add Widget_Histogram htmlwidget consuming the safety.viz bundle",
      "Body": "\nParent: jwildfire/obot.roadmap#2 (slice ③) · [Design document](https://jwildfire.github.io/obot.roadmap/requirements/design/2_design.html) · Depends on the safety.viz histogram module (slice ②) shipping a `dist/` bundle\n\n## Summary\n\nAdd `Widget_Histogram`, the first safetyGraphics-replacement htmlwidget in gsm.safety: an interactive lab-results distribution view (normal-range overlays + linked participant listing) rendered by the safety.viz histogram module. Mirrors how gsm.kri wraps gsm.viz charts.\n\n## Proposed Solution\n\n- `inst/htmlwidgets/Widget_Histogram.js` + `Widget_Histogram.yaml`, with the safety.viz bundle vendored at `inst/htmlwidgets/lib/safety.viz-{version}/` (the gsm.kri precedent — no node toolchain at install time).\n- `Widget_Histogram()` R function maps a long lab-results data.frame (`subjid`-keyed, per gsm column conventions) plus a settings list onto the module's JSON data contract, then drives the module lifecycle API (`init`/`setData`/`setSettings`/`render`/`resize`/`destroy`) from the widget's `renderValue`/`resize` hooks.\n\n## Example Usage\n\n```r\nWidget_Histogram(\n  dfResults = dfLabs,           # long format: one record per measurement\n  lSettings = list(\n    strMeasureCol = \"lbtest\",\n    strResultCol  = \"lbstresn\",\n    strIDCol      = \"subjid\"\n  )\n)\n```\n\n## QC Approach\n\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n- [ ] Unit Tests — testthat coverage of the R-side data/settings → JSON contract mapping\n- [ ] User Tests (e.g. visual comparison) — pkgdown example page provides the rendered artifact for review\n- [ ] `devtools::check()` clean as the merge gate\n\n---\n\nThis Issue was drafted by Claude Code using Fable 5 and reviewed by @jwildfire.\n",
      "Labels": ["enhancement"],
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/30",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 2,
      "CreatedAt": "2026-07-04",
      "Assignees": ["jwildfire"],
      "Test": "safety_histogram workflow renders an HTML report from ExampleData (#30, #38)",
      "File": "test-workflow-safety-histogram.R",
      "Disposition": "pass"
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 28,
      "Title": "Add pkgdown widget thumbnail gallery",
      "Body": "Add a pkgdown gallery for the interactive SafetyCharts examples.\\n\\nScope:\\n- Generate thumbnail screenshots for each supported interactive widget example.\\n- Replace or supplement the current widget table with a gallery of thumbnail cards.\\n- Each thumbnail should link to the corresponding pkgdown example.\\n- Prefer a headless-browser capture workflow so JavaScript/htmlwidgets finish rendering before capture.\\n- Keep screenshot tooling as development/docs tooling, not a runtime package dependency.\\n\\nInitial implementation plan:\\n- Use Playwright to open rendered pkgdown example pages.\\n- Wait for htmlwidget content to render.\\n- Capture stable element/page screenshots into package assets.\\n- Render a gallery in README/pkgdown index with clickable thumbnail links.\\n\\nAcceptance criteria:\\n- Gallery appears on the pkgdown home page.\\n- Gallery links go to the corresponding examples.\\n- Thumbnails are committed static assets.\\n- Documentation explains how to regenerate thumbnails.",
      "Labels": {},
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/28",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-05-15",
      "Assignees": ["obot-claw"]
    },
    {
      "Milestone": "v1.0.0",
      "Issue": 27,
      "Title": "Add QCThat testing framework",
      "Body": "## Summary\n\nAdd gilead-biostats/qcthat test framework to gsm.safety. Consider best way to implement UAT review for widgets. Static charts can likely use more traditional testthat workflows. \n\n## Proposed Solution (Optional)\n<!-- High-level idea: algorithms, data model changes, UI sketch, workflow diagram. -->\n\n## Example Usage (Optional)\n<!-- Illustrative code snippet or workflow showing how users would consume it. -->\n\n## QC Approach\n<!-- How will the quality of the implementation be verified? -->\nIn addition to standard QC (e.g., code reviews, automated checks) the following QC measures will be implemented:\n\n[ ] Qualification Test via Double Programming\n[ ] Unit Tests\n[ ] User Tests (e.g. visual comparison)",
      "Labels": {},
      "State": "open",
      "Type": "Issue",
      "Url": "https://github.com/jwildfire/gsm.safety/issues/27",
      "ParentOwner": "jwildfire",
      "ParentRepo": "obot.roadmap",
      "ParentNumber": 28,
      "CreatedAt": "2026-05-14",
      "Assignees": {},
      "Test": "every test in the package carries a qcthat issue reference (#27)",
      "File": "test-qcthat-convention.R",
      "Disposition": "pass"
    }
  ],
  "IgnoredIssues": {
    "qcthat-nocov": [],
    "qcthat-uat": []
  },
  "ColumnOrder": ["Milestone", "Issue", "Title", "Body", "Labels", "State", "StateReason", "Type", "Url", "ParentOwner", "ParentRepo", "ParentNumber", "CreatedAt", "ClosedAt", "Assignees", "Test", "File", "Disposition"]
}
