medsci-skills 4.1.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/README.md +171 -8
  2. package/installers/install.py +130 -43
  3. package/installers/medsci_txn.py +351 -0
  4. package/installers/session_update_check.py +71 -0
  5. package/installers/update-macos.command +23 -0
  6. package/installers/update-windows.cmd +18 -0
  7. package/installers/update.py +581 -0
  8. package/metadata/distribution_files.json +3640 -0
  9. package/metadata/distribution_manifest.json +51 -0
  10. package/metadata/skills_catalog.json +55 -1
  11. package/package.json +8 -1
  12. package/skills/academic-aio/SKILL.md +2 -0
  13. package/skills/academic-aio/references/summary_box_specs.json +27 -0
  14. package/skills/academic-aio/scripts/check_summary_box.py +206 -0
  15. package/skills/academic-aio/skill.yml +3 -0
  16. package/skills/academic-aio/tests/test_batch_metadata_audit.sh +91 -0
  17. package/skills/academic-aio/tests/test_summary_box.sh +72 -0
  18. package/skills/academic-aio/tests/test_validate_schema.sh +66 -0
  19. package/skills/add-journal/skill.yml +1 -0
  20. package/skills/analyze-stats/SKILL.md +31 -1
  21. package/skills/analyze-stats/references/analysis_guides/mediation.md +76 -0
  22. package/skills/analyze-stats/references/analysis_guides/survey_weighted.md +16 -0
  23. package/skills/analyze-stats/references/table-standards/table-types/agreement.md +67 -0
  24. package/skills/analyze-stats/references/table-standards/table-types/incremental_value.md +71 -0
  25. package/skills/analyze-stats/references/table-standards/table-types/reader_study.md +62 -0
  26. package/skills/analyze-stats/references/table-standards/table-types/survival_results.md +82 -0
  27. package/skills/analyze-stats/references/table-standards/table-types/table1_demographics.md +23 -1
  28. package/skills/analyze-stats/references/templates/likert_summary.py +68 -6
  29. package/skills/analyze-stats/skill.yml +1 -0
  30. package/skills/author-strategy/SKILL.md +74 -5
  31. package/skills/author-strategy/analyze_patterns.py +11 -10
  32. package/skills/author-strategy/classify_archetypes.py +524 -0
  33. package/skills/author-strategy/fetch_pubmed.py +169 -294
  34. package/skills/author-strategy/pubmed_parse.py +344 -0
  35. package/skills/author-strategy/references/trajectory_archetypes.md +130 -0
  36. package/skills/author-strategy/references/trajectory_archetypes.yaml +377 -0
  37. package/skills/author-strategy/render_archetype_doc.py +176 -0
  38. package/skills/author-strategy/skill.yml +8 -2
  39. package/skills/author-strategy/tests/fixtures/sample_corpus.csv +9 -0
  40. package/skills/author-strategy/tests/fixtures/two_samesurname_authors.xml +48 -0
  41. package/skills/author-strategy/tests/test_archetype_classifier.sh +227 -0
  42. package/skills/batch-cohort/skill.yml +1 -0
  43. package/skills/calc-sample-size/SKILL.md +1 -0
  44. package/skills/calc-sample-size/references/justification_examples.md +54 -0
  45. package/skills/calc-sample-size/skill.yml +1 -0
  46. package/skills/check-reporting/SKILL.md +35 -2
  47. package/skills/check-reporting/references/LICENSES.md +13 -0
  48. package/skills/check-reporting/references/appraisal_tools/METRICS.md +57 -0
  49. package/skills/check-reporting/references/checklists/CARE.md +16 -0
  50. package/skills/check-reporting/references/checklists/CONSORT_AI.md +77 -0
  51. package/skills/check-reporting/references/checklists/DECIDE_AI.md +90 -0
  52. package/skills/check-reporting/references/checklists/SPIRIT_AI.md +74 -0
  53. package/skills/check-reporting/references/checklists/TRIPOD_LLM.md +156 -0
  54. package/skills/check-reporting/references/critical_item_floor.md +61 -0
  55. package/skills/check-reporting/scripts/check_checklist_exists.py +2 -0
  56. package/skills/check-reporting/skill.yml +3 -2
  57. package/skills/check-reporting/tests/test_checklist_fail_fast.sh +12 -8
  58. package/skills/clean-data/SKILL.md +3 -0
  59. package/skills/clean-data/scripts/check_reverse_coding.py +211 -0
  60. package/skills/clean-data/skill.yml +1 -0
  61. package/skills/clean-data/tests/fixtures/scale_reverse.csv +9 -0
  62. package/skills/clean-data/tests/test_reverse_coding.sh +57 -0
  63. package/skills/cross-national/skill.yml +1 -0
  64. package/skills/define-variables/skill.yml +1 -0
  65. package/skills/deidentify/skill.yml +1 -0
  66. package/skills/deidentify/tests/test_deidentify_scan.sh +80 -0
  67. package/skills/design-ai-benchmarking/skill.yml +1 -0
  68. package/skills/design-study/SKILL.md +1 -1
  69. package/skills/design-study/skill.yml +1 -0
  70. package/skills/fill-icmje-coi/skill.yml +1 -0
  71. package/skills/fill-icmje-coi/tests/test_fill_icmje_coi.sh +70 -0
  72. package/skills/fill-protocol/skill.yml +1 -0
  73. package/skills/fill-protocol/tests/test_fill_form.sh +94 -0
  74. package/skills/find-cohort-gap/skill.yml +1 -0
  75. package/skills/find-journal/references/journal_profiles/BJR_Case_Reports.md +39 -0
  76. package/skills/find-journal/references/journal_profiles/BMJ_Case_Reports.md +31 -0
  77. package/skills/find-journal/references/journal_profiles/CVIR.md +16 -9
  78. package/skills/find-journal/references/journal_profiles/Cureus.md +32 -0
  79. package/skills/find-journal/references/journal_profiles/Journal_of_Medical_Case_Reports.md +30 -0
  80. package/skills/find-journal/references/journal_profiles/NEJM_AI.md +38 -0
  81. package/skills/find-journal/references/journal_profiles/Radiology_Case_Reports.md +30 -0
  82. package/skills/find-journal/references/journal_profiles/The_Lancet_Digital_Health.md +3 -1
  83. package/skills/find-journal/skill.yml +1 -0
  84. package/skills/fulltext-retrieval/skill.yml +1 -0
  85. package/skills/fulltext-retrieval/tests/test_pdf_to_md.py +61 -0
  86. package/skills/generate-codebook/skill.yml +1 -0
  87. package/skills/grant-builder/skill.yml +1 -0
  88. package/skills/humanize/SKILL.md +2 -1
  89. package/skills/humanize/skill.yml +1 -0
  90. package/skills/intake-project/skill.yml +1 -0
  91. package/skills/lit-sync/skill.yml +1 -0
  92. package/skills/ma-scout/skill.yml +1 -0
  93. package/skills/make-figures/SKILL.md +5 -2
  94. package/skills/make-figures/references/critic_rubrics/data_plot.md +3 -0
  95. package/skills/make-figures/references/exemplar_plots/README.md +61 -0
  96. package/skills/make-figures/references/exemplar_plots/bland_altman.md +46 -0
  97. package/skills/make-figures/references/exemplar_plots/calibration_plot.md +36 -0
  98. package/skills/make-figures/references/exemplar_plots/clinical_timeline.md +56 -0
  99. package/skills/make-figures/references/exemplar_plots/confusion_matrix.md +48 -0
  100. package/skills/make-figures/references/exemplar_plots/decision_curve.md +52 -0
  101. package/skills/make-figures/references/exemplar_plots/forest_plot.md +45 -0
  102. package/skills/make-figures/references/exemplar_plots/imaging_panel.md +45 -0
  103. package/skills/make-figures/references/exemplar_plots/km_curve.md +41 -0
  104. package/skills/make-figures/references/exemplar_plots/mrmc_roc.md +41 -0
  105. package/skills/make-figures/references/exemplar_plots/roc_pr.md +37 -0
  106. package/skills/make-figures/references/flow_diagram_lessons.md +41 -0
  107. package/skills/make-figures/references/reporting_guideline_figure_map.md +3 -3
  108. package/skills/make-figures/skill.yml +1 -0
  109. package/skills/manage-project/skill.yml +1 -0
  110. package/skills/manage-refs/SKILL.md +12 -0
  111. package/skills/manage-refs/scripts/pre_submission_gate.sh +2 -1
  112. package/skills/manage-refs/scripts/render_pandoc.sh +34 -1
  113. package/skills/manage-refs/skill.yml +1 -0
  114. package/skills/meta-analysis/SKILL.md +65 -0
  115. package/skills/meta-analysis/references/phase6_statistical_synthesis.md +2 -2
  116. package/skills/meta-analysis/references/single_arm_proportion_ma.md +53 -0
  117. package/skills/meta-analysis/scripts/extract_assist.py +193 -0
  118. package/skills/meta-analysis/scripts/extract_assist_challenge/expected/suggestions.tsv +13 -0
  119. package/skills/meta-analysis/scripts/extract_assist_challenge/fixture/confirmed_example.csv +2 -0
  120. package/skills/meta-analysis/scripts/extract_assist_challenge/fixture/paper.md +17 -0
  121. package/skills/meta-analysis/scripts/extract_assist_challenge/fixture/schema.yaml +12 -0
  122. package/skills/meta-analysis/scripts/extract_assist_challenge/problem.md +71 -0
  123. package/skills/meta-analysis/scripts/extract_assist_challenge/verify.sh +43 -0
  124. package/skills/meta-analysis/skill.yml +3 -0
  125. package/skills/orchestrate/SKILL.md +1 -1
  126. package/skills/orchestrate/skill.yml +1 -0
  127. package/skills/peer-review/SKILL.md +97 -17
  128. package/skills/peer-review/references/domain-probes/ai_overclaiming.md +33 -3
  129. package/skills/peer-review/references/domain-probes/case_report.md +119 -0
  130. package/skills/peer-review/references/domain-probes/clinical_prediction_model.md +44 -0
  131. package/skills/peer-review/references/domain-probes/diagnostic_accuracy.md +46 -0
  132. package/skills/peer-review/references/domain-probes/equity_fairness.md +99 -0
  133. package/skills/peer-review/references/domain-probes/image_synthesis.md +38 -0
  134. package/skills/peer-review/references/domain-probes/narrative_review.md +17 -3
  135. package/skills/peer-review/references/domain-probes/observational_confounding.md +57 -3
  136. package/skills/peer-review/references/domain-probes/rct_trial.md +69 -0
  137. package/skills/peer-review/references/domain-probes/sr_ma.md +20 -2
  138. package/skills/peer-review/references/domain-probes/survival_prognostic.md +30 -2
  139. package/skills/peer-review/references/exemplar_reviews/README.md +5 -0
  140. package/skills/peer-review/references/exemplar_reviews/optimistic_validation_reporting.md +68 -0
  141. package/skills/peer-review/references/exemplar_reviews/selective_outcome_reporting.md +51 -0
  142. package/skills/peer-review/references/narrative_review_audit.md +1 -1
  143. package/skills/peer-review/references/reviewer_calibration/README.md +4 -1
  144. package/skills/peer-review/references/reviewer_calibration/compliance_floor.md +27 -0
  145. package/skills/peer-review/references/reviewer_profiles/AJR.md +1 -1
  146. package/skills/peer-review/skill.yml +1 -0
  147. package/skills/polish-language/SKILL.md +136 -0
  148. package/skills/polish-language/scripts/lint_challenge/expected/report.txt +28 -0
  149. package/skills/polish-language/scripts/lint_challenge/fixture/manuscript.md +17 -0
  150. package/skills/polish-language/scripts/lint_challenge/problem.md +55 -0
  151. package/skills/polish-language/scripts/lint_challenge/verify.sh +16 -0
  152. package/skills/polish-language/scripts/lint_consistency.py +296 -0
  153. package/skills/polish-language/skill.yml +38 -0
  154. package/skills/present-paper/SKILL.md +5 -1
  155. package/skills/present-paper/scripts/inject_speaker_notes.py +70 -2
  156. package/skills/present-paper/skill.yml +1 -0
  157. package/skills/present-paper/tests/test_speaker_notes_markdown.py +56 -0
  158. package/skills/publish-skill/skill.yml +1 -0
  159. package/skills/render-pdf-doc/SKILL.md +23 -0
  160. package/skills/render-pdf-doc/scripts/scan_glyph_coverage.py +160 -0
  161. package/skills/render-pdf-doc/skill.yml +2 -0
  162. package/skills/render-pdf-doc/tests/fixtures/glyph_plain.md +3 -0
  163. package/skills/render-pdf-doc/tests/fixtures/glyph_risky.md +3 -0
  164. package/skills/render-pdf-doc/tests/test_glyph_coverage.sh +39 -0
  165. package/skills/replicate-study/skill.yml +1 -0
  166. package/skills/review-paper/SKILL.md +3 -3
  167. package/skills/review-paper/skill.yml +1 -0
  168. package/skills/revise/SKILL.md +2 -1
  169. package/skills/revise/skill.yml +1 -0
  170. package/skills/search-lit/SKILL.md +42 -0
  171. package/skills/search-lit/references/snowball.py +318 -0
  172. package/skills/search-lit/references/snowball_challenge/expected/snowball.bib +54 -0
  173. package/skills/search-lit/references/snowball_challenge/fixture/DOI_10_0_seed1.backward.json +22 -0
  174. package/skills/search-lit/references/snowball_challenge/fixture/DOI_10_0_seed1.forward.json +22 -0
  175. package/skills/search-lit/references/snowball_challenge/fixture/DOI_10_0_seed1.similar.json +11 -0
  176. package/skills/search-lit/references/snowball_challenge/fixture/library.bib +10 -0
  177. package/skills/search-lit/references/snowball_challenge/problem.md +64 -0
  178. package/skills/search-lit/references/snowball_challenge/verify.sh +22 -0
  179. package/skills/search-lit/skill.yml +3 -0
  180. package/skills/self-review/SKILL.md +114 -19
  181. package/skills/self-review/references/domain-probes/ai_overclaiming.md +33 -3
  182. package/skills/self-review/references/domain-probes/case_report.md +119 -0
  183. package/skills/self-review/references/domain-probes/clinical_prediction_model.md +44 -0
  184. package/skills/self-review/references/domain-probes/diagnostic_accuracy.md +46 -0
  185. package/skills/self-review/references/domain-probes/equity_fairness.md +99 -0
  186. package/skills/self-review/references/domain-probes/image_synthesis.md +38 -0
  187. package/skills/self-review/references/domain-probes/narrative_review.md +17 -3
  188. package/skills/self-review/references/domain-probes/observational_confounding.md +57 -3
  189. package/skills/self-review/references/domain-probes/rct_trial.md +69 -0
  190. package/skills/self-review/references/domain-probes/sr_ma.md +20 -2
  191. package/skills/self-review/references/domain-probes/survival_prognostic.md +30 -2
  192. package/skills/self-review/references/exemplar_findings/README.md +8 -0
  193. package/skills/self-review/references/exemplar_findings/cross_sectional_mediation.md +42 -0
  194. package/skills/self-review/references/exemplar_findings/over_adjustment_collider.md +41 -0
  195. package/skills/self-review/references/exemplar_findings/prediction_two_null_conflation.md +41 -0
  196. package/skills/self-review/references/panel_review_template.md +18 -1
  197. package/skills/self-review/scripts/check_classical_style.py +55 -7
  198. package/skills/self-review/scripts/check_cohort_arithmetic.py +89 -3
  199. package/skills/self-review/scripts/check_confounding_completeness.py +206 -13
  200. package/skills/self-review/scripts/check_paren_spans.py +161 -0
  201. package/skills/self-review/scripts/check_scope_coherence.py +33 -0
  202. package/skills/self-review/skill.yml +1 -0
  203. package/skills/self-review/tests/fixtures/cohort_repeat_subjects.csv +11 -0
  204. package/skills/self-review/tests/fixtures/cohort_unit_disclosed.md +15 -0
  205. package/skills/self-review/tests/fixtures/cohort_unit_undisclosed.md +12 -0
  206. package/skills/self-review/tests/fixtures/paren_clean.md +6 -0
  207. package/skills/self-review/tests/fixtures/paren_corrupt.md +11 -0
  208. package/skills/self-review/tests/fixtures/scope_yield.md +16 -0
  209. package/skills/self-review/tests/fixtures/scope_yield_defined.md +17 -0
  210. package/skills/self-review/tests/fixtures/style_emdash_structural.md +27 -0
  211. package/skills/self-review/tests/fixtures/table1_by_exposure_dbcodes.csv +15 -0
  212. package/skills/self-review/tests/fixtures/table1_meansd_wide.csv +7 -0
  213. package/skills/self-review/tests/test_classical_style.sh +11 -0
  214. package/skills/self-review/tests/test_cohort_arithmetic.sh +24 -0
  215. package/skills/self-review/tests/test_confounding_completeness.sh +72 -0
  216. package/skills/self-review/tests/test_paren_spans.sh +40 -0
  217. package/skills/self-review/tests/test_scope_coherence.sh +16 -0
  218. package/skills/setup-medsci/skill.yml +1 -0
  219. package/skills/sync-submission/SKILL.md +32 -0
  220. package/skills/sync-submission/references/journal_availability_policy.json +17 -0
  221. package/skills/sync-submission/scripts/assemble_supplement.py +199 -0
  222. package/skills/sync-submission/scripts/check_asset_anonymization.py +41 -0
  223. package/skills/sync-submission/scripts/check_disclosure_availability.py +230 -0
  224. package/skills/sync-submission/scripts/check_wordcount_cap.py +226 -0
  225. package/skills/sync-submission/skill.yml +4 -0
  226. package/skills/sync-submission/tests/fixtures/suppl_bad/00_index.md +5 -0
  227. package/skills/sync-submission/tests/fixtures/suppl_bad/S1_methods.md +7 -0
  228. package/skills/sync-submission/tests/fixtures/suppl_bad/S2_a.md +2 -0
  229. package/skills/sync-submission/tests/fixtures/suppl_bad/S2_b.md +2 -0
  230. package/skills/sync-submission/tests/fixtures/suppl_bad/S4_figs.md +2 -0
  231. package/skills/sync-submission/tests/fixtures/suppl_bad/S6_orphan.md +2 -0
  232. package/skills/sync-submission/tests/fixtures/suppl_clean/00_index.md +4 -0
  233. package/skills/sync-submission/tests/fixtures/suppl_clean/S1_methods.md +3 -0
  234. package/skills/sync-submission/tests/fixtures/suppl_clean/S2_analyses.md +7 -0
  235. package/skills/sync-submission/tests/fixtures/suppl_clean/S3_tables.md +3 -0
  236. package/skills/sync-submission/tests/fixtures/suppl_manuscript.md +1 -0
  237. package/skills/sync-submission/tests/fixtures/wc_body.md +29 -0
  238. package/skills/sync-submission/tests/fixtures/wc_journal_profile.md +11 -0
  239. package/skills/sync-submission/tests/test_assemble_supplement.sh +52 -0
  240. package/skills/sync-submission/tests/test_asset_anonymization.sh +23 -3
  241. package/skills/sync-submission/tests/test_disclosure_availability.sh +109 -0
  242. package/skills/sync-submission/tests/test_wordcount_cap.sh +60 -0
  243. package/skills/verify-refs/SKILL.md +20 -2
  244. package/skills/verify-refs/scripts/verify_refs.py +181 -8
  245. package/skills/verify-refs/skill.yml +3 -0
  246. package/skills/verify-refs/tests/fixtures/corporate_author.bib +23 -0
  247. package/skills/verify-refs/tests/test_corporate_author.sh +52 -0
  248. package/skills/verify-refs/tests/test_openalex_tier.sh +137 -0
  249. package/skills/version-dataset/skill.yml +1 -0
  250. package/skills/version-dataset/tests/test_version_dataset.sh +4 -0
  251. package/skills/write-paper/SKILL.md +50 -212
  252. package/skills/write-paper/references/exemplar_abstract.md +55 -0
  253. package/skills/write-paper/references/exemplar_case_report.md +175 -0
  254. package/skills/write-paper/references/exemplar_case_report_radiology.md +89 -0
  255. package/skills/write-paper/references/exemplar_discussion/README.md +42 -0
  256. package/skills/write-paper/references/exemplar_discussion/ai_validation_tripod_claim.md +44 -0
  257. package/skills/write-paper/references/exemplar_discussion/diagnostic_accuracy_stard.md +41 -0
  258. package/skills/write-paper/references/exemplar_discussion/observational_cohort_strobe.md +57 -0
  259. package/skills/write-paper/references/exemplar_introduction.md +41 -0
  260. package/skills/write-paper/references/exemplar_results/README.md +42 -0
  261. package/skills/write-paper/references/exemplar_results/ai_validation_tripod_claim.md +51 -0
  262. package/skills/write-paper/references/exemplar_results/diagnostic_accuracy_stard.md +46 -0
  263. package/skills/write-paper/references/exemplar_results/observational_cohort_strobe.md +44 -0
  264. package/skills/write-paper/references/journal_profiles/CVIR.md +57 -112
  265. package/skills/write-paper/references/journal_profiles/NEJM_AI.md +105 -0
  266. package/skills/write-paper/references/journal_profiles/The_Lancet_Digital_Health.md +58 -0
  267. package/skills/write-paper/references/paper_types/case_report.md +2 -2
  268. package/skills/write-paper/references/paper_types/case_series.md +94 -0
  269. package/skills/write-paper/references/phase7_integrity_audits.md +208 -0
  270. package/skills/write-paper/references/section_guides/title_abstract.md +38 -0
  271. package/skills/write-paper/scripts/build_title_page_affiliations.py +275 -0
  272. package/skills/write-paper/skill.yml +3 -0
  273. package/skills/write-paper/tests/test_title_page_affiliations.sh +73 -0
  274. package/skills/write-protocol/skill.yml +1 -0
package/README.md CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  # MedSci Skills
4
4
 
5
- **44 skills that actually work.** Built by a physician-researcher, tested on real publications.
5
+ **45 skills that actually work.** Built by a physician-researcher, tested on real publications.
6
6
 
7
- *MedSci Skills is a submission-grade clinical manuscript workflow, not a generic biomedical skill catalog. It competes on clinical submission reliability, not skill count.*
7
+ *MedSci Skills is a submission-grade clinical manuscript workflow, not a generic biomedical skill catalog. Its moat is the compliance layer — 36 reporting guidelines and risk-of-bias tools, reference/citation verification, and deterministic integrity gates, before peer review sees the manuscript. It competes on clinical submission reliability, not skill count.*
8
8
 
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
10
  [![Release](https://img.shields.io/github/v/release/Aperivue/medsci-skills?style=flat-square&color=blue)](https://github.com/Aperivue/medsci-skills/releases/latest)
11
11
  [![CI](https://img.shields.io/github/actions/workflow/status/Aperivue/medsci-skills/validate.yml?branch=main&style=flat-square&label=CI)](https://github.com/Aperivue/medsci-skills/actions/workflows/validate.yml)
12
- ![Skills](https://img.shields.io/badge/Skills-44-brightgreen?style=flat-square)
12
+ ![Skills](https://img.shields.io/badge/Skills-45-brightgreen?style=flat-square)
13
+ [![npm](https://img.shields.io/npm/v/medsci-skills?style=flat-square&label=npm&color=cb3837)](https://www.npmjs.com/package/medsci-skills)
14
+ [![good first issues](https://img.shields.io/github/issues/Aperivue/medsci-skills/good%20first%20issue?style=flat-square&label=good%20first%20issues&color=7057ff)](https://github.com/Aperivue/medsci-skills/contribute)
13
15
 
14
16
  [![Agent Skills](https://img.shields.io/badge/Agent_Skills-standard-blue?style=flat-square)](https://agentskills.io)
15
17
  [![Claude Code](https://img.shields.io/badge/Claude_Code-supported-success?style=flat-square)](docs/host_compatibility.md)
@@ -18,6 +20,7 @@
18
20
  [![GitHub Copilot](https://img.shields.io/badge/GitHub_Copilot-supported-success?style=flat-square)](docs/host_compatibility.md)
19
21
 
20
22
  [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.20155321-blue?style=flat-square)](https://doi.org/10.5281/zenodo.20155321)
23
+ [![arXiv](https://img.shields.io/badge/arXiv-2606.09500-b31b1b?style=flat-square)](https://arxiv.org/abs/2606.09500)
21
24
  [![Citation](https://img.shields.io/badge/Cite-CITATION.cff-blue?style=flat-square)](CITATION.cff)
22
25
  ![Built by](https://img.shields.io/badge/Built_by-Physician--Researcher-blue?style=flat-square)
23
26
 
@@ -35,10 +38,31 @@
35
38
 
36
39
  ---
37
40
 
41
+ ## What is MedSci Skills?
42
+
43
+ MedSci Skills is an open-source Claude Code skill collection for **clinical
44
+ manuscript preparation**. It helps physician-researchers and biomedical
45
+ investigators move from literature search, study design, statistics, and figures to
46
+ reporting-guideline compliance, citation/reference auditing, numerical-consistency
47
+ checks, and response-to-reviewer workflows — combining agentic writing with
48
+ **deterministic integrity gates** for submission-grade biomedical research. It is
49
+ **not** a diagnostic tool, an autonomous author, or a general AI-scientist platform;
50
+ every output requires human-expert verification. New here? See the
51
+ [3 workflows below](#start-here-3-workflows), the [FAQ](docs/faq.md), and the
52
+ [scope boundary](ROADMAP.md#not-planned--explicitly-out-of-scope).
53
+
54
+ ---
55
+
38
56
  ## Quick Start
39
57
 
40
58
  **No terminal?** Use the classroom installer ZIP — download, unzip, double-click the installer, then restart your agent app (see [Installation](#installation)).
41
59
 
60
+ **Have a terminal?** Fastest path — one command, nothing to clone:
61
+
62
+ ```bash
63
+ npx medsci-skills install # copies every skill into your agent's folder
64
+ ```
65
+
42
66
  **Have git?** Install every skill in three commands:
43
67
 
44
68
  ```bash
@@ -81,10 +105,38 @@ All eight plugins share the same repository source, so this groups and enables s
81
105
  **Want just one capability?** Two skills are also published as focused standalone repos (generated mirrors; this repo stays the source of truth), each installable on its own with `/plugin marketplace add Aperivue/<repo>`:
82
106
 
83
107
  - [`Aperivue/verify-refs`](https://github.com/Aperivue/verify-refs) — catch fabricated/mismatched citations (PubMed + CrossRef).
84
- - [`Aperivue/check-reporting`](https://github.com/Aperivue/check-reporting) — audit a manuscript against 32 EQUATOR reporting guidelines.
108
+ - [`Aperivue/check-reporting`](https://github.com/Aperivue/check-reporting) — audit a manuscript against the bundled EQUATOR reporting guidelines and risk-of-bias tools.
85
109
 
86
110
  ---
87
111
 
112
+ ## Start here: 3 workflows
113
+
114
+ New users don't need all the skills at once. Most work starts as one of three
115
+ workflows. Each runs through `/orchestrate` or by invoking the named skills in
116
+ order; all outputs require human-expert review.
117
+
118
+ **Workflow A — Manuscript pre-submission audit.** *Use when* a manuscript is nearly
119
+ ready and you want it checked before a reviewer sees it. *Skills:* `/self-review` →
120
+ `/check-reporting` → `/verify-refs` → `/sync-submission`. *In:* your manuscript
121
+ (+ `refs.bib`, tables/figures). *Out:* anticipated reviewer comments, an item-by-item
122
+ reporting-guideline audit, a citation-integrity report, and a submission-package
123
+ drift check. *Safety:* it flags issues; you fix and verify them.
124
+
125
+ **Workflow B — Data to manuscript package.** *Use when* you have a cleaned dataset
126
+ and need a full draft. *Skills:* `/clean-data` → `/analyze-stats` → `/make-figures` →
127
+ `/write-paper` → `/check-reporting` → `/find-journal`. *In:* a cleaned CSV/parquet
128
+ + a research question. *Out:* reproducible analysis code, publication-ready figures,
129
+ an IMRaD draft, a reporting checklist, and a journal shortlist. *Safety:* statistics
130
+ and claims must be verified against your data; the toolkit never fabricates numbers
131
+ or references.
132
+
133
+ **Workflow C — Systematic review / meta-analysis.** *Use when* you are running an
134
+ SR/MA. *Skills:* `/meta-analysis` (with `/search-lit`, `/make-figures`,
135
+ `/check-reporting`). *In:* a research question + search strategy. *Out:* PROSPERO-style
136
+ protocol scaffolding, screening/extraction structure, PRISMA-consistent counts and
137
+ diagram, pooled-estimate figures, and a manuscript draft. *Safety:* screening and
138
+ extraction decisions stay with the human review team.
139
+
88
140
  ## Live Demos: Three Study Types, Three Full Pipelines
89
141
 
90
142
  Three public datasets. Three study types. Each produces a complete manuscript, publication-ready figures, and a reporting compliance audit.
@@ -215,6 +267,43 @@ The E2E pipeline (`orchestrate --e2e`) produces everything up to `qc/`. The `sub
215
267
 
216
268
  ## What's New
217
269
 
270
+ **v4.7** is the **self-update foundation** — physician-researchers stay current without GitHub, git, or a terminal. Additive and backward-compatible; still 45 skills / 36 guidelines / 30 detectors:
271
+
272
+ - **Transactional, crash-recoverable installer.** Each install runs through a durable journal state machine recovered on the next run (roll back / forward-clean / fail-closed), with per-target SHA-256 inventories — your modified or third-party skills are backed up and never clobbered or auto-deleted.
273
+ - **One-click self-updater** (`~/.medsci-skills/updater/`, `install.py --check-update`). Verifies the download against the github.com API digest and **never `extractall()`s** (per-entry rejection of traversal / symlink / duplicate / zip-bomb + an allowlist & per-file hash). The release pipeline injects a verified `provenance.json`, attests build provenance, runs on a protected `release` environment, and verifies each ZIP round-trips through the updater's own safe-extract before publishing.
274
+ - **Opt-in update notice (off by default):** `install.py --enable-update-notify` shows a one-line "update available" message at Claude Code session start — no telemetry, reads nothing about your session, installs nothing. `--disable-update-notify` / `MEDSCI_NO_UPDATE_CHECK=1` turn it off. *(Honest scope: the digest/attestation detect transport tampering, not a compromised publisher account — see `SECURITY.md`.)*
275
+
276
+ **v4.6** is a maintainability, governance, and review-depth release — still 45 skills / 36 guidelines; analysis-integrity detectors **28 → 30**, domain probes 11 → 12:
277
+
278
+ - **Fairness / equity / subgroup-performance probe (EQ0–EQ6)** for AI/prediction/diagnostic studies that claim cross-population performance, plus two new detectors: an **AI-disclosure + data/code-availability** check (`/sync-submission`) and a **structured-summary-box conformance** check (`/academic-aio`).
279
+ - **Governance + answer-engine layer:** `ROADMAP.md`, `MAINTAINERS.md`, `SECURITY.md`, a maintainer workflow + release checklist, an AEO/GEO `docs/faq.md`, a "Start here: 3 workflows" + "Validation status" section in this README, and a new `maturity` field (official / experimental / community) on every skill.
280
+ - **Token diet (pilot):** `write-paper` Phase 7 integrity audits moved to a load-on-demand reference (~2,559 tokens saved per invocation). Positioning now leads with the compliance moat rather than skill count.
281
+
282
+ **v4.5** deepens the review + submission surface with no new skill or reporting-guideline count (still 45 skills / 36 guidelines); analysis-integrity detectors **27 → 28**:
283
+
284
+ - **`/clean-data` + `/analyze-stats` — reverse-coded-item / negative-alpha detector.** A multi-item Likert scale with a negatively-worded item must be recoded `(min+max) − x` before the scale total or Cronbach's alpha is computed; left un-recoded, the item correlates negatively with the rest of the scale and alpha collapses (often negative). A negative alpha is a coding bug, not a "multidimensional construct." New stdlib-only `check_reverse_coding.py` returns `REVERSE_CODING_LIKELY` / `REVERSE_CODING_SUSPECT` / `OK` from per-item item-rest correlations + raw alpha; the Likert summary template gains a `--reverse-items` recode flag.
285
+ - **`/peer-review` + `/self-review` — SR/MA + DTA + prediction-model probe batch.** `sr_ma.md` **P12** risk-of-bias table row-sum ↔ traffic-light figure-matrix reconciliation and **P13** included-study ↔ reference-list completeness; `diagnostic_accuracy.md` **D7** index-test-as-enrollment-criterion circularity; `clinical_prediction_model.md` **CP5** intended-use horizon leakage and **CP6** development/CV vs held-out/external validation-nomenclature conflation. Vendored byte-identical into `/self-review`.
286
+ - **`/sync-submission` — embedded absolute-path leak scan.** A `word/*.xml` attribute (e.g. a pandoc-embedded image's `<pic:cNvPr descr="…">`) carrying an absolute home-dir path (`/Users/…`, `/home/…`) is a username leak invisible to a rendered-text scan; now flagged as `docx_embedded_abs_path` under `check_asset_anonymization.py`.
287
+
288
+ **v4.4** adds reviewer/analysis depth with no new skill or reporting-guideline count (still 45 skills / 36 guidelines / 27 detectors):
289
+
290
+ - **`/author-strategy` — trajectory-archetype classification (optional).** Classifies a queried author's PubMed trajectory into abstract career archetypes (A1 infrastructure builder, A2 methodology rule-maker, A3 clinical→AI hybrid, A4 SR/MA volume engine, A5 large-consortium participation, A6 device/technique depth, + a computed composite) as an **explainable, multi-label, confidence-scored heuristic — not an objective verdict**. The rubric is a single canonical YAML (the narrative doc is generated from it); scores exclude `unavailable` signals (h-index/citation/venue-tier → `[VERIFY]`, never fabricated); a **disambiguation gate** binds an approved `corpus_manifest.json` to the CSV (csv + PMID-set hashes) so a surname alone never classifies, and target-author attribution never borrows a co-author's ORCID/affiliation.
291
+ - **`/peer-review` + `/self-review` — Image-Synthesis / cross-modality probe (IS1–IS4)** for studies that synthesize one imaging modality from another and claim the output carries the target's information, plus a reviewer-side reference-integrity spot-check.
292
+ - **`/verify-refs` — OpenAlex tertiary index** recovers conference-proceedings / non-DOI citations (NeurIPS/ICLR/ACL) that fall through PubMed and CrossRef, the free analogue of a portal's second index.
293
+
294
+ **v4.3** hardens the **cross-sectional / observational cohort** review surface end-to-end, much of it reverse-engineered from real CC-BY cohort papers (learn-only under the license firewall) — no new skill or reporting-guideline count (still 45 skills / 36 guidelines); analysis-integrity detectors **25 → 27**:
295
+
296
+ - **Observational probes O1 → O14** (`/peer-review` + `/self-review`, vendored) — over-adjustment / analysis-unit clustering / outcome construct-validity (O7–O9), overlapping-subset gradient (O10), **complex-survey design & weighting** for NHANES/KNHANES (O11), **data-driven threshold / "inflection-point" mining** (O12), **cross-sectional mediation** temporal-order & sequential-ignorability (O13), and **interaction scale** — additive RERI/AP/S vs multiplicative (O14). Plus a new **clinical-prediction-model** probe module **CP1–CP4** and survival **S9** (panel-data / multistate variance).
297
+ - **Two new detectors (25 → 27)** — `check_wordcount_cap.py` (the revision-inflation trap: body vs journal cap) and `check_paren_spans.py` (em-dash→paren conversions that wrap a whole sentence). Plus a `check_confounding_completeness.py` upgrade (DB-code↔prose alias map, SMD-from-mean±SD, exposure-defining-covariate exemption), a `check_cohort_arithmetic.py` `ANALYSIS_UNIT_UNDISCLOSED` check, a `check_scope_coherence.py` cross-sectional-yield lexicon, and a verify-refs corporate/collective-author render-abort fix.
298
+ - **Analysis & submission tooling** — `/analyze-stats` gains **mediation** and **interaction & effect-modification** guides; `/sync-submission` gains `assemble_supplement.py` (S{N} index↔file integrity) and a `/revise` body-word-count exit gate; `/render-pdf-doc` gains a `scan_glyph_coverage.py` xelatex silent-glyph-drop scan.
299
+
300
+ **v4.2** builds out the case-report capability end-to-end, grounded in real CC-BY case reports (learn-only under the license firewall) — no new skill or reporting-guideline count (still 45 skills / 36 guidelines); journal profiles **68 → 73**:
301
+
302
+ - **Case-report + case-series writing** — `/write-paper` gains a CARE narrative + 150-word-abstract case-report exemplar, a **case-series** paper type (methods-light mini-cohort, all-cases summary table, counts-not-rates), and **adverse-event/pharmacovigilance** (Naranjo/WHO-UMC causality) and **diagnostic-pitfall/mimic** subtypes.
303
+ - **Radiology / imaging-led track** — a dedicated `exemplar_case_report_radiology.md` (per-modality technique→findings→impression, structured-reporting lexicons BI-RADS/LI-RADS/PI-RADS/TI-RADS/Lung-RADS/O-RADS, quantitative threshold honesty, an interventional-radiology procedure/complication subtype, DICOM de-identification) plus a `/make-figures` annotated multimodality imaging-panel exemplar.
304
+ - **Case-report reviewer probe** — `/peer-review` + `/self-review` ship a vendored case-report domain probe **CR1–CR9** (novelty/consent/n=1 causality, case-series design, adverse-event causality, imaging-led discipline).
305
+ - **Where to submit** — compact `/find-journal` profiles for Journal of Medical Case Reports, Cureus, Radiology Case Reports, BMJ Case Reports, and BJR Case Reports, and `/check-reporting` CARE notes for adverse-event and case-series subtypes.
306
+
218
307
  **v4.1** ships distribution levers and a submission pre-flight gate — analysis-integrity detectors **24 → 25** (still 43 skills):
219
308
 
220
309
  - **Claude Code plugin marketplace** — `/plugin marketplace add Aperivue/medsci-skills`, then `/plugin` discovery of eight `medsci-*` category plugins generated from the catalog SSOT (`.claude-plugin/marketplace.json`).
@@ -260,7 +349,7 @@ Earlier in this series: analysis-integrity guards (confounding completeness, cla
260
349
  | **Battle-tested** | Used on real manuscript submissions by a practicing physician-researcher | Unknown provenance and validation |
261
350
  | **Depth per skill** | 150-600 lines of documentation + bundled reference files (curated journal profile library, checklists, formula sheets, code templates) | Typically thin SKILL.md templates |
262
351
 
263
- **MedSci-Audit** — the verification edge in the first rows above is a named suite of **25 deterministic detectors** (citation & reference integrity, cohort & pool arithmetic, scope/estimand contracts, reporting compliance, and more) that catch fabricated or drifted content before a manuscript reaches a reviewer. See **[`MEDSCI_AUDIT.md`](MEDSCI_AUDIT.md)** for the suite, its six families, and its evaluation evidence.
352
+ **MedSci-Audit** — the verification edge in the first rows above is a named suite of **28 deterministic detectors** (citation & reference integrity, cohort & pool arithmetic, scope/estimand contracts, reporting compliance, and more) that catch fabricated or drifted content before a manuscript reaches a reviewer. See **[`MEDSCI_AUDIT.md`](MEDSCI_AUDIT.md)** for the suite, its six families, and its evaluation evidence.
264
353
 
265
354
  ---
266
355
 
@@ -332,7 +421,7 @@ ma-scout -> search-lit -> fulltext-retrieval -> design-study ──> write-proto
332
421
  | **search-lit** | PubMed + Semantic Scholar + bioRxiv search with anti-hallucination citation verification. Token-efficient error handling -- CrossRef failures are silently batched, not repeated. BibTeX output tags each entry with `verified`/`verified_by`/`verified_on` fields so downstream skills can trust the citation provenance. |
333
422
  | **verify-refs** | Pre-submission reference audit for `.md`, `.docx`, `.bib`, or `.tsv` inputs. Extracts references, verifies DOI/PMID via CrossRef/PubMed when available, and writes `qc/reference_audit.json` as the sole output — row-level status (OK / MISMATCH / UNVERIFIED / FABRICATED) lives inside the JSON `records[]` block. `/search-lit` produces candidate BibTeX; `/lit-sync` owns `manuscript/_src/refs.bib`. |
334
423
  | **fulltext-retrieval** | Batch open-access PDF downloader. Unpaywall → PMC → OpenAlex → CrossRef pipeline. OA-only -- no paywall bypass. Input: DOI list or TSV. Optional PDF→Markdown conversion via [pymupdf4llm](https://pymupdf.readthedocs.io/en/latest/pymupdf4llm/) for token-efficient LLM analysis of academic papers. |
335
- | **check-reporting** | Manuscript compliance audit against 32 reporting guidelines and risk of bias tools (STROBE, STARD, STARD-AI, TRIPOD, TRIPOD+AI, PRISMA, PRISMA-DTA, PRISMA-P, MOOSE, ARRIVE, CONSORT, CARE, SPIRIT, CLAIM, SQUIRE 2.0, CLEAR, GRRAS, MI-CLEAR-LLM, SWiM, AMSTAR 2, QUADAS-2, QUADAS-C, RoB 2, ROBINS-I, ROBINS-E, ROBIS, ROB-ME, PROBAST, PROBAST+AI, NOS, COSMIN, RoB NMA). Machine-readable JSON summary with `compliance_pct` and `fixable_by_ai` flags for automated pipeline integration. |
424
+ | **check-reporting** | Manuscript compliance audit against 36 reporting guidelines and risk of bias tools (STROBE, STARD, STARD-AI, TRIPOD, TRIPOD+AI, TRIPOD-LLM, PRISMA, PRISMA-DTA, PRISMA-P, MOOSE, ARRIVE, CONSORT, CONSORT-AI, CARE, SPIRIT, SPIRIT-AI, CLAIM, DECIDE-AI, SQUIRE 2.0, CLEAR, GRRAS, MI-CLEAR-LLM, SWiM, AMSTAR 2, QUADAS-2, QUADAS-C, RoB 2, ROBINS-I, ROBINS-E, ROBIS, ROB-ME, PROBAST, PROBAST+AI, NOS, COSMIN, RoB NMA). Machine-readable JSON summary with `compliance_pct` and `fixable_by_ai` flags for automated pipeline integration. |
336
425
  | **analyze-stats** | Statistical analysis code generation (Python/R) for diagnostic accuracy, DTA meta-analysis (bivariate/HSROC), inter-rater agreement, survival analysis, demographics tables, regression (logistic/linear), propensity score (matching/IPTW/overlap weighting), and repeated measures (RM ANOVA/GEE/mixed models). Calibration mandatory for prediction models. |
337
426
  | **meta-analysis** | Full systematic review and meta-analysis pipeline (8 phases). DTA (bivariate/HSROC) and intervention meta-analysis. Protocol to submission-ready manuscript with PRISMA-DTA compliance. |
338
427
  | **make-figures** | Publication-ready figures and visual abstracts: ROC curves, forest plots, PRISMA/CONSORT/STARD flow diagrams, Kaplan-Meier curves, Bland-Altman plots, confusion matrices, and journal-specific visual/graphical abstracts (python-pptx template-based). Communication-first design principles (Nat Hum Behav 2026 — key message, audience, cognitive load, figure-vs-table decision) and five flow-diagram production lessons (official-template fidelity, VML fallback PDF export, docx XML escape, sequential placeholder mapping, version freeze); critic rubric Section G adds 5 communication-first checks. `--study-type` auto-generates the full required figure set; structured `_figure_manifest.md` output for downstream pipeline consumption; D2 enforced as default for flow diagrams. |
@@ -363,6 +452,7 @@ ma-scout -> search-lit -> fulltext-retrieval -> design-study ──> write-proto
363
452
  | **ma-scout** | Meta-analysis topic discovery and feasibility assessment. Two modes: (A) Professor-first — profile → pillar analysis → MA gaps, (B) Topic-first — question → landscape scan → co-author matching. Multi-source validation (PubMed, PROSPERO, bioRxiv) with realistic k estimation (15-30% discount). |
364
453
  | **lit-sync** | Sync research references from .bib files to Zotero library + Obsidian literature notes. Concept extraction from 10+ literature notes with cross-cutting theme discovery. Works after `/search-lit` or standalone. |
365
454
  | **academic-aio** | AI search engine (Perplexity / ChatGPT web / Elicit / Consensus / SciSpace) and RAG visibility checklist for medical AI papers. Integrates TRIPOD+AI, CLAIM, STARD-AI, TRIPOD-LLM, DECIDE-AI reporting anchors with generative-engine-optimization (GEO) principles. Covers title, abstract, structured summary boxes (Key Points / Research in Context / Plain-Language Summary), preprints, GitHub README, `CITATION.cff`, Zenodo, and Hugging Face model/dataset cards. Explicit defense against LLM citation fabrication (Agarwal 2025, Nat Commun). Produces a visible PASS/PARTIAL/FAIL checklist; never applies edits silently. Pairs with `write-paper` Phase 4/6/7, runs after `self-review` + `humanize`. |
455
+ | **polish-language** | Academic English consistency linting and non-native (ESL) clarity polish. A deterministic linter (`lint_consistency.py`) flags abbreviation define-once violations, US/UK spelling drift, hyphen-vs-en-dash numeric ranges, `P`/`p` case and impossible `P = 0.000`, hyphenation variants, small-number style, and value/unit spacing — then a gated, style-only clarity pass fixes wording without ever changing numbers, citations, or scientific meaning. Distinct from `humanize` (AI-tell removal) and `check-reporting` (guideline items); bundles a reproducible challenge card. |
366
456
  | **manage-refs** | Reference lifecycle as a single skill: citekey ↔ `.bib` validation, journal-CSL pandoc rendering (`render_pandoc.sh`), manuscript ↔ rendered DOCX cross-reference QC (`check_xref.py --strict` is the submission gate), `[N]` ↔ `[@key]` marker conversion, and native Zotero CWYW field-code injection for co-author Word workflows. Hybrid 3-phase strategy (pandoc draft → CWYW transition → Zotero CWYW for circulation/revision/submission). Sole writer of `manuscript_final.docx` and `qc/xref_audit.json`. Split out of `write-paper` Phase 7.6 so `revise`, `peer-review`, `sync-submission`, and `find-journal` can render directly without depending on a sibling skill. |
367
457
  | **render-pdf-doc** | Render non-bibliography academic markdown (proposal, briefing handout, anchor doc, IRB cover, reference table) to publication-quality PDF via `pandoc + xelatex` with CJK font fallback (Apple SD Gothic Neo on macOS, Noto Sans CJK KR on Linux) and content-proportional pipe-table column widths. Boundary opposite of `manage-refs` (bibliography-driven). Spun off from `write-paper` Phase 7.6. |
368
458
  | **define-variables** | Literature-grounded variable operationalization for observational research. Turns a data dictionary plus research question into a citation-backed table of exposure / outcome / covariate definitions, cutoffs, and DB-variable mappings. Tier 0 dictionary-first rule prevents ad-hoc phenotype definitions that invite reviewer rejection. Bridges `/search-lit` output into `/write-protocol` Methods. |
@@ -442,6 +532,30 @@ See [docs/classroom_distribution_plan.md](docs/classroom_distribution_plan.md) a
442
532
 
443
533
  > **Tip:** Not sure which skill to use? Start with `/orchestrate` -- it will classify your request and route you to the right tool.
444
534
 
535
+ ## Updating
536
+
537
+ MedSci Skills updates often. You do **not** need GitHub, git, or the command line to stay current.
538
+
539
+ - **One click (recommended for the classroom install).** After installing, an updater is placed at
540
+ `~/.medsci-skills/updater/` (and, if you chose `--desktop-launcher`, an **"Update MedSci Skills"**
541
+ icon on your Desktop). Double-click it: it downloads the latest release from GitHub, verifies it,
542
+ and re-installs — transactionally, so an interrupted update never corrupts your install.
543
+ - **Already installed an old copy?** Re-download the latest classroom ZIP **once** and double-click
544
+ the installer; from then on the one-click updater is in place for every future update.
545
+ - **Terminal users:** `npx medsci-skills@latest install` always installs the latest.
546
+ - **Just checking:** `python3 installers/install.py --check-update` reports whether a newer version
547
+ is available and installs nothing.
548
+ - **Get reminded (opt-in, Claude Code):** `python3 installers/install.py --enable-update-notify`
549
+ shows a one-line *"update available"* notice when a Claude Code session starts. It is **off by
550
+ default**, checks at most once a day, reads nothing about your session, and never installs
551
+ anything. Turn it off with `--disable-update-notify`, or silence it with `MEDSCI_NO_UPDATE_CHECK=1`.
552
+ - **Claude Code plugin marketplace:** third-party marketplace **auto-update is off by default** —
553
+ enable it in Claude Code or run a manual plugin update.
554
+
555
+ Updates connect only to GitHub, send no information about your machine or work, and create no
556
+ telemetry or tracking. Modified skills are backed up before an update and never auto-deleted. See
557
+ the [update privacy & data notice](docs/update_privacy.md).
558
+
445
559
  ## Key Features
446
560
 
447
561
  ### Autonomous E2E Pipeline
@@ -465,8 +579,8 @@ Projects declare their source-of-truth layout in `SSOT.yaml`, and a `qc/migratio
465
579
  ### Meta-Analysis Failure Modes
466
580
  `/meta-analysis` ships empirical failure-mode references (data integrity, review orchestration, submission package drift, post-submission release ops) with four automation hooks: `scripts/prisma_5way_consistency.py` (DI-6 PRISMA number consistency), `scripts/extraction_consensus_log_init.py` (DI-1 dual-extraction scaffold), `scripts/tag_cleanup_gate.sh` (DI-8 placeholder tag gate), and `scripts/verify_package_integrity.py` (SPD SHA-256 manifest for submission bundles).
467
581
 
468
- ### 32 Reporting Guidelines & RoB Tools Built-in
469
- `check-reporting` includes bundled checklists for 32 guidelines and risk-of-bias tools: STROBE, STARD, STARD-AI, TRIPOD, TRIPOD+AI, PRISMA 2020, PRISMA-DTA, PRISMA-P, MOOSE, ARRIVE, CONSORT, CARE, SPIRIT, CLAIM, SQUIRE 2.0, CLEAR, GRRAS, MI-CLEAR-LLM, SWiM, AMSTAR 2, QUADAS-2, QUADAS-C, RoB 2, ROBINS-I, ROBINS-E, ROBIS, ROB-ME, PROBAST, PROBAST+AI, NOS, COSMIN, RoB NMA. Includes Results/Discussion section boundary checks and machine-readable JSON summary for pipeline integration.
582
+ ### 36 Reporting Guidelines & RoB Tools Built-in
583
+ `check-reporting` includes bundled checklists for 36 guidelines and risk-of-bias tools: STROBE, STARD, STARD-AI, TRIPOD, TRIPOD+AI, TRIPOD-LLM, PRISMA 2020, PRISMA-DTA, PRISMA-P, MOOSE, ARRIVE, CONSORT, CONSORT-AI, CARE, SPIRIT, SPIRIT-AI, CLAIM, DECIDE-AI, SQUIRE 2.0, CLEAR, GRRAS, MI-CLEAR-LLM, SWiM, AMSTAR 2, QUADAS-2, QUADAS-C, RoB 2, ROBINS-I, ROBINS-E, ROBIS, ROB-ME, PROBAST, PROBAST+AI, NOS, COSMIN, RoB NMA. Includes Results/Discussion section boundary checks and machine-readable JSON summary for pipeline integration.
470
584
 
471
585
  ### Publication-Ready Output
472
586
  `analyze-stats` generates reproducible Python/R code for 13 analysis types -- including regression, propensity score, and repeated measures -- with mandatory calibration for prediction models. `make-figures` produces journal-specification figures (300 DPI, colorblind-safe palettes, proper dimensions), visual/graphical abstracts, and a tool selection guide (D2 for flow diagrams, matplotlib for data plots). `--study-type` auto-generates the complete figure set for each study design.
@@ -480,6 +594,14 @@ Projects declare their source-of-truth layout in `SSOT.yaml`, and a `qc/migratio
480
594
  ### Skills Work Together
481
595
  Skills call each other. `check-reporting` invokes `make-figures` for PRISMA diagrams. `write-paper` calls `search-lit` for citation verification. `self-review` delegates reporting compliance to `check-reporting`. `calc-sample-size` output feeds directly into `write-protocol`'s IRB justification section.
482
596
 
597
+ ### Validation status — available vs CI-gated vs evaluated
598
+ Be precise about what "validated" means here — the three tiers are different facts:
599
+ - **Available** — every bundled skill and deterministic detector. The current totals are the single source of truth in [`metadata/catalog_counts.json`](metadata/catalog_counts.json) and [`MEDSCI_AUDIT.md`](MEDSCI_AUDIT.md).
600
+ - **CI-gated** — detectors with a committed challenge/regression test that runs on every push via [`validate.yml`](.github/workflows/validate.yml).
601
+ - **Formally evaluated** — the subset measured by the canonical evaluation harness **E1** in [`evaluation/`](evaluation/), which is v3.8-era and validates the then-current detector subset; detectors added since are **CI-tested, not yet E1-evaluated** (the size of the catalog and the size of the evaluated subset are deliberately reported as separate facts — see `MEDSCI_AUDIT.md`).
602
+
603
+ The toolkit is *designed to reduce common manuscript-preparation errors*; it does **not** guarantee correctness and is **not** clinically validated.
604
+
483
605
  ## Setup
484
606
 
485
607
  **New to Python, R, or the command line?** The full step-by-step guide for clinicians is in [`docs/setup/`](docs/setup/README.md):
@@ -567,6 +689,35 @@ Or equivalently: `/write-paper --autonomous` if analysis and figures already exi
567
689
  /search-lit # Find supporting literature with verified citations
568
690
  ```
569
691
 
692
+ ## Contributing
693
+
694
+ Contributions are welcome — and most are **one small, self-contained file** that a
695
+ template walks you through. You do not need to understand the whole pipeline to add value.
696
+ Pick a [**good first issue**](https://github.com/Aperivue/medsci-skills/contribute), or start
697
+ from one of these:
698
+
699
+ | Want to add… | How | Issue |
700
+ |---|---|---|
701
+ | **A journal profile** (submission rules for a journal we don't cover) | `/add-journal`, or copy an existing `journal_profiles/*.md` | [#115](https://github.com/Aperivue/medsci-skills/issues/115) |
702
+ | **A figure exemplar** (ROC, KM, forest, Bland–Altman, confusion matrix…) | one `make-figures/references/exemplar_plots/*.md` anatomy model | [#118](https://github.com/Aperivue/medsci-skills/issues/118) |
703
+ | **A CSL citation style** for a journal that lacks one | drop a `.csl` into `manage-refs/citation_styles/` | [#117](https://github.com/Aperivue/medsci-skills/issues/117) |
704
+ | **A de-identification locale pack** for one more country | add patterns to `deidentify/` | [#116](https://github.com/Aperivue/medsci-skills/issues/116) |
705
+ | **A reporting checklist or peer-review exemplar** | one reference file in the matching skill | [#120](https://github.com/Aperivue/medsci-skills/issues/120) |
706
+ | **A README translation** (e.g., zh-CN) | a translated `README` | [#119](https://github.com/Aperivue/medsci-skills/issues/119) |
707
+
708
+ Every contribution is gated the same way the maintainers are: it must be a self-contained
709
+ file, pass the CI (`validate.yml` — PII scan, structure, catalog consistency), and carry no
710
+ patient or author identifiers. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the PR checklist
711
+ and the PII/publication hygiene rules. New ideas that don't fit a template? Open a
712
+ [skill request](https://github.com/Aperivue/medsci-skills/issues/new?template=skill_request.yml)
713
+ or a [detector request](https://github.com/Aperivue/medsci-skills/issues/new?template=detector_request.yml).
714
+
715
+ **Governance:** [`ROADMAP.md`](ROADMAP.md) (priorities + scope boundary),
716
+ [`MAINTAINERS.md`](MAINTAINERS.md) (roles — clinical authority stays with the founder),
717
+ [`docs/maintainer_workflow.md`](docs/maintainer_workflow.md) (review + release process),
718
+ and [`SECURITY.md`](SECURITY.md) (vulnerability reporting + the medical-scope boundary).
719
+ A change that touches a medical/research claim needs Clinical-Lead review.
720
+
570
721
  ## In the Wild
571
722
 
572
723
  Adoption is tracked openly in [`IMPACT.md`](IMPACT.md) (stars, forks, traffic,
@@ -577,6 +728,18 @@ and academic use is logged in [`docs/citations.md`](docs/citations.md).
577
728
  [let us know](https://github.com/Aperivue/medsci-skills/issues/new?template=used-in-research.yml).
578
729
  It helps other researchers find the toolkit — and we list it (with your permission).
579
730
 
731
+ ## Citation
732
+
733
+ If you use MedSci Skills in your research, please cite the software via
734
+ [`CITATION.cff`](CITATION.cff) (Zenodo concept DOI
735
+ [10.5281/zenodo.20155321](https://doi.org/10.5281/zenodo.20155321)).
736
+
737
+ The design and evaluation of the toolkit are described in a preprint:
738
+
739
+ > Nam Y, Kim N. *Agentic Skills for Auditable and Reproducible Medical Research
740
+ > Writing: An Integrity-gated Architecture for LLM-Assisted Clinical Manuscripts.*
741
+ > arXiv:2606.09500 (2026). https://arxiv.org/abs/2606.09500
742
+
580
743
  ## Disclaimer
581
744
 
582
745
  These skills are research productivity tools. They do **not** provide clinical decision support, medical advice, or diagnostic recommendations. All outputs should be reviewed by qualified researchers before use in any publication or clinical context.
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env python3
2
2
  """Install MedSci Skills for local agent apps.
3
3
 
4
- This installer is intentionally conservative and dependency-free. It copies the
5
- repository's skills into common local skill folders and optionally writes a
6
- small Cursor project rule that tells Cursor where to find the skills.
4
+ Dependency-free. Installs the repository's skills into common local skill folders via a
5
+ **transactional, crash-recoverable** install (see installers/medsci_txn.py) so an
6
+ interrupted install is recovered on the next run, and optionally writes a small Cursor
7
+ project rule. No network access here.
7
8
  """
8
9
 
9
10
  from __future__ import annotations
@@ -11,10 +12,11 @@ from __future__ import annotations
11
12
  import argparse
12
13
  import datetime as dt
13
14
  import os
14
- import shutil
15
15
  import sys
16
16
  from pathlib import Path
17
17
 
18
+ sys.path.insert(0, str(Path(__file__).resolve().parent)) # allow `import medsci_txn` when run as a script
19
+ import medsci_txn # noqa: E402
18
20
 
19
21
  REPO_ROOT = Path(__file__).resolve().parents[1]
20
22
  SKILLS_DIR = REPO_ROOT / "skills"
@@ -53,20 +55,20 @@ def copy_skills(target: str, dest: Path, log_lines: list[str], dry_run: bool) ->
53
55
  if not SKILLS_DIR.exists():
54
56
  raise FileNotFoundError(f"skills directory not found: {SKILLS_DIR}")
55
57
 
56
- skill_dirs = sorted(p for p in SKILLS_DIR.iterdir() if p.is_dir() and (p / "SKILL.md").exists())
57
- log(f"\n[{target}] installing {len(skill_dirs)} skills to {dest}", log_lines)
58
+ owned = sorted(p.name for p in SKILLS_DIR.iterdir() if p.is_dir() and (p / "SKILL.md").exists())
59
+ log(f"\n[{target}] installing {len(owned)} skills to {dest}", log_lines)
58
60
 
59
61
  if dry_run:
60
- for skill in skill_dirs:
61
- log(f" DRY RUN copy {skill.name}", log_lines)
62
- return len(skill_dirs)
62
+ for name in owned:
63
+ log(f" DRY RUN install {name}", log_lines)
64
+ return len(owned)
63
65
 
64
- dest.mkdir(parents=True, exist_ok=True)
65
- for skill in skill_dirs:
66
- shutil.copytree(skill, dest / skill.name, dirs_exist_ok=True)
67
- log(f" installed {skill.name}", log_lines)
68
- verify_discoverable(dest, [s.name for s in skill_dirs], log_lines)
69
- return len(skill_dirs)
66
+ result = medsci_txn.install_target(
67
+ SKILLS_DIR, dest, target, owned, medsci_txn.state_home(),
68
+ lambda m: log(m, log_lines),
69
+ )
70
+ verify_discoverable(dest, owned, log_lines)
71
+ return result["installed"]
70
72
 
71
73
 
72
74
  def install_cursor_rule(project: Path, log_lines: list[str], dry_run: bool) -> None:
@@ -116,29 +118,44 @@ def run_self_test() -> int:
116
118
  problems: list[str] = []
117
119
  sink: list[str] = []
118
120
 
119
- # Snapshot real host dirs to prove the self-test never creates them.
121
+ # Snapshot real host + state dirs to prove the self-test never creates them.
120
122
  host_dirs = [default_target_dir("claude"), default_target_dir("codex")]
121
- existed_before = {d: d.exists() for d in host_dirs}
123
+ real_state = medsci_txn.state_home()
124
+ watched = host_dirs + [real_state]
125
+ existed_before = {d: d.exists() for d in watched}
122
126
 
127
+ prev_home = os.environ.get("MEDSCI_HOME")
123
128
  with tempfile.TemporaryDirectory(prefix="medsci-selftest-") as tmp:
124
129
  tmp_path = Path(tmp)
125
- dest = tmp_path / "skills"
130
+ os.environ["MEDSCI_HOME"] = str(tmp_path / "state") # isolate transactional state to temp
126
131
  try:
127
- copied = copy_skills("self-test", dest, sink, dry_run=False) # includes verify_discoverable
128
- except Exception as exc: # noqa: BLE001
129
- problems.append(f"copy/verify raised: {exc}")
130
- copied = -1
131
- if copied != n:
132
- problems.append(f"copied {copied} != source skill count {n}")
133
-
134
- proj = tmp_path / "project"
135
- install_cursor_rule(proj, sink, dry_run=False)
136
- if not (proj / ".cursor" / "rules" / "medsci-skills.mdc").is_file():
137
- problems.append("cursor project rule was not written")
138
-
139
- for d in host_dirs:
132
+ dest = tmp_path / "skills"
133
+ try:
134
+ copied = copy_skills("self-test", dest, sink, dry_run=False) # transactional + verify
135
+ except Exception as exc: # noqa: BLE001
136
+ problems.append(f"install/verify raised: {exc}")
137
+ copied = -1
138
+ if copied != n:
139
+ problems.append(f"installed {copied} != source skill count {n}")
140
+ # a second install must be idempotent (recovery + re-commit, no error)
141
+ try:
142
+ copy_skills("self-test", dest, sink, dry_run=False)
143
+ except Exception as exc: # noqa: BLE001
144
+ problems.append(f"second (idempotent) install raised: {exc}")
145
+
146
+ proj = tmp_path / "project"
147
+ install_cursor_rule(proj, sink, dry_run=False)
148
+ if not (proj / ".cursor" / "rules" / "medsci-skills.mdc").is_file():
149
+ problems.append("cursor project rule was not written")
150
+ finally:
151
+ if prev_home is None:
152
+ os.environ.pop("MEDSCI_HOME", None)
153
+ else:
154
+ os.environ["MEDSCI_HOME"] = prev_home
155
+
156
+ for d in watched:
140
157
  if not existed_before[d] and d.exists():
141
- problems.append(f"self-test created a real host dir: {d}")
158
+ problems.append(f"self-test created a real dir: {d}")
142
159
 
143
160
  print("MedSci Skills installer self-test")
144
161
  print(f" source skills: {n}")
@@ -146,7 +163,7 @@ def run_self_test() -> int:
146
163
  for p in problems:
147
164
  print(f" FAIL: {p}")
148
165
  return 1
149
- print(f" OK: {n}/{n} skills discoverable in temp target; cursor rule written; no host dir touched")
166
+ print(f" OK: {n}/{n} skills discoverable in temp target; idempotent; cursor rule written; no host/state dir touched")
150
167
  return 0
151
168
 
152
169
 
@@ -177,6 +194,27 @@ def parse_args() -> argparse.Namespace:
177
194
  action="store_true",
178
195
  help="Simulate installs into temp dirs, assert all skills are discoverable, and touch no host directory. Exits 0 on pass.",
179
196
  )
197
+ parser.add_argument(
198
+ "--check-update",
199
+ action="store_true",
200
+ help="Report whether a newer release is available (connects to GitHub; installs nothing).",
201
+ )
202
+ parser.add_argument(
203
+ "--desktop-launcher",
204
+ action="store_true",
205
+ help="With your consent, also place an 'Update MedSci Skills' launcher on your Desktop.",
206
+ )
207
+ parser.add_argument(
208
+ "--enable-update-notify",
209
+ action="store_true",
210
+ help="Opt in: show a one-line 'update available' notice at Claude Code session start "
211
+ "(merges a hook into ~/.claude/settings.json; 24h-cached; no telemetry).",
212
+ )
213
+ parser.add_argument(
214
+ "--disable-update-notify",
215
+ action="store_true",
216
+ help="Opt out: remove the session-start update-notice hook from ~/.claude/settings.json.",
217
+ )
180
218
  return parser.parse_args()
181
219
 
182
220
 
@@ -184,31 +222,80 @@ def main() -> int:
184
222
  args = parse_args()
185
223
  if args.self_test:
186
224
  return run_self_test()
225
+ if args.check_update:
226
+ try:
227
+ import update # noqa: PLC0415 - optional, only when explicitly requested
228
+ return update.check_update(medsci_txn.state_home())
229
+ except Exception as exc: # noqa: BLE001
230
+ print(f"MedSci Skills: update check unavailable ({exc}).", file=sys.stderr)
231
+ return 1
232
+ if args.enable_update_notify or args.disable_update_notify:
233
+ try:
234
+ import update # noqa: PLC0415
235
+ home = medsci_txn.state_home()
236
+ if args.disable_update_notify:
237
+ r = update.unregister_session_hook(home, update.default_settings_path())
238
+ print("Session-start update notice disabled." if r == "disabled"
239
+ else "Session-start update notice was not enabled; nothing to do.")
240
+ return 0
241
+ # Opt-in: ensure the updater home (with the hook script) exists, then register the hook.
242
+ update.install_updater_home(REPO_ROOT, home, lambda _m: None)
243
+ r = update.register_session_hook(home, update.default_settings_path())
244
+ print("Opted in: Claude Code will show a one-line update notice at session start "
245
+ "(24h-cached, no telemetry). Disable with: install.py --disable-update-notify"
246
+ if r == "enabled" else "Already opted in to the session-start update notice; no change.")
247
+ return 0
248
+ except Exception as exc: # noqa: BLE001
249
+ print(f"MedSci Skills: could not change the update-notify setting ({exc}).", file=sys.stderr)
250
+ return 1
187
251
  log_lines: list[str] = []
188
252
  log("MedSci Skills Installer", log_lines)
189
253
  log(f"Repository: {REPO_ROOT}", log_lines)
190
254
  log(f"Python: {sys.version.split()[0]}", log_lines)
191
255
  log(f"OS: {os.name}", log_lines)
192
256
 
257
+ # Each target is an independent transaction: a failure on one (e.g. a fail-closed corrupt
258
+ # journal) is logged and the others still proceed; successful targets are fully committed.
259
+ targets = [t for t in ("claude", "codex") if args.target in {"all", t}]
260
+ failures: list[str] = []
261
+ for t in targets:
262
+ try:
263
+ copy_skills(t, default_target_dir(t), log_lines, args.dry_run)
264
+ except Exception as exc: # noqa: BLE001 - classroom installer shows friendly per-target errors.
265
+ failures.append(t)
266
+ log(f"\n[{t}] FAILED: {exc}", log_lines)
267
+ log(f" [{t}] left unchanged (transactional); other targets continue.", log_lines)
268
+
193
269
  try:
194
- if args.target in {"all", "claude"}:
195
- copy_skills("claude", default_target_dir("claude"), log_lines, args.dry_run)
196
- if args.target in {"all", "codex"}:
197
- copy_skills("codex", default_target_dir("codex"), log_lines, args.dry_run)
198
270
  if args.target == "cursor" and not args.cursor_project:
199
271
  log("\n[cursor] skipped: pass --cursor-project <folder> to install a Cursor rule.", log_lines)
200
272
  if args.cursor_project:
201
273
  install_cursor_rule(args.cursor_project.expanduser().resolve(), log_lines, args.dry_run)
274
+ except Exception as exc: # noqa: BLE001
275
+ failures.append("cursor")
276
+ log(f"\n[cursor] FAILED: {exc}", log_lines)
277
+
278
+ # Place the one-click updater under ~/.medsci-skills/updater/ so a future update needs no
279
+ # GitHub/terminal even if this download folder is deleted (best-effort; never fatal).
280
+ if not args.dry_run:
281
+ try:
282
+ import update # noqa: PLC0415
283
+ update.install_updater_home(REPO_ROOT, medsci_txn.state_home(),
284
+ lambda m: log(m, log_lines),
285
+ desktop=args.desktop_launcher)
286
+ except Exception as exc: # noqa: BLE001
287
+ log(f"\n[updater] could not install the one-click updater ({exc}); updates still work via re-running the installer.", log_lines)
202
288
 
203
- log("\nDone. Restart Claude Code, Codex, or Cursor before testing the skills.", log_lines)
204
- log("First test prompt:", log_lines)
205
- log("MedSci Skills가 설치됐는지 확인하고, 오늘 실습에 쓸 대표 스킬 5개만 보여줘.", log_lines)
206
- except Exception as exc: # noqa: BLE001 - classroom installer should show friendly errors.
207
- log(f"\nERROR: {exc}", log_lines)
289
+ if failures:
290
+ log(f"\nCompleted with errors on: {', '.join(failures)}. Other targets are fully installed.", log_lines)
208
291
  log("If this happened during class, send the install log to the instructor.", log_lines)
209
- write_log(log_lines)
292
+ log_path = write_log(log_lines)
293
+ print(f"\nInstall log: {log_path}")
210
294
  return 1
211
295
 
296
+ log("\nDone. Restart Claude Code, Codex, or Cursor before testing the skills.", log_lines)
297
+ log("First test prompt:", log_lines)
298
+ log("MedSci Skills가 설치됐는지 확인하고, 오늘 실습에 쓸 대표 스킬 5개만 보여줘.", log_lines)
212
299
  log_path = write_log(log_lines)
213
300
  print(f"\nInstall log: {log_path}")
214
301
  return 0