medsci-skills 4.1.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 (702) hide show
  1. package/LICENSE +50 -0
  2. package/README.md +602 -0
  3. package/README_FIRST.md +27 -0
  4. package/bin/medsci-skills.js +159 -0
  5. package/installers/install-macos.command +19 -0
  6. package/installers/install-windows.cmd +26 -0
  7. package/installers/install-windows.ps1 +17 -0
  8. package/installers/install.py +218 -0
  9. package/metadata/skills_catalog.json +452 -0
  10. package/package.json +48 -0
  11. package/skills/academic-aio/SKILL.md +408 -0
  12. package/skills/academic-aio/references/case_studies/kjr_mllm_2025.md +82 -0
  13. package/skills/academic-aio/references/checklists/AIO_GENERAL.md +354 -0
  14. package/skills/academic-aio/references/journal_summarybox_templates.yaml +126 -0
  15. package/skills/academic-aio/references/oac_funding_checklist.yaml +129 -0
  16. package/skills/academic-aio/references/reporting_guideline_mapping.md +39 -0
  17. package/skills/academic-aio/references/schema_markup_templates/CodeRepository.jsonld +32 -0
  18. package/skills/academic-aio/references/schema_markup_templates/Dataset.jsonld +36 -0
  19. package/skills/academic-aio/references/schema_markup_templates/Person.jsonld +30 -0
  20. package/skills/academic-aio/references/schema_markup_templates/README.md +43 -0
  21. package/skills/academic-aio/references/schema_markup_templates/ScholarlyArticle.jsonld +55 -0
  22. package/skills/academic-aio/scripts/batch_metadata_audit.py +169 -0
  23. package/skills/academic-aio/scripts/validate_schema.py +118 -0
  24. package/skills/academic-aio/skill.yml +36 -0
  25. package/skills/academic-aio/templates/aio_audit_checklist.md.j2 +108 -0
  26. package/skills/add-journal/SKILL.md +482 -0
  27. package/skills/add-journal/skill.yml +33 -0
  28. package/skills/analyze-stats/SKILL.md +598 -0
  29. package/skills/analyze-stats/references/analysis_guides/missing_data.md +109 -0
  30. package/skills/analyze-stats/references/analysis_guides/nhis_icd10_mapping.md +247 -0
  31. package/skills/analyze-stats/references/analysis_guides/propensity_score.md +132 -0
  32. package/skills/analyze-stats/references/analysis_guides/regression.md +115 -0
  33. package/skills/analyze-stats/references/analysis_guides/repeated_measures.md +160 -0
  34. package/skills/analyze-stats/references/analysis_guides/survey_weighted.md +366 -0
  35. package/skills/analyze-stats/references/analysis_guides/test_selection.md +86 -0
  36. package/skills/analyze-stats/references/style/figure_style.mplstyle +69 -0
  37. package/skills/analyze-stats/references/style/theme_publication.R +147 -0
  38. package/skills/analyze-stats/references/table-standards/journal-profiles/ajr.yaml +51 -0
  39. package/skills/analyze-stats/references/table-standards/journal-profiles/european_radiology.yaml +55 -0
  40. package/skills/analyze-stats/references/table-standards/journal-profiles/jama.yaml +66 -0
  41. package/skills/analyze-stats/references/table-standards/journal-profiles/lancet.yaml +57 -0
  42. package/skills/analyze-stats/references/table-standards/journal-profiles/nejm.yaml +51 -0
  43. package/skills/analyze-stats/references/table-standards/journal-profiles/radiology.yaml +66 -0
  44. package/skills/analyze-stats/references/table-standards/table-standards.md +287 -0
  45. package/skills/analyze-stats/references/table-standards/table-types/diagnostic_accuracy.md +36 -0
  46. package/skills/analyze-stats/references/table-standards/table-types/meta_analysis.md +58 -0
  47. package/skills/analyze-stats/references/table-standards/table-types/model_comparison.md +36 -0
  48. package/skills/analyze-stats/references/table-standards/table-types/regression_results.md +50 -0
  49. package/skills/analyze-stats/references/table-standards/table-types/table1_demographics.md +51 -0
  50. package/skills/analyze-stats/references/table-standards/tool-comparison.md +79 -0
  51. package/skills/analyze-stats/references/templates/agreement_analysis.py +436 -0
  52. package/skills/analyze-stats/references/templates/dca_plot.R +237 -0
  53. package/skills/analyze-stats/references/templates/diagnostic_accuracy.py +401 -0
  54. package/skills/analyze-stats/references/templates/dta_meta_analysis.R +384 -0
  55. package/skills/analyze-stats/references/templates/forest_plot.py +412 -0
  56. package/skills/analyze-stats/references/templates/likert_summary.py +356 -0
  57. package/skills/analyze-stats/references/templates/meta_analysis.R +365 -0
  58. package/skills/analyze-stats/references/templates/propensity_score.py +478 -0
  59. package/skills/analyze-stats/references/templates/regression.py +425 -0
  60. package/skills/analyze-stats/references/templates/repeated_measures.py +434 -0
  61. package/skills/analyze-stats/references/templates/sample_size.R +382 -0
  62. package/skills/analyze-stats/references/templates/survey_weighted_analysis.py +411 -0
  63. package/skills/analyze-stats/references/templates/survival_analysis.py +325 -0
  64. package/skills/analyze-stats/references/templates/table1_demographics.py +287 -0
  65. package/skills/analyze-stats/scripts/check_generated_code.py +335 -0
  66. package/skills/analyze-stats/skill.yml +38 -0
  67. package/skills/analyze-stats/tests/fixtures/gen_bad.R +16 -0
  68. package/skills/analyze-stats/tests/fixtures/gen_bad.py +24 -0
  69. package/skills/analyze-stats/tests/fixtures/gen_clean.py +21 -0
  70. package/skills/analyze-stats/tests/test_generated_code.sh +59 -0
  71. package/skills/analyze-stats/tests/test_survival_template.sh +53 -0
  72. package/skills/author-strategy/SKILL.md +117 -0
  73. package/skills/author-strategy/analyze_patterns.py +303 -0
  74. package/skills/author-strategy/fetch_pubmed.py +374 -0
  75. package/skills/author-strategy/skill.yml +34 -0
  76. package/skills/batch-cohort/SKILL.md +223 -0
  77. package/skills/batch-cohort/references/base_template_knhanes.R +210 -0
  78. package/skills/batch-cohort/references/batch_template_generator.R +222 -0
  79. package/skills/batch-cohort/references/variable_coding_registry.md +136 -0
  80. package/skills/batch-cohort/skill.yml +35 -0
  81. package/skills/calc-sample-size/SKILL.md +491 -0
  82. package/skills/calc-sample-size/references/formulas.md +655 -0
  83. package/skills/calc-sample-size/references/observational_cohort.md +49 -0
  84. package/skills/calc-sample-size/skill.yml +51 -0
  85. package/skills/check-reporting/SKILL.md +534 -0
  86. package/skills/check-reporting/references/LICENSES.md +41 -0
  87. package/skills/check-reporting/references/checklists/AMSTAR2.md +54 -0
  88. package/skills/check-reporting/references/checklists/ARRIVE_2.md +234 -0
  89. package/skills/check-reporting/references/checklists/CARE.md +102 -0
  90. package/skills/check-reporting/references/checklists/CLAIM_2024.md +128 -0
  91. package/skills/check-reporting/references/checklists/CLEAR.md +113 -0
  92. package/skills/check-reporting/references/checklists/CONSORT.md +86 -0
  93. package/skills/check-reporting/references/checklists/COSMIN_RoB.md +136 -0
  94. package/skills/check-reporting/references/checklists/GRRAS.md +61 -0
  95. package/skills/check-reporting/references/checklists/MI_CLEAR_LLM.md +167 -0
  96. package/skills/check-reporting/references/checklists/MOOSE.md +85 -0
  97. package/skills/check-reporting/references/checklists/NOS.md +88 -0
  98. package/skills/check-reporting/references/checklists/PRISMA_2020.md +135 -0
  99. package/skills/check-reporting/references/checklists/PRISMA_DTA.md +36 -0
  100. package/skills/check-reporting/references/checklists/PRISMA_P.md +56 -0
  101. package/skills/check-reporting/references/checklists/PROBAST.md +75 -0
  102. package/skills/check-reporting/references/checklists/PROBAST_AI.md +130 -0
  103. package/skills/check-reporting/references/checklists/QUADAS2.md +77 -0
  104. package/skills/check-reporting/references/checklists/QUADAS_C.md +131 -0
  105. package/skills/check-reporting/references/checklists/ROBINS_E.md +179 -0
  106. package/skills/check-reporting/references/checklists/ROBINS_I.md +87 -0
  107. package/skills/check-reporting/references/checklists/ROBIS.md +114 -0
  108. package/skills/check-reporting/references/checklists/ROB_ME.md +126 -0
  109. package/skills/check-reporting/references/checklists/RoB2.md +79 -0
  110. package/skills/check-reporting/references/checklists/RoB_NMA.md +96 -0
  111. package/skills/check-reporting/references/checklists/SPIRIT.md +112 -0
  112. package/skills/check-reporting/references/checklists/SQUIRE_2.md +68 -0
  113. package/skills/check-reporting/references/checklists/STARD.md +129 -0
  114. package/skills/check-reporting/references/checklists/STARD_AI.md +211 -0
  115. package/skills/check-reporting/references/checklists/STROBE.md +80 -0
  116. package/skills/check-reporting/references/checklists/SWiM.md +33 -0
  117. package/skills/check-reporting/references/checklists/TRIPOD.md +157 -0
  118. package/skills/check-reporting/references/checklists/TRIPOD_AI.md +140 -0
  119. package/skills/check-reporting/references/step4c_registration_timing.md +93 -0
  120. package/skills/check-reporting/references/step4d_prisma_figure_audit.md +137 -0
  121. package/skills/check-reporting/scripts/check_checklist_exists.py +183 -0
  122. package/skills/check-reporting/scripts/check_checklist_version.py +168 -0
  123. package/skills/check-reporting/scripts/check_framework_naming.py +206 -0
  124. package/skills/check-reporting/scripts/check_prisma_figure.py +209 -0
  125. package/skills/check-reporting/scripts/prisma_cascade_check.py +274 -0
  126. package/skills/check-reporting/skill.yml +41 -0
  127. package/skills/check-reporting/tests/fixtures/framework_bad.md +8 -0
  128. package/skills/check-reporting/tests/fixtures/framework_clean.md +7 -0
  129. package/skills/check-reporting/tests/test_checklist_fail_fast.sh +77 -0
  130. package/skills/check-reporting/tests/test_checklist_version.sh +72 -0
  131. package/skills/check-reporting/tests/test_framework_naming.sh +45 -0
  132. package/skills/check-reporting/tests/test_prisma_cascade.sh +104 -0
  133. package/skills/clean-data/SKILL.md +180 -0
  134. package/skills/clean-data/references/cleaning_patterns.md +299 -0
  135. package/skills/clean-data/references/profiling_template.py +304 -0
  136. package/skills/clean-data/scripts/check_structural_zero.py +174 -0
  137. package/skills/clean-data/skill.yml +35 -0
  138. package/skills/clean-data/tests/fixtures/smoking.csv +8 -0
  139. package/skills/clean-data/tests/test_structural_zero.sh +49 -0
  140. package/skills/cross-national/SKILL.md +264 -0
  141. package/skills/cross-national/skill.yml +37 -0
  142. package/skills/define-variables/SKILL.md +146 -0
  143. package/skills/define-variables/references/common_definitions.md +190 -0
  144. package/skills/define-variables/skill.yml +34 -0
  145. package/skills/define-variables/templates/variable_operationalization.md +64 -0
  146. package/skills/deidentify/SKILL.md +203 -0
  147. package/skills/deidentify/deidentify.py +1224 -0
  148. package/skills/deidentify/locales/_template.json +45 -0
  149. package/skills/deidentify/locales/au.json +43 -0
  150. package/skills/deidentify/locales/ca.json +44 -0
  151. package/skills/deidentify/locales/cn.json +47 -0
  152. package/skills/deidentify/locales/de.json +48 -0
  153. package/skills/deidentify/locales/fr.json +48 -0
  154. package/skills/deidentify/locales/in.json +48 -0
  155. package/skills/deidentify/locales/jp.json +48 -0
  156. package/skills/deidentify/locales/kr.json +48 -0
  157. package/skills/deidentify/locales/uk.json +45 -0
  158. package/skills/deidentify/locales/us.json +43 -0
  159. package/skills/deidentify/references/date_shift_guide.md +82 -0
  160. package/skills/deidentify/references/hipaa_18_identifiers.md +48 -0
  161. package/skills/deidentify/references/korean_phi_patterns.md +135 -0
  162. package/skills/deidentify/skill.yml +43 -0
  163. package/skills/deidentify/tests/README.md +26 -0
  164. package/skills/deidentify/tests/test_clean.csv +16 -0
  165. package/skills/deidentify/tests/test_edge_cases.csv +11 -0
  166. package/skills/deidentify/tests/test_phi_korean.csv +11 -0
  167. package/skills/design-ai-benchmarking/SKILL.md +214 -0
  168. package/skills/design-ai-benchmarking/references/benchmark_export_schema.json +69 -0
  169. package/skills/design-ai-benchmarking/references/elicitation_rubric_template.md +37 -0
  170. package/skills/design-ai-benchmarking/skill.yml +38 -0
  171. package/skills/design-study/SKILL.md +298 -0
  172. package/skills/design-study/skill.yml +33 -0
  173. package/skills/fill-icmje-coi/SKILL.md +216 -0
  174. package/skills/fill-icmje-coi/scripts/fill_icmje_coi.py +140 -0
  175. package/skills/fill-icmje-coi/skill.yml +35 -0
  176. package/skills/fill-icmje-coi/templates/icmje_coi_seed_synthetic.docx +0 -0
  177. package/skills/fill-protocol/SKILL.md +248 -0
  178. package/skills/fill-protocol/examples/example_irb_template.yaml +53 -0
  179. package/skills/fill-protocol/references/best_practices.md +121 -0
  180. package/skills/fill-protocol/scripts/doc_to_docx.py +111 -0
  181. package/skills/fill-protocol/scripts/fill_form.py +611 -0
  182. package/skills/fill-protocol/scripts/inspect_template.py +61 -0
  183. package/skills/fill-protocol/setup.sh +162 -0
  184. package/skills/fill-protocol/skill.yml +37 -0
  185. package/skills/find-cohort-gap/SKILL.md +309 -0
  186. package/skills/find-cohort-gap/references/cohort_profile_template.md +93 -0
  187. package/skills/find-cohort-gap/references/onepager_template.md +84 -0
  188. package/skills/find-cohort-gap/references/pattern_scoring_rubric.md +169 -0
  189. package/skills/find-cohort-gap/references/saturation_query_templates.md +143 -0
  190. package/skills/find-cohort-gap/skill.yml +35 -0
  191. package/skills/find-journal/POLICY.md +87 -0
  192. package/skills/find-journal/SKILL.md +340 -0
  193. package/skills/find-journal/references/journal_profiles/AJNR.md +29 -0
  194. package/skills/find-journal/references/journal_profiles/AJR.md +30 -0
  195. package/skills/find-journal/references/journal_profiles/Abdominal_Radiology.md +30 -0
  196. package/skills/find-journal/references/journal_profiles/Academic_Radiology.md +30 -0
  197. package/skills/find-journal/references/journal_profiles/Annals_of_Internal_Medicine.md +33 -0
  198. package/skills/find-journal/references/journal_profiles/Artificial_Intelligence_in_Medicine.md +28 -0
  199. package/skills/find-journal/references/journal_profiles/BMC_Medicine.md +31 -0
  200. package/skills/find-journal/references/journal_profiles/British_Journal_of_Radiology.md +39 -0
  201. package/skills/find-journal/references/journal_profiles/CVIR.md +30 -0
  202. package/skills/find-journal/references/journal_profiles/Chest.md +39 -0
  203. package/skills/find-journal/references/journal_profiles/Clinical_Radiology.md +30 -0
  204. package/skills/find-journal/references/journal_profiles/Clinical_and_Molecular_Hepatology.md +32 -0
  205. package/skills/find-journal/references/journal_profiles/Diabetes_Metabolism_Journal.md +36 -0
  206. package/skills/find-journal/references/journal_profiles/Diagnostic_and_Interventional_Radiology.md +32 -0
  207. package/skills/find-journal/references/journal_profiles/Endocrinology_and_Metabolism.md +37 -0
  208. package/skills/find-journal/references/journal_profiles/European_Journal_of_Preventive_Cardiology.md +39 -0
  209. package/skills/find-journal/references/journal_profiles/European_Radiology.md +29 -0
  210. package/skills/find-journal/references/journal_profiles/Hepatology_Communications.md +40 -0
  211. package/skills/find-journal/references/journal_profiles/Hepatology_International.md +37 -0
  212. package/skills/find-journal/references/journal_profiles/IEEE_JBHI.md +28 -0
  213. package/skills/find-journal/references/journal_profiles/IEEE_TMI.md +28 -0
  214. package/skills/find-journal/references/journal_profiles/INSI.md +29 -0
  215. package/skills/find-journal/references/journal_profiles/Investigative_Radiology.md +25 -0
  216. package/skills/find-journal/references/journal_profiles/JACC_Advances.md +41 -0
  217. package/skills/find-journal/references/journal_profiles/JACC_Asia.md +30 -0
  218. package/skills/find-journal/references/journal_profiles/JACR.md +28 -0
  219. package/skills/find-journal/references/journal_profiles/JAMA.md +40 -0
  220. package/skills/find-journal/references/journal_profiles/JAMA_Network_Open.md +30 -0
  221. package/skills/find-journal/references/journal_profiles/JCSM.md +39 -0
  222. package/skills/find-journal/references/journal_profiles/JKMS.md +32 -0
  223. package/skills/find-journal/references/journal_profiles/JMIR.md +29 -0
  224. package/skills/find-journal/references/journal_profiles/JMIR_Medical_Education.md +29 -0
  225. package/skills/find-journal/references/journal_profiles/JNIS.md +35 -0
  226. package/skills/find-journal/references/journal_profiles/JVIR.md +31 -0
  227. package/skills/find-journal/references/journal_profiles/Journal_of_Biomedical_Informatics.md +29 -0
  228. package/skills/find-journal/references/journal_profiles/Journal_of_Clinical_Endocrinology_and_Metabolism.md +40 -0
  229. package/skills/find-journal/references/journal_profiles/Journal_of_Magnetic_Resonance_Imaging.md +30 -0
  230. package/skills/find-journal/references/journal_profiles/Journal_of_Nuclear_Medicine.md +31 -0
  231. package/skills/find-journal/references/journal_profiles/Journal_of_Stroke.md +32 -0
  232. package/skills/find-journal/references/journal_profiles/KJR.md +38 -0
  233. package/skills/find-journal/references/journal_profiles/Korean_Circulation_Journal.md +38 -0
  234. package/skills/find-journal/references/journal_profiles/Korean_Journal_of_Internal_Medicine.md +36 -0
  235. package/skills/find-journal/references/journal_profiles/Lancet_Diabetes_and_Endocrinology.md +40 -0
  236. package/skills/find-journal/references/journal_profiles/Lancet_Gastroenterology_and_Hepatology.md +49 -0
  237. package/skills/find-journal/references/journal_profiles/Lancet_Infectious_Diseases.md +38 -0
  238. package/skills/find-journal/references/journal_profiles/Lancet_Neurology.md +39 -0
  239. package/skills/find-journal/references/journal_profiles/Lancet_Oncology.md +40 -0
  240. package/skills/find-journal/references/journal_profiles/Lancet_Psychiatry.md +38 -0
  241. package/skills/find-journal/references/journal_profiles/Lancet_Public_Health.md +30 -0
  242. package/skills/find-journal/references/journal_profiles/Lancet_Respiratory_Medicine.md +39 -0
  243. package/skills/find-journal/references/journal_profiles/Liver_International.md +33 -0
  244. package/skills/find-journal/references/journal_profiles/Medical_Image_Analysis.md +28 -0
  245. package/skills/find-journal/references/journal_profiles/NEJM.md +33 -0
  246. package/skills/find-journal/references/journal_profiles/Nature_Machine_Intelligence.md +31 -0
  247. package/skills/find-journal/references/journal_profiles/Nature_Medicine.md +39 -0
  248. package/skills/find-journal/references/journal_profiles/Neuroradiology.md +31 -0
  249. package/skills/find-journal/references/journal_profiles/Nutrition_Metabolism_and_Cardiovascular_Diseases.md +39 -0
  250. package/skills/find-journal/references/journal_profiles/PLOS_Medicine.md +32 -0
  251. package/skills/find-journal/references/journal_profiles/RYAI.md +28 -0
  252. package/skills/find-journal/references/journal_profiles/Radiology.md +29 -0
  253. package/skills/find-journal/references/journal_profiles/Skeletal_Radiology.md +31 -0
  254. package/skills/find-journal/references/journal_profiles/Stroke.md +37 -0
  255. package/skills/find-journal/references/journal_profiles/The_BMJ.md +31 -0
  256. package/skills/find-journal/references/journal_profiles/The_Lancet.md +31 -0
  257. package/skills/find-journal/references/journal_profiles/The_Lancet_Digital_Health.md +29 -0
  258. package/skills/find-journal/references/journal_profiles/World_Journal_of_Hepatology.md +53 -0
  259. package/skills/find-journal/references/journal_profiles/npj_Digital_Medicine.md +29 -0
  260. package/skills/find-journal/skill.yml +34 -0
  261. package/skills/fulltext-retrieval/SKILL.md +174 -0
  262. package/skills/fulltext-retrieval/fetch_oa.py +433 -0
  263. package/skills/fulltext-retrieval/pdf_to_md.py +160 -0
  264. package/skills/fulltext-retrieval/skill.yml +41 -0
  265. package/skills/generate-codebook/SKILL.md +155 -0
  266. package/skills/generate-codebook/references/codebook_schema.md +76 -0
  267. package/skills/generate-codebook/scripts/generate_codebook.py +278 -0
  268. package/skills/generate-codebook/skill.yml +35 -0
  269. package/skills/generate-codebook/tests/test_generate_codebook.sh +76 -0
  270. package/skills/grant-builder/SKILL.md +251 -0
  271. package/skills/grant-builder/skill.yml +34 -0
  272. package/skills/humanize/SKILL.md +251 -0
  273. package/skills/humanize/references/ai_patterns.md +571 -0
  274. package/skills/humanize/skill.yml +33 -0
  275. package/skills/intake-project/SKILL.md +264 -0
  276. package/skills/intake-project/skill.yml +34 -0
  277. package/skills/lit-sync/SKILL.md +448 -0
  278. package/skills/lit-sync/references/locale/ko/note_templates.md +110 -0
  279. package/skills/lit-sync/skill.yml +52 -0
  280. package/skills/lit-sync/tests/test_poll_logic.sh +92 -0
  281. package/skills/ma-scout/SKILL.md +640 -0
  282. package/skills/ma-scout/references/project_readme_template.md +95 -0
  283. package/skills/ma-scout/references/project_readme_template_ko.md +82 -0
  284. package/skills/ma-scout/skill.yml +33 -0
  285. package/skills/make-figures/SKILL.md +957 -0
  286. package/skills/make-figures/references/critic_rubrics/data_plot.md +166 -0
  287. package/skills/make-figures/references/critic_rubrics/flow_diagram.md +169 -0
  288. package/skills/make-figures/references/design_principles.md +181 -0
  289. package/skills/make-figures/references/exemplar_diagrams/README.md +65 -0
  290. package/skills/make-figures/references/exemplar_diagrams/consort/README.md +15 -0
  291. package/skills/make-figures/references/exemplar_diagrams/consort/template_input.yaml +37 -0
  292. package/skills/make-figures/references/exemplar_diagrams/consort/template_output.pdf +0 -0
  293. package/skills/make-figures/references/exemplar_diagrams/consort/template_output.png +0 -0
  294. package/skills/make-figures/references/exemplar_diagrams/consort/template_output_600.png +0 -0
  295. package/skills/make-figures/references/exemplar_diagrams/other/other_02.meta.yaml +4 -0
  296. package/skills/make-figures/references/exemplar_diagrams/other/other_02.png +0 -0
  297. package/skills/make-figures/references/exemplar_diagrams/other/other_02_why.md +13 -0
  298. package/skills/make-figures/references/exemplar_diagrams/pipeline/README.md +15 -0
  299. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01.meta.yaml +4 -0
  300. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01.png +0 -0
  301. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01_why.md +13 -0
  302. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03.meta.yaml +4 -0
  303. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03.png +0 -0
  304. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03_why.md +13 -0
  305. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04.meta.yaml +4 -0
  306. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04.png +0 -0
  307. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04_why.md +13 -0
  308. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05.meta.yaml +4 -0
  309. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05.png +0 -0
  310. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05_why.md +13 -0
  311. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06.meta.yaml +4 -0
  312. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06.png +0 -0
  313. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06_why.md +13 -0
  314. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07.meta.yaml +4 -0
  315. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07.png +0 -0
  316. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07_why.md +13 -0
  317. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08.meta.yaml +4 -0
  318. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08.png +0 -0
  319. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08_why.md +13 -0
  320. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09.meta.yaml +4 -0
  321. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09.png +0 -0
  322. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09_why.md +13 -0
  323. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10.meta.yaml +4 -0
  324. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10.png +0 -0
  325. package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10_why.md +13 -0
  326. package/skills/make-figures/references/exemplar_diagrams/prisma/README.md +15 -0
  327. package/skills/make-figures/references/exemplar_diagrams/prisma/template_input.yaml +47 -0
  328. package/skills/make-figures/references/exemplar_diagrams/prisma/template_output.pdf +0 -0
  329. package/skills/make-figures/references/exemplar_diagrams/prisma/template_output.png +0 -0
  330. package/skills/make-figures/references/exemplar_diagrams/prisma/template_output_600.png +0 -0
  331. package/skills/make-figures/references/exemplar_diagrams/stard/README.md +15 -0
  332. package/skills/make-figures/references/exemplar_diagrams/stard/template_input.yaml +40 -0
  333. package/skills/make-figures/references/exemplar_diagrams/stard/template_output.pdf +0 -0
  334. package/skills/make-figures/references/exemplar_diagrams/stard/template_output.png +0 -0
  335. package/skills/make-figures/references/exemplar_diagrams/stard/template_output_600.png +0 -0
  336. package/skills/make-figures/references/exemplar_diagrams/strobe/template_input.yaml +43 -0
  337. package/skills/make-figures/references/exemplar_diagrams/strobe/template_input_pptx.yaml +43 -0
  338. package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.pdf +0 -0
  339. package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.png +0 -0
  340. package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.pptx +0 -0
  341. package/skills/make-figures/references/exemplar_diagrams/strobe/template_output_600.png +0 -0
  342. package/skills/make-figures/references/figure_specs.md +291 -0
  343. package/skills/make-figures/references/flow_diagram_lessons.md +164 -0
  344. package/skills/make-figures/references/jacc_central_illustration_principles.md +91 -0
  345. package/skills/make-figures/references/medical_illustration_sources.md +98 -0
  346. package/skills/make-figures/references/pipeline_concepts_medical_ai.md +240 -0
  347. package/skills/make-figures/references/reporting_guideline_figure_map.md +104 -0
  348. package/skills/make-figures/references/visual_abstract_templates/european_radiology.pptx +0 -0
  349. package/skills/make-figures/references/visual_abstract_templates/jacc_central_illustration.pptx +0 -0
  350. package/skills/make-figures/references/visual_abstract_templates/medsci_default.pptx +0 -0
  351. package/skills/make-figures/references/visual_abstract_templates/template_guide.md +114 -0
  352. package/skills/make-figures/scripts/build_jacc_template.py +77 -0
  353. package/skills/make-figures/scripts/build_prisma2020_template.py +371 -0
  354. package/skills/make-figures/scripts/build_strobe_template.py +351 -0
  355. package/skills/make-figures/scripts/critic_figure.py +264 -0
  356. package/skills/make-figures/scripts/derive_figure_legend_counts.py +138 -0
  357. package/skills/make-figures/scripts/extract_exemplar_from_pdf.py +186 -0
  358. package/skills/make-figures/scripts/fetch_official_templates.sh +88 -0
  359. package/skills/make-figures/scripts/fill_prisma_template.py +142 -0
  360. package/skills/make-figures/scripts/generate_flow_diagram.R +133 -0
  361. package/skills/make-figures/scripts/generate_image.py +99 -0
  362. package/skills/make-figures/scripts/generate_visual_abstract.py +438 -0
  363. package/skills/make-figures/scripts/validate_pptx_mac_compat.py +233 -0
  364. package/skills/make-figures/skill.yml +52 -0
  365. package/skills/make-figures/templates/official/NOTES.md +62 -0
  366. package/skills/make-figures/templates/official/consort2010/CONSORT_2025_editable_checklist.docx +0 -0
  367. package/skills/make-figures/templates/official/consort2010/CONSORT_2025_flow_diagram.docx +0 -0
  368. package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_new_v1.pptx +0 -0
  369. package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_new_v2.pptx +0 -0
  370. package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_updated_v2.pptx +0 -0
  371. package/skills/make-figures/templates/official/spirit2013/SPIRIT_2025_editable_checklist.docx +0 -0
  372. package/skills/make-figures/templates/official/spirit2013/SPIRIT_2025_participant_timeline.docx +0 -0
  373. package/skills/make-figures/templates/official/stard2015/STARD_2015_checklist.docx +0 -0
  374. package/skills/make-figures/templates/official/stard2015/STARD_2015_flow_diagram.pdf +0 -0
  375. package/skills/make-figures/tests/fixtures/figure1_flow.yaml +8 -0
  376. package/skills/make-figures/tests/fixtures/manuscript_ok.md +9 -0
  377. package/skills/make-figures/tests/fixtures/manuscript_stale.md +4 -0
  378. package/skills/make-figures/tests/test_legend_reconcile.sh +36 -0
  379. package/skills/manage-project/SKILL.md +358 -0
  380. package/skills/manage-project/references/pre_submission_checklist.md +53 -0
  381. package/skills/manage-project/references/project_state_template.json +37 -0
  382. package/skills/manage-project/references/scaffold_templates.md +118 -0
  383. package/skills/manage-project/references/status_output_format.md +44 -0
  384. package/skills/manage-project/references/timeline_example.md +20 -0
  385. package/skills/manage-project/skill.yml +36 -0
  386. package/skills/manage-project/templates/SSOT.yaml.template +41 -0
  387. package/skills/manage-refs/LICENSE.zotero-mcp +21 -0
  388. package/skills/manage-refs/NOTICE.md +29 -0
  389. package/skills/manage-refs/SKILL.md +289 -0
  390. package/skills/manage-refs/citation_styles/README.md +40 -0
  391. package/skills/manage-refs/citation_styles/american-journal-of-roentgenology.csl +211 -0
  392. package/skills/manage-refs/citation_styles/cardiovascular-and-interventional-radiology.csl +19 -0
  393. package/skills/manage-refs/citation_styles/european-radiology.csl +19 -0
  394. package/skills/manage-refs/citation_styles/journal-of-cachexia-sarcopenia-and-muscle.csl +150 -0
  395. package/skills/manage-refs/citation_styles/journal-of-korean-medical-science-strict.csl +533 -0
  396. package/skills/manage-refs/citation_styles/journal-of-korean-medical-science.csl +16 -0
  397. package/skills/manage-refs/citation_styles/korean-journal-of-radiology.csl +155 -0
  398. package/skills/manage-refs/citation_styles/nature.csl +189 -0
  399. package/skills/manage-refs/citation_styles/nlm-citation-sequence.csl +535 -0
  400. package/skills/manage-refs/citation_styles/radiology.csl +228 -0
  401. package/skills/manage-refs/citation_styles/springer-basic-brackets.csl +187 -0
  402. package/skills/manage-refs/citation_styles/springer-vancouver-brackets.csl +276 -0
  403. package/skills/manage-refs/citation_styles/vancouver-superscript.csl +536 -0
  404. package/skills/manage-refs/citation_styles/vancouver.csl +535 -0
  405. package/skills/manage-refs/references/REFERENCE_STYLE_SPECS.md +59 -0
  406. package/skills/manage-refs/references/check_xref_symptoms.md +35 -0
  407. package/skills/manage-refs/scripts/_vendor_citation_writer.py +600 -0
  408. package/skills/manage-refs/scripts/check_citation_keys.py +112 -0
  409. package/skills/manage-refs/scripts/check_csl_render.py +102 -0
  410. package/skills/manage-refs/scripts/check_xref.py +633 -0
  411. package/skills/manage-refs/scripts/fill_journal_abbrev.py +104 -0
  412. package/skills/manage-refs/scripts/inject_zotero_cwyw.py +133 -0
  413. package/skills/manage-refs/scripts/md_marker_convert.py +193 -0
  414. package/skills/manage-refs/scripts/pre_submission_gate.sh +238 -0
  415. package/skills/manage-refs/scripts/render_pandoc.sh +88 -0
  416. package/skills/manage-refs/skill.yml +70 -0
  417. package/skills/manage-refs/tests/fixtures/pre_submission_gate/README.md +32 -0
  418. package/skills/manage-refs/tests/fixtures/pre_submission_gate/manuscript.md +10 -0
  419. package/skills/manage-refs/tests/fixtures/pre_submission_gate/refs.bib +34 -0
  420. package/skills/manage-refs/tests/fixtures/pre_submission_gate/run.sh +117 -0
  421. package/skills/manage-refs/tests/test_vN_docx_check.sh +145 -0
  422. package/skills/meta-analysis/SKILL.md +739 -0
  423. package/skills/meta-analysis/references/LICENSES.md +21 -0
  424. package/skills/meta-analysis/references/PROSPERO_template.md +221 -0
  425. package/skills/meta-analysis/references/ai_pre_screening_template.py +245 -0
  426. package/skills/meta-analysis/references/checklists/JBI_Case_Series.md +45 -0
  427. package/skills/meta-analysis/references/checklists/NOS.md +88 -0
  428. package/skills/meta-analysis/references/checklists/PRISMA_DTA.md +36 -0
  429. package/skills/meta-analysis/references/checklists/PROBAST.md +75 -0
  430. package/skills/meta-analysis/references/checklists/QUADAS2.md +77 -0
  431. package/skills/meta-analysis/references/checklists/ROBINS_I.md +87 -0
  432. package/skills/meta-analysis/references/checklists/RoB2.md +79 -0
  433. package/skills/meta-analysis/references/data_integrity_checklist.md +57 -0
  434. package/skills/meta-analysis/references/icmje_coi_guide.md +181 -0
  435. package/skills/meta-analysis/references/phase10_recovery.md +136 -0
  436. package/skills/meta-analysis/references/phase4_km_composite.md +58 -0
  437. package/skills/meta-analysis/references/phase6_statistical_synthesis.md +148 -0
  438. package/skills/meta-analysis/references/phase9_circulation.md +84 -0
  439. package/skills/meta-analysis/references/post_submission_release_ops.md +41 -0
  440. package/skills/meta-analysis/references/r_templates.md +132 -0
  441. package/skills/meta-analysis/references/review_orchestration.md +40 -0
  442. package/skills/meta-analysis/references/submission_package_drift.md +71 -0
  443. package/skills/meta-analysis/scripts/check_pool_consistency.py +201 -0
  444. package/skills/meta-analysis/scripts/cohort_overlap_check.py +242 -0
  445. package/skills/meta-analysis/scripts/dta_extraction_qc.py +137 -0
  446. package/skills/meta-analysis/scripts/screening_reconcile.py +160 -0
  447. package/skills/meta-analysis/skill.yml +47 -0
  448. package/skills/meta-analysis/templates/FINAL_POOL_LOCK.yaml.template +70 -0
  449. package/skills/meta-analysis/templates/extraction_form_v2.md +129 -0
  450. package/skills/meta-analysis/templates/supplementary_8file_checklist.md +94 -0
  451. package/skills/meta-analysis/tests/test_pool_consistency.sh +123 -0
  452. package/skills/orchestrate/SKILL.md +501 -0
  453. package/skills/orchestrate/references/dialogue_nodes.md +196 -0
  454. package/skills/orchestrate/references/report_template.md +109 -0
  455. package/skills/orchestrate/references/report_template_ko.md +88 -0
  456. package/skills/orchestrate/skill.yml +44 -0
  457. package/skills/peer-review/SKILL.md +381 -0
  458. package/skills/peer-review/references/aczel_2021_reviewer2_patterns.md +88 -0
  459. package/skills/peer-review/references/domain-probes/ai_overclaiming.md +47 -0
  460. package/skills/peer-review/references/domain-probes/narrative_review.md +44 -0
  461. package/skills/peer-review/references/domain-probes/observational_confounding.md +48 -0
  462. package/skills/peer-review/references/domain-probes/radiomics.md +38 -0
  463. package/skills/peer-review/references/domain-probes/sr_ma.md +87 -0
  464. package/skills/peer-review/references/domain-probes/survival_prognostic.md +68 -0
  465. package/skills/peer-review/references/exemplar_reviews/README.md +43 -0
  466. package/skills/peer-review/references/exemplar_reviews/ai_overclaiming.md +47 -0
  467. package/skills/peer-review/references/exemplar_reviews/calibration_missing.md +44 -0
  468. package/skills/peer-review/references/exemplar_reviews/data_leakage.md +48 -0
  469. package/skills/peer-review/references/exemplar_reviews/reference_standard_validity.md +45 -0
  470. package/skills/peer-review/references/narrative_review_audit.md +67 -0
  471. package/skills/peer-review/references/reviewer_calibration/README.md +34 -0
  472. package/skills/peer-review/references/reviewer_calibration/compliance_floor.md +52 -0
  473. package/skills/peer-review/references/reviewer_profiles/AJR.md +82 -0
  474. package/skills/peer-review/references/reviewer_profiles/EURE.md +64 -0
  475. package/skills/peer-review/references/reviewer_profiles/INSI.md +57 -0
  476. package/skills/peer-review/references/reviewer_profiles/KJR.md +100 -0
  477. package/skills/peer-review/references/reviewer_profiles/README.md +32 -0
  478. package/skills/peer-review/references/reviewer_profiles/RYAI.md +86 -0
  479. package/skills/peer-review/skill.yml +39 -0
  480. package/skills/present-paper/SKILL.md +675 -0
  481. package/skills/present-paper/references/critic_rubrics/slide.md +155 -0
  482. package/skills/present-paper/references/generate_pptx_templates.py +604 -0
  483. package/skills/present-paper/references/medical_presentation_templates.md +277 -0
  484. package/skills/present-paper/references/slide_design_principles.md +202 -0
  485. package/skills/present-paper/references/slide_visual_styles/nature_lancet.md +168 -0
  486. package/skills/present-paper/references/workflow-checklist.md +109 -0
  487. package/skills/present-paper/scripts/extract_pdf_figures.py +243 -0
  488. package/skills/present-paper/scripts/inject_pronunciation_notes.py +178 -0
  489. package/skills/present-paper/scripts/inject_speaker_notes.py +133 -0
  490. package/skills/present-paper/scripts/strip_notes_for_sharing.py +140 -0
  491. package/skills/present-paper/scripts/trim_caption.py +271 -0
  492. package/skills/present-paper/skill.yml +41 -0
  493. package/skills/present-paper/templates/build_pptx_nature_lancet.py +688 -0
  494. package/skills/publish-skill/SKILL.md +370 -0
  495. package/skills/publish-skill/references/license-compatibility-matrix.md +132 -0
  496. package/skills/publish-skill/references/pii-patterns.md +130 -0
  497. package/skills/publish-skill/scripts/audit_skill.sh +278 -0
  498. package/skills/publish-skill/skill.yml +35 -0
  499. package/skills/render-pdf-doc/SKILL.md +146 -0
  500. package/skills/render-pdf-doc/references/known_pitfalls.md +53 -0
  501. package/skills/render-pdf-doc/references/pandoc_korean_cheatsheet.md +77 -0
  502. package/skills/render-pdf-doc/scripts/check_deps.sh +42 -0
  503. package/skills/render-pdf-doc/scripts/infer_colwidths.py +164 -0
  504. package/skills/render-pdf-doc/scripts/render_pdf.sh +98 -0
  505. package/skills/render-pdf-doc/skill.yml +57 -0
  506. package/skills/render-pdf-doc/templates/anchor-doc.md +27 -0
  507. package/skills/render-pdf-doc/templates/anchor-doc_ko.md +25 -0
  508. package/skills/render-pdf-doc/templates/briefing-handout.md +33 -0
  509. package/skills/render-pdf-doc/templates/briefing-handout_ko.md +31 -0
  510. package/skills/render-pdf-doc/templates/proposal-cover.md +33 -0
  511. package/skills/render-pdf-doc/templates/proposal-cover_ko.md +31 -0
  512. package/skills/render-pdf-doc/templates/reference-table.md +22 -0
  513. package/skills/render-pdf-doc/templates/reference-table_ko.md +20 -0
  514. package/skills/replicate-study/SKILL.md +150 -0
  515. package/skills/replicate-study/references/harmonization_3country.csv +47 -0
  516. package/skills/replicate-study/references/harmonization_knhanes_nhanes.csv +68 -0
  517. package/skills/replicate-study/references/methodology_extraction_template.md +134 -0
  518. package/skills/replicate-study/skill.yml +37 -0
  519. package/skills/review-paper/SKILL.md +104 -0
  520. package/skills/review-paper/references/macro_skeleton.md +6 -0
  521. package/skills/review-paper/skill.yml +25 -0
  522. package/skills/revise/SKILL.md +515 -0
  523. package/skills/revise/references/r2r_voice.md +346 -0
  524. package/skills/revise/skill.yml +43 -0
  525. package/skills/search-lit/SKILL.md +443 -0
  526. package/skills/search-lit/references/parse_pubmed.py +326 -0
  527. package/skills/search-lit/references/pubmed_eutils.sh +111 -0
  528. package/skills/search-lit/skill.yml +46 -0
  529. package/skills/self-review/SKILL.md +1045 -0
  530. package/skills/self-review/references/domain-probes/ai_overclaiming.md +47 -0
  531. package/skills/self-review/references/domain-probes/narrative_review.md +44 -0
  532. package/skills/self-review/references/domain-probes/observational_confounding.md +48 -0
  533. package/skills/self-review/references/domain-probes/radiomics.md +38 -0
  534. package/skills/self-review/references/domain-probes/sr_ma.md +87 -0
  535. package/skills/self-review/references/domain-probes/survival_prognostic.md +68 -0
  536. package/skills/self-review/references/exemplar_findings/README.md +43 -0
  537. package/skills/self-review/references/exemplar_findings/cohort_arithmetic_mismatch.md +35 -0
  538. package/skills/self-review/references/exemplar_findings/estimand_drift_posthoc_primary.md +39 -0
  539. package/skills/self-review/references/exemplar_findings/scope_overreach_cross_sectional.md +35 -0
  540. package/skills/self-review/references/exemplar_findings/unadjusted_confounder.md +36 -0
  541. package/skills/self-review/references/panel_review_template.md +177 -0
  542. package/skills/self-review/scripts/check_artifact_coverage.py +301 -0
  543. package/skills/self-review/scripts/check_claim_artifact.py +248 -0
  544. package/skills/self-review/scripts/check_classical_style.py +185 -0
  545. package/skills/self-review/scripts/check_cohort_arithmetic.py +481 -0
  546. package/skills/self-review/scripts/check_confounding_completeness.py +287 -0
  547. package/skills/self-review/scripts/check_panel_diversity.py +336 -0
  548. package/skills/self-review/scripts/check_reference_adequacy.py +392 -0
  549. package/skills/self-review/scripts/check_reviewer_team_consistency.py +412 -0
  550. package/skills/self-review/scripts/check_scope_coherence.py +177 -0
  551. package/skills/self-review/skill.yml +47 -0
  552. package/skills/self-review/tests/fixtures/claim_manuscript.md +17 -0
  553. package/skills/self-review/tests/fixtures/claim_prereg.md +6 -0
  554. package/skills/self-review/tests/fixtures/cohort_bad.md +21 -0
  555. package/skills/self-review/tests/fixtures/cohort_clean.md +21 -0
  556. package/skills/self-review/tests/fixtures/cohort_partition.csv +5 -0
  557. package/skills/self-review/tests/fixtures/coverage_analysis/31_delong_nested_added_value.csv +3 -0
  558. package/skills/self-review/tests/fixtures/coverage_analysis/table1_demographics.csv +3 -0
  559. package/skills/self-review/tests/fixtures/coverage_clean.md +13 -0
  560. package/skills/self-review/tests/fixtures/coverage_manuscript.md +11 -0
  561. package/skills/self-review/tests/fixtures/panel_collapse.json +27 -0
  562. package/skills/self-review/tests/fixtures/panel_good.json +32 -0
  563. package/skills/self-review/tests/fixtures/panel_monoculture.json +32 -0
  564. package/skills/self-review/tests/fixtures/refadeq_letter.md +13 -0
  565. package/skills/self-review/tests/fixtures/refadeq_original_fixed.md +42 -0
  566. package/skills/self-review/tests/fixtures/refadeq_original_uncited.md +40 -0
  567. package/skills/self-review/tests/fixtures/scope_bad.md +9 -0
  568. package/skills/self-review/tests/fixtures/scope_clean.md +8 -0
  569. package/skills/self-review/tests/fixtures/scope_surrogate.md +8 -0
  570. package/skills/self-review/tests/fixtures/style_bad.md +13 -0
  571. package/skills/self-review/tests/fixtures/style_clean.md +11 -0
  572. package/skills/self-review/tests/fixtures/table1_by_exposure.csv +11 -0
  573. package/skills/self-review/tests/test_artifact_coverage.sh +44 -0
  574. package/skills/self-review/tests/test_claim_artifact.sh +50 -0
  575. package/skills/self-review/tests/test_classical_style.sh +44 -0
  576. package/skills/self-review/tests/test_cohort_arithmetic.sh +49 -0
  577. package/skills/self-review/tests/test_confounding_completeness.sh +66 -0
  578. package/skills/self-review/tests/test_panel_diversity.sh +55 -0
  579. package/skills/self-review/tests/test_panel_mode.sh +69 -0
  580. package/skills/self-review/tests/test_reference_adequacy.sh +68 -0
  581. package/skills/self-review/tests/test_reviewer_team_consistency.sh +138 -0
  582. package/skills/self-review/tests/test_scope_coherence.sh +46 -0
  583. package/skills/setup-medsci/SKILL.md +110 -0
  584. package/skills/setup-medsci/references/setup-checklist.md +51 -0
  585. package/skills/setup-medsci/skill.yml +30 -0
  586. package/skills/sync-submission/SKILL.md +382 -0
  587. package/skills/sync-submission/scripts/author_registry_example.yaml +36 -0
  588. package/skills/sync-submission/scripts/blind_sweep.py +203 -0
  589. package/skills/sync-submission/scripts/check_asset_anonymization.py +300 -0
  590. package/skills/sync-submission/scripts/check_cross_artifact_stale.py +211 -0
  591. package/skills/sync-submission/scripts/cover_letter_drift_check.py +451 -0
  592. package/skills/sync-submission/scripts/cross_document_n_check.py +486 -0
  593. package/skills/sync-submission/scripts/detect_copy_divergence.py +136 -0
  594. package/skills/sync-submission/scripts/preflight_gate.py +458 -0
  595. package/skills/sync-submission/scripts/scope_drift_check.py +362 -0
  596. package/skills/sync-submission/scripts/sync_submission.py +169 -0
  597. package/skills/sync-submission/skill.yml +43 -0
  598. package/skills/sync-submission/tests/fixtures/copy_ok.md +5 -0
  599. package/skills/sync-submission/tests/fixtures/copy_stale.md +5 -0
  600. package/skills/sync-submission/tests/fixtures/ssot.md +5 -0
  601. package/skills/sync-submission/tests/test_asset_anonymization.sh +99 -0
  602. package/skills/sync-submission/tests/test_copy_divergence.sh +44 -0
  603. package/skills/sync-submission/tests/test_cross_artifact_stale.sh +80 -0
  604. package/skills/sync-submission/tests/test_cross_document_n.sh +132 -0
  605. package/skills/sync-submission/tests/test_preflight_gate.sh +112 -0
  606. package/skills/sync-submission/tests/test_scope_drift.sh +122 -0
  607. package/skills/sync-submission/tests/test_vN_docx_assertion.sh +51 -0
  608. package/skills/verify-refs/SKILL.md +177 -0
  609. package/skills/verify-refs/references/manual_checkpoint_guide.md +100 -0
  610. package/skills/verify-refs/scripts/verify_cli.sh +62 -0
  611. package/skills/verify-refs/scripts/verify_refs.py +782 -0
  612. package/skills/verify-refs/skill.yml +44 -0
  613. package/skills/verify-refs/tests/fixtures/pagination_placeholder.bib +17 -0
  614. package/skills/verify-refs/tests/test_pagination_placeholder.sh +42 -0
  615. package/skills/version-dataset/SKILL.md +143 -0
  616. package/skills/version-dataset/references/manifest_schema.md +72 -0
  617. package/skills/version-dataset/scripts/version_dataset.py +242 -0
  618. package/skills/version-dataset/skill.yml +35 -0
  619. package/skills/version-dataset/tests/test_version_dataset.sh +52 -0
  620. package/skills/write-paper/SKILL.md +1148 -0
  621. package/skills/write-paper/references/exemplar_methods/README.md +38 -0
  622. package/skills/write-paper/references/exemplar_methods/ai_validation_tripod_claim.md +47 -0
  623. package/skills/write-paper/references/exemplar_methods/diagnostic_accuracy_stard.md +50 -0
  624. package/skills/write-paper/references/exemplar_methods/observational_cohort_strobe.md +43 -0
  625. package/skills/write-paper/references/journal_profiles/AJNR.md +185 -0
  626. package/skills/write-paper/references/journal_profiles/AJR.md +149 -0
  627. package/skills/write-paper/references/journal_profiles/Abdominal_Radiology.md +139 -0
  628. package/skills/write-paper/references/journal_profiles/Academic_Radiology.md +90 -0
  629. package/skills/write-paper/references/journal_profiles/Annals_of_Internal_Medicine.md +150 -0
  630. package/skills/write-paper/references/journal_profiles/Artificial_Intelligence_in_Medicine.md +82 -0
  631. package/skills/write-paper/references/journal_profiles/British_Journal_of_Radiology.md +161 -0
  632. package/skills/write-paper/references/journal_profiles/CVIR.md +157 -0
  633. package/skills/write-paper/references/journal_profiles/Chest.md +270 -0
  634. package/skills/write-paper/references/journal_profiles/Clinical_Radiology.md +160 -0
  635. package/skills/write-paper/references/journal_profiles/Clinical_and_Molecular_Hepatology.md +147 -0
  636. package/skills/write-paper/references/journal_profiles/Diabetes_Metabolism_Journal.md +163 -0
  637. package/skills/write-paper/references/journal_profiles/Diagnostic_and_Interventional_Radiology.md +216 -0
  638. package/skills/write-paper/references/journal_profiles/Endocrinology_and_Metabolism.md +167 -0
  639. package/skills/write-paper/references/journal_profiles/European_Journal_of_Preventive_Cardiology.md +192 -0
  640. package/skills/write-paper/references/journal_profiles/European_Radiology.md +159 -0
  641. package/skills/write-paper/references/journal_profiles/Hepatology_Communications.md +110 -0
  642. package/skills/write-paper/references/journal_profiles/Hepatology_International.md +106 -0
  643. package/skills/write-paper/references/journal_profiles/IEEE_TMI.md +180 -0
  644. package/skills/write-paper/references/journal_profiles/INSI.md +163 -0
  645. package/skills/write-paper/references/journal_profiles/Investigative_Radiology.md +86 -0
  646. package/skills/write-paper/references/journal_profiles/JACC_Advances.md +197 -0
  647. package/skills/write-paper/references/journal_profiles/JACC_Asia.md +168 -0
  648. package/skills/write-paper/references/journal_profiles/JACR.md +87 -0
  649. package/skills/write-paper/references/journal_profiles/JAMA.md +188 -0
  650. package/skills/write-paper/references/journal_profiles/JAMA_Network_Open.md +170 -0
  651. package/skills/write-paper/references/journal_profiles/JCSM.md +266 -0
  652. package/skills/write-paper/references/journal_profiles/JKMS.md +201 -0
  653. package/skills/write-paper/references/journal_profiles/JMIR.md +88 -0
  654. package/skills/write-paper/references/journal_profiles/JMIR_Medical_Education.md +86 -0
  655. package/skills/write-paper/references/journal_profiles/JNIS.md +227 -0
  656. package/skills/write-paper/references/journal_profiles/JVIR.md +158 -0
  657. package/skills/write-paper/references/journal_profiles/Journal_of_Clinical_Endocrinology_and_Metabolism.md +191 -0
  658. package/skills/write-paper/references/journal_profiles/Journal_of_Stroke.md +176 -0
  659. package/skills/write-paper/references/journal_profiles/KJR.md +185 -0
  660. package/skills/write-paper/references/journal_profiles/Korean_Circulation_Journal.md +184 -0
  661. package/skills/write-paper/references/journal_profiles/Korean_Journal_of_Internal_Medicine.md +178 -0
  662. package/skills/write-paper/references/journal_profiles/Lancet_Gastroenterology_and_Hepatology.md +127 -0
  663. package/skills/write-paper/references/journal_profiles/Liver_International.md +165 -0
  664. package/skills/write-paper/references/journal_profiles/Medical_Image_Analysis.md +147 -0
  665. package/skills/write-paper/references/journal_profiles/NEJM.md +147 -0
  666. package/skills/write-paper/references/journal_profiles/Nature_Medicine.md +181 -0
  667. package/skills/write-paper/references/journal_profiles/Neuroradiology.md +151 -0
  668. package/skills/write-paper/references/journal_profiles/Nutrition_Metabolism_and_Cardiovascular_Diseases.md +184 -0
  669. package/skills/write-paper/references/journal_profiles/PLOS_Medicine.md +166 -0
  670. package/skills/write-paper/references/journal_profiles/RYAI.md +124 -0
  671. package/skills/write-paper/references/journal_profiles/Radiology.md +173 -0
  672. package/skills/write-paper/references/journal_profiles/Skeletal_Radiology.md +135 -0
  673. package/skills/write-paper/references/journal_profiles/Stroke.md +210 -0
  674. package/skills/write-paper/references/journal_profiles/The_BMJ.md +121 -0
  675. package/skills/write-paper/references/journal_profiles/The_Lancet.md +112 -0
  676. package/skills/write-paper/references/journal_profiles/The_Lancet_Digital_Health.md +104 -0
  677. package/skills/write-paper/references/journal_profiles/World_Journal_of_Hepatology.md +106 -0
  678. package/skills/write-paper/references/journal_profiles/npj_Digital_Medicine.md +93 -0
  679. package/skills/write-paper/references/paper_types/ai_validation.md +270 -0
  680. package/skills/write-paper/references/paper_types/animal_study.md +194 -0
  681. package/skills/write-paper/references/paper_types/case_report.md +237 -0
  682. package/skills/write-paper/references/paper_types/cross_national.md +328 -0
  683. package/skills/write-paper/references/paper_types/letter.md +127 -0
  684. package/skills/write-paper/references/paper_types/meta_analysis.md +181 -0
  685. package/skills/write-paper/references/paper_types/nhis_cohort.md +297 -0
  686. package/skills/write-paper/references/paper_types/original_article.md +221 -0
  687. package/skills/write-paper/references/paper_types/technical_note.md +131 -0
  688. package/skills/write-paper/references/section_guides/discussion.md +155 -0
  689. package/skills/write-paper/references/section_guides/introduction.md +108 -0
  690. package/skills/write-paper/references/section_guides/methods.md +144 -0
  691. package/skills/write-paper/references/section_guides/results.md +113 -0
  692. package/skills/write-paper/references/section_guides/step7_1_classical_qc.md +67 -0
  693. package/skills/write-paper/references/section_guides/step7_4a_audit_recovery.md +74 -0
  694. package/skills/write-paper/references/section_guides/title_abstract.md +123 -0
  695. package/skills/write-paper/references/section_templates/methods_statistical.md +147 -0
  696. package/skills/write-paper/scripts/check_placeholders.py +182 -0
  697. package/skills/write-paper/skill.yml +48 -0
  698. package/skills/write-paper/tests/test_placeholders.sh +107 -0
  699. package/skills/write-protocol/SKILL.md +243 -0
  700. package/skills/write-protocol/references/ethics_checklist.md +150 -0
  701. package/skills/write-protocol/references/protocol_template.md +304 -0
  702. package/skills/write-protocol/skill.yml +34 -0
@@ -0,0 +1,335 @@
1
+ #!/usr/bin/env python3
2
+ """Generated-code quality gate for analysis scripts (analyze-stats Phase 3.5).
3
+
4
+ AI-generated analysis code carries a recurring set of reproducibility-hygiene
5
+ "slop" patterns that pass a casual read but break reproducibility or violate
6
+ the data-integrity rules every medsci-skills analysis must follow. This linter
7
+ scans emitted .py / .R scripts before they are reported as final and flags:
8
+
9
+ MISSING_SEED randomness is used (sampling, bootstrap, train/test
10
+ split, shuffling, rng) but no seed is set
11
+ (np.random.seed / set.seed / random_state= /
12
+ default_rng / RandomState). Non-reproducible. (Major)
13
+ HARDCODED_DATA_LITERAL a large hand-typed numeric literal that looks like
14
+ tabular data — either alongside a real data-file read,
15
+ or very large on its own. The data-integrity rule is
16
+ "never hand-type CSV data into scripts; use read_csv +
17
+ subset." (Major)
18
+ HARDCODED_ABS_PATH an absolute filesystem path literal (/Users/, /home/,
19
+ C:\\, ~/Documents). Non-portable and a PII risk. (Major)
20
+ INPLACE_SOURCE_OVERWRITE the same path is both read as input and written as
21
+ output — silently overwriting raw source data. The
22
+ data-integrity rule is "never modify raw data." (Major)
23
+ DEBUG_LEFTOVER a debugger/print artifact left in (breakpoint(),
24
+ pdb.set_trace(), browser(), print("debug"...)) or a
25
+ TODO/FIXME/XXX marker. (Flag)
26
+ UNUSED_IMPORT (Python only) an imported name never referenced again;
27
+ dead dependency. (Flag)
28
+
29
+ The gate is conservative on the Major checks (it fires HARDCODED_DATA_LITERAL
30
+ only on genuinely table-shaped literals, MISSING_SEED only when a real
31
+ randomness call is present) so it stays quiet on legitimate analysis code.
32
+
33
+ INPUTS
34
+ positional one or more .py / .R / .r files.
35
+ --code-dir directory to scan recursively for .py / .R / .r files.
36
+ (at least one source must be provided via either form.)
37
+
38
+ OUTPUT
39
+ A findings table (stdout) and, with --out, a JSON artifact:
40
+ {files[], claims[{verdict, severity, file, line, detail}], summary}
41
+ Exit 1 (with --strict) when any Major claim exists; exit 2 on input error.
42
+
43
+ Stdlib-only (ast / json / re / argparse / pathlib). Exit codes: 0 clean (or
44
+ report-only), 1 Major claim(s) found (with --strict), 2 input/usage error.
45
+ """
46
+
47
+ from __future__ import annotations
48
+
49
+ import argparse
50
+ import ast
51
+ import json
52
+ import re
53
+ import sys
54
+ from pathlib import Path
55
+
56
+ # --- shared regexes (language-agnostic unless noted) ------------------------
57
+
58
+ ABS_PATH = re.compile(r"""['"](?:/Users/|/home/|~/Documents|~/Desktop|~/Downloads|[A-Za-z]:\\\\)[^'"]*['"]""")
59
+
60
+ DEBUG_PY = re.compile(
61
+ r"\bbreakpoint\s*\(|\bpdb\.set_trace\s*\(|^\s*import\s+pdb\b|"
62
+ r"\bprint\s*\(\s*['\"](?:debug|here|test|xxx|todo|checkpoint)\b", re.IGNORECASE)
63
+ DEBUG_R = re.compile(
64
+ r"\bbrowser\s*\(\s*\)|\bdebug(?:once)?\s*\(|"
65
+ r"\bprint\s*\(\s*paste0?\s*\(\s*['\"](?:debug|here|test)\b|"
66
+ r"\bcat\s*\(\s*['\"](?:debug|here)\b", re.IGNORECASE)
67
+ TODO_MARKER = re.compile(r"#\s*(?:TODO|FIXME|XXX)\b", re.IGNORECASE)
68
+
69
+ # randomness signals vs seed signals
70
+ RAND_PY = re.compile(
71
+ r"np\.random\.|numpy\.random\.|\brandom\.(?:sample|shuffle|choice|random|randint|randrange)\b|"
72
+ r"\bRandomState\b|\bdefault_rng\b|\btrain_test_split\b|\bKFold\b|\bStratifiedKFold\b|"
73
+ r"\bShuffleSplit\b|\bresample\s*\(|\bbootstrap\b|\bpermutation\b")
74
+ SEED_PY = re.compile(
75
+ r"np\.random\.seed\s*\(|numpy\.random\.seed\s*\(|\brandom\.seed\s*\(|"
76
+ r"\bRandomState\s*\(|\bdefault_rng\s*\(|\brandom_state\s*=")
77
+ RAND_R = re.compile(
78
+ r"\bsample\s*\(|\bsample\.int\s*\(|\brnorm\s*\(|\brunif\s*\(|\brbinom\s*\(|"
79
+ r"\brpois\s*\(|\bboot\s*\(|\bcreateDataPartition\s*\(")
80
+ SEED_R = re.compile(r"\bset\.seed\s*\(")
81
+
82
+ # data-file reads / writes (for INPLACE_SOURCE_OVERWRITE and the DATA_LITERAL gate)
83
+ READ_CALL = re.compile(
84
+ r"(?:read_csv|read\.csv|read_excel|read\.xlsx|read_parquet|read_table|read\.table|"
85
+ r"read_csv2|read_tsv|read_sas|read_stata|read_feather|read_json|loadtxt|genfromtxt)"
86
+ r"\s*\(\s*([^,\)]+)")
87
+ WRITE_FN = re.compile(
88
+ r"(?:to_csv|write\.csv|write_csv|write_csv2|to_excel|write\.xlsx|to_parquet|"
89
+ r"write_parquet|to_feather|savetxt|write\.table|write_tsv|fwrite)\s*\(")
90
+
91
+ STR_LITERAL = re.compile(r"""['"]([^'"]+)['"]""")
92
+ # bracketed/paren literal whose body is mostly comma-separated numbers
93
+ NUM_LITERAL_BODY = re.compile(r"[\[(]([^\[\]()]*?\d[^\[\]()]*?)[\])]")
94
+ NUM_TOKEN = re.compile(r"-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?")
95
+
96
+ DATA_LITERAL_MIN = 12 # numbers in one literal to look table-shaped (with a read)
97
+ DATA_LITERAL_STANDALONE = 24 # numbers in one literal to flag even with no read
98
+
99
+
100
+ def _first_path_literal(arg: str) -> str | None:
101
+ m = STR_LITERAL.search(arg)
102
+ return m.group(1) if m else None
103
+
104
+
105
+ def strip_comments(src: str) -> str:
106
+ """Blank out `#`-to-EOL comments while preserving byte offsets and line count,
107
+ so seed/randomness detection never matches a mention inside a comment (e.g.
108
+ '# no set.seed() used') yet reported line numbers stay correct. Runs only for
109
+ the seed/randomness checks; path/literal checks keep the full source."""
110
+ out = []
111
+ for line in src.split("\n"):
112
+ i = line.find("#")
113
+ out.append(line if i < 0 else line[:i] + " " * (len(line) - i))
114
+ return "\n".join(out)
115
+
116
+
117
+ def check_text_common(src: str, lang: str) -> list[dict]:
118
+ claims: list[dict] = []
119
+ lines = src.splitlines()
120
+ has_read = bool(READ_CALL.search(src))
121
+ code = strip_comments(src) # comment-free copy for seed/randomness logic
122
+
123
+ # MISSING_SEED
124
+ rand, seed = (RAND_PY, SEED_PY) if lang == "py" else (RAND_R, SEED_R)
125
+ rm = rand.search(code)
126
+ if rm and not seed.search(code):
127
+ ln = src[:rm.start()].count("\n") + 1
128
+ claims.append({
129
+ "verdict": "MISSING_SEED", "severity": "Major", "line": ln,
130
+ "detail": (f"randomness ('{rm.group(0).strip()[:30]}') is used but no seed is set "
131
+ f"({'np.random.seed/random_state=' if lang == 'py' else 'set.seed()'}); "
132
+ f"the result is not reproducible"),
133
+ })
134
+
135
+ # HARDCODED_ABS_PATH
136
+ am = ABS_PATH.search(src)
137
+ if am:
138
+ ln = src[:am.start()].count("\n") + 1
139
+ claims.append({
140
+ "verdict": "HARDCODED_ABS_PATH", "severity": "Major", "line": ln,
141
+ "detail": f"absolute path literal {am.group(0)[:50]} — non-portable and a PII risk",
142
+ })
143
+
144
+ # HARDCODED_DATA_LITERAL
145
+ for m in NUM_LITERAL_BODY.finditer(src):
146
+ body = m.group(1)
147
+ # ignore obvious non-data: ranges, single repeated, function-call args with kwargs
148
+ nums = NUM_TOKEN.findall(body)
149
+ if "=" in body: # kwargs like figsize=(8,6) or linspace(0,1,...) — not table data
150
+ continue
151
+ if len(nums) >= DATA_LITERAL_STANDALONE or (len(nums) >= DATA_LITERAL_MIN and has_read):
152
+ ln = src[:m.start()].count("\n") + 1
153
+ claims.append({
154
+ "verdict": "HARDCODED_DATA_LITERAL", "severity": "Major", "line": ln,
155
+ "detail": (f"a hand-typed numeric literal with {len(nums)} values"
156
+ + (" alongside a data-file read" if has_read else "")
157
+ + "; load tabular data with read_csv()/read.csv() + subset, "
158
+ "never hand-type it into the script"),
159
+ })
160
+ break # one report per file is enough to act on
161
+
162
+ # INPLACE_SOURCE_OVERWRITE — a write call writing to a path also read as input.
163
+ # Reads capture the first call argument; writes scan the call window for any
164
+ # string literal (the output path is often the 2nd arg, e.g. write.csv(df, "x")).
165
+ reads = {p for a in READ_CALL.findall(src) if (p := _first_path_literal(a))}
166
+ writes: set[str] = set()
167
+ for wm in WRITE_FN.finditer(src):
168
+ window = src[wm.end():wm.end() + 200]
169
+ window = window.split(")")[0] # stay within this call's arg list
170
+ writes.update(STR_LITERAL.findall(window))
171
+ overlap = reads & writes
172
+ if overlap:
173
+ path = sorted(overlap)[0]
174
+ idx = src.find(path)
175
+ ln = src[:idx].count("\n") + 1 if idx >= 0 else 0
176
+ claims.append({
177
+ "verdict": "INPLACE_SOURCE_OVERWRITE", "severity": "Major", "line": ln,
178
+ "detail": (f"'{path}' is both read as input and written as output; writing to the "
179
+ f"source path overwrites raw data — write derived outputs to a new path"),
180
+ })
181
+
182
+ # DEBUG_LEFTOVER
183
+ debug_re = DEBUG_PY if lang == "py" else DEBUG_R
184
+ for i, line in enumerate(lines, 1):
185
+ if debug_re.search(line) or TODO_MARKER.search(line):
186
+ claims.append({
187
+ "verdict": "DEBUG_LEFTOVER", "severity": "Flag", "line": i,
188
+ "detail": f"debug/marker leftover: {line.strip()[:60]}",
189
+ })
190
+ break # first occurrence per file
191
+
192
+ return claims
193
+
194
+
195
+ def check_unused_imports_py(src: str) -> list[dict]:
196
+ """Python-only, AST-based. An imported name never referenced elsewhere."""
197
+ try:
198
+ tree = ast.parse(src)
199
+ except SyntaxError:
200
+ return [] # don't guess on unparseable files
201
+ imported: list[tuple[str, str, int]] = [] # (bound_name, display, lineno)
202
+ for node in ast.walk(tree):
203
+ if isinstance(node, ast.Import):
204
+ for alias in node.names:
205
+ bound = (alias.asname or alias.name).split(".")[0]
206
+ imported.append((bound, alias.asname or alias.name, node.lineno))
207
+ elif isinstance(node, ast.ImportFrom):
208
+ if node.module == "__future__":
209
+ continue
210
+ for alias in node.names:
211
+ if alias.name == "*":
212
+ return [] # star import: cannot reason about usage
213
+ bound = alias.asname or alias.name
214
+ imported.append((bound, f"{node.module or ''}.{alias.name}", node.lineno))
215
+ # collect all Name usages outside the import statements
216
+ used: set[str] = set()
217
+ for node in ast.walk(tree):
218
+ if isinstance(node, ast.Name):
219
+ used.add(node.id)
220
+ elif isinstance(node, ast.Attribute):
221
+ pass # base Name already captured by the Name walk
222
+ claims = []
223
+ for bound, display, lineno in imported:
224
+ if bound not in used:
225
+ claims.append({
226
+ "verdict": "UNUSED_IMPORT", "severity": "Flag", "line": lineno,
227
+ "detail": f"'{display}' is imported but never used; remove the dead import",
228
+ })
229
+ return claims
230
+
231
+
232
+ def check_file(path: Path) -> list[dict]:
233
+ lang = "py" if path.suffix.lower() == ".py" else "r"
234
+ src = path.read_text(encoding="utf-8", errors="replace")
235
+ claims = check_text_common(src, lang)
236
+ if lang == "py":
237
+ claims += check_unused_imports_py(src)
238
+ for c in claims:
239
+ c["file"] = str(path)
240
+ return claims
241
+
242
+
243
+ def gather_files(positional: list[str], code_dir: str | None) -> list[Path]:
244
+ files: list[Path] = []
245
+ for p in positional:
246
+ pp = Path(p)
247
+ if not pp.is_file():
248
+ sys.stderr.write(f"ERROR: not a file: {p}\n")
249
+ sys.exit(2)
250
+ files.append(pp)
251
+ if code_dir:
252
+ d = Path(code_dir)
253
+ if not d.is_dir():
254
+ sys.stderr.write(f"ERROR: not a directory: {code_dir}\n")
255
+ sys.exit(2)
256
+ for ext in ("*.py", "*.R", "*.r"):
257
+ files.extend(sorted(d.rglob(ext)))
258
+ # dedupe, preserve order
259
+ seen, uniq = set(), []
260
+ for f in files:
261
+ key = str(f.resolve())
262
+ if key not in seen:
263
+ seen.add(key)
264
+ uniq.append(f)
265
+ if not uniq:
266
+ sys.stderr.write("ERROR: no .py/.R source files to scan\n")
267
+ sys.exit(2)
268
+ return uniq
269
+
270
+
271
+ def analyze(positional: list[str], code_dir: str | None) -> dict:
272
+ files = gather_files(positional, code_dir)
273
+ claims: list[dict] = []
274
+ for f in files:
275
+ claims += check_file(f)
276
+ n_major = sum(1 for c in claims if c["severity"] == "Major")
277
+ return {
278
+ "files": [str(f) for f in files],
279
+ "claims": claims,
280
+ "summary": {
281
+ "n_files": len(files),
282
+ "n_claims": len(claims),
283
+ "n_major": n_major,
284
+ "n_flag": len(claims) - n_major,
285
+ "verdict": "MAJOR_CANDIDATE" if n_major else "OK",
286
+ },
287
+ }
288
+
289
+
290
+ def render(result: dict) -> str:
291
+ lines = ["| File:Line | Check | Severity | Detail |", "|---|---|---|---|"]
292
+ for c in result["claims"]:
293
+ loc = f"{Path(c['file']).name}:{c.get('line', 0)}"
294
+ lines.append(f"| {loc} | {c['verdict']} | {c['severity']} | {c['detail']} |")
295
+ if len(lines) == 2:
296
+ lines.append("| (none) | — | — | scripts are reproducibility-clean |")
297
+ return "\n".join(lines)
298
+
299
+
300
+ def main() -> int:
301
+ ap = argparse.ArgumentParser(description="Generated-code quality gate (analyze-stats Phase 3.5).")
302
+ ap.add_argument("files", nargs="*", help=".py / .R source files to scan")
303
+ ap.add_argument("--code-dir", help="directory to scan recursively for .py/.R files")
304
+ ap.add_argument("--out", help="write JSON artifact to this path")
305
+ ap.add_argument("--strict", action="store_true", help="exit 1 if any Major claim exists")
306
+ ap.add_argument("--quiet", action="store_true", help="suppress stdout table")
307
+ args = ap.parse_args()
308
+
309
+ result = analyze(args.files, args.code_dir)
310
+
311
+ if not args.quiet:
312
+ print("=" * 41)
313
+ print(" Generated-Code Quality (Phase 3.5)")
314
+ print("=" * 41)
315
+ print(render(result))
316
+ print()
317
+ s = result["summary"]
318
+ if s["n_major"]:
319
+ print(f"MAJOR candidate: {s['n_major']} reproducibility/integrity issue(s) "
320
+ f"across {s['n_files']} file(s).")
321
+ else:
322
+ print(f"OK: {s['n_files']} file(s) reproducibility-clean "
323
+ f"({s['n_flag']} minor flag(s)).")
324
+
325
+ if args.out:
326
+ Path(args.out).parent.mkdir(parents=True, exist_ok=True)
327
+ Path(args.out).write_text(json.dumps(result, indent=2), encoding="utf-8")
328
+ if not args.quiet:
329
+ print(f"\nwrote {args.out}")
330
+
331
+ return 1 if (args.strict and result["summary"]["n_major"]) else 0
332
+
333
+
334
+ if __name__ == "__main__":
335
+ sys.exit(main())
@@ -0,0 +1,38 @@
1
+ schema_version: 2
2
+ name: analyze-stats
3
+ layer: B
4
+ owner_domain: statistical_analysis
5
+
6
+ when_to_use: "Generate reproducible Python/R analysis code with publication-ready tables and figures for a defined study design."
7
+ when_NOT_to_use: "Sample-size planning (use calc-sample-size); figure-only generation (use make-figures)."
8
+
9
+ inputs:
10
+ - "analysis dataset (CSV)"
11
+ - "analysis plan / variable definitions"
12
+ outputs:
13
+ - "analysis code (Python/R)"
14
+ - "result tables"
15
+ - "analysis figures"
16
+ side_effects:
17
+ - writes_project_artifacts
18
+ - executes_analysis_code
19
+ downstream_consumers:
20
+ - write-paper
21
+ - make-figures
22
+ - self-review
23
+ forbidden_actions:
24
+ - fabricate_or_hand_type_numeric_results
25
+ - report_estimates_without_ci_or_p
26
+
27
+ # v2.1 quality card
28
+ purpose: "Produce reproducible statistical code and publication-ready output for a specified design (DTA, agreement, survival, regression, survey, etc.)."
29
+ safety_boundaries:
30
+ - "All numbers come from executed code on the supplied data; never hand-typed (seed-fixed transforms)."
31
+ - "Primary estimates report effect size with 95% CI and exact p-values."
32
+ known_limitations:
33
+ - "Correctness depends on a correct analysis plan and clean data (use design-study / clean-data first)."
34
+ - "Does not adjudicate clinical validity of the chosen test."
35
+ validation_commands:
36
+ - "re-run the emitted script and diff results"
37
+ - "/self-review"
38
+ evidence_surface: demo
@@ -0,0 +1,16 @@
1
+ # Analysis: synthetic BAD fixture (R) for the generated-code quality gate.
2
+ # Date: 2020-01-01
3
+
4
+ # absolute path literal + source read
5
+ df <- read.csv("/Users/researcher/data/cohort.csv")
6
+
7
+ # hand-typed tabular data instead of read.csv + subset
8
+ auc <- c(0.81, 0.83, 0.79, 0.88, 0.84, 0.77, 0.82, 0.86, 0.80, 0.85, 0.78, 0.87, 0.83, 0.81)
9
+
10
+ # randomness with no set.seed() -> non-reproducible
11
+ boot <- sample(df$auc, size = 1000, replace = TRUE)
12
+
13
+ browser() # debugger left in
14
+
15
+ # writes back to the source path -> overwrites raw data
16
+ write.csv(df, "/Users/researcher/data/cohort.csv")
@@ -0,0 +1,24 @@
1
+ """
2
+ Analysis: synthetic BAD fixture for the generated-code quality gate.
3
+ Date: 2020-01-01
4
+ Random seed: (intentionally missing)
5
+ """
6
+ import numpy as np
7
+ import pandas as pd
8
+ import json # unused import (dead dependency)
9
+
10
+ # absolute path literal + source read
11
+ df = pd.read_csv("/Users/researcher/data/cohort.csv")
12
+
13
+ # hand-typed tabular data instead of read_csv + subset
14
+ ref = pd.DataFrame({
15
+ "auc": [0.81, 0.83, 0.79, 0.88, 0.84, 0.77, 0.82, 0.86, 0.80, 0.85, 0.78, 0.87, 0.83, 0.81],
16
+ })
17
+
18
+ # randomness with no seed set -> non-reproducible
19
+ boot = np.random.choice(df["auc"].values, size=1000, replace=True)
20
+
21
+ breakpoint() # debugger left in
22
+
23
+ # writes back to the source path -> overwrites raw data
24
+ df.to_csv("/Users/researcher/data/cohort.csv")
@@ -0,0 +1,21 @@
1
+ """
2
+ Analysis: synthetic CLEAN fixture for the generated-code quality gate.
3
+ Date: 2026-01-01
4
+ Random seed: 42
5
+ """
6
+ import numpy as np
7
+ import pandas as pd
8
+
9
+ np.random.seed(42)
10
+
11
+ # portable relative path; no hand-typed data
12
+ df = pd.read_csv("cohort.csv")
13
+
14
+ # seeded randomness -> reproducible
15
+ boot = np.random.choice(df["auc"].values, size=1000, replace=True)
16
+ boot_mean = float(np.mean(boot))
17
+
18
+ # derived output written to a NEW path, not the source
19
+ summary = df["auc"].describe()
20
+ summary.to_csv("auc_summary.csv")
21
+ print(f"bootstrap mean AUC = {boot_mean:.3f}")
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env bash
2
+ # Regression test for the generated-code quality gate (analyze-stats Phase 3.5).
3
+ # Synthetic, PII-free fixtures reproduce reproducibility/integrity slop in both
4
+ # Python and R (missing seed, hardcoded absolute path, hand-typed tabular data,
5
+ # in-place source overwrite, debug leftover, unused import) and a clean script.
6
+ # Absolute-path literals use a synthetic /Users/researcher/ that does not match
7
+ # the repo PII blocklist (personal home dirs only).
8
+ # Stdlib-only (python3).
9
+ set -u
10
+
11
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
+ SCRIPT="$HERE/../scripts/check_generated_code.py"
13
+ BAD_PY="$HERE/fixtures/gen_bad.py"
14
+ BAD_R="$HERE/fixtures/gen_bad.R"
15
+ CLEAN="$HERE/fixtures/gen_clean.py"
16
+ OUT="$(mktemp -t gencode_XXXX).json"
17
+ trap 'rm -f "$OUT"' EXIT
18
+
19
+ fail=0
20
+ check() { local label="$1"; shift
21
+ if "$@" >/dev/null 2>&1; then printf ' PASS %s\n' "$label"
22
+ else printf ' FAIL %s\n' "$label"; fail=$((fail+1)); fi
23
+ }
24
+ has_verdict() { python3 -c "
25
+ import json,sys
26
+ d=json.load(open('$OUT'))
27
+ assert any(c['verdict']=='$1' for c in d['claims']), '$1 not found'
28
+ "; }
29
+
30
+ [[ -f "$SCRIPT" ]] || { echo "ENV-ERR: script missing" >&2; exit 2; }
31
+
32
+ # (1) bad Python script -> exit 1 with all four Major verdicts + flags
33
+ python3 "$SCRIPT" "$BAD_PY" --out "$OUT" --strict --quiet >/dev/null 2>&1
34
+ check "exit 1 (bad .py)" test "$?" -eq 1
35
+ check "MISSING_SEED detected" has_verdict MISSING_SEED
36
+ check "HARDCODED_ABS_PATH detected" has_verdict HARDCODED_ABS_PATH
37
+ check "HARDCODED_DATA_LITERAL detected" has_verdict HARDCODED_DATA_LITERAL
38
+ check "INPLACE_SOURCE_OVERWRITE detected" has_verdict INPLACE_SOURCE_OVERWRITE
39
+ check "UNUSED_IMPORT detected" has_verdict UNUSED_IMPORT
40
+ check "DEBUG_LEFTOVER detected" has_verdict DEBUG_LEFTOVER
41
+
42
+ # (2) bad R script -> exit 1 with R-side Major verdicts
43
+ python3 "$SCRIPT" "$BAD_R" --out "$OUT" --strict --quiet >/dev/null 2>&1
44
+ check "exit 1 (bad .R)" test "$?" -eq 1
45
+ check "MISSING_SEED detected (R)" has_verdict MISSING_SEED
46
+ check "HARDCODED_ABS_PATH detected (R)" has_verdict HARDCODED_ABS_PATH
47
+ check "HARDCODED_DATA_LITERAL detected (R)" has_verdict HARDCODED_DATA_LITERAL
48
+ check "INPLACE_SOURCE_OVERWRITE detected (R)" has_verdict INPLACE_SOURCE_OVERWRITE
49
+
50
+ # (3) clean Python script -> exit 0
51
+ python3 "$SCRIPT" "$CLEAN" --strict --quiet >/dev/null 2>&1
52
+ check "exit 0 (clean .py)" test "$?" -eq 0
53
+
54
+ # (4) --code-dir scans the fixtures directory (finds Major issues -> exit 1)
55
+ python3 "$SCRIPT" --code-dir "$HERE/fixtures" --strict --quiet >/dev/null 2>&1
56
+ check "exit 1 (--code-dir scan)" test "$?" -eq 1
57
+
58
+ echo "fail=$fail"; [[ "$fail" -eq 0 ]] && echo "ALL PASS" || echo "FAILURES: $fail"
59
+ exit "$fail"
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ # Test the survival_analysis.py template hardening (A1):
3
+ # - median survival reported WITH a 95% CI (not a bare point estimate)
4
+ # - Cox events-per-variable (EPV) gate
5
+ # - cluster-robust (sandwich) SE for nested observation units
6
+ # Static assertions always run (CI-safe, no heavy deps). A runtime smoke runs
7
+ # only when lifelines is importable; otherwise it SKIPs (never fails CI).
8
+ set -u
9
+
10
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ TPL="$HERE/../references/templates/survival_analysis.py"
12
+ PASS=0
13
+ FAIL=0
14
+ ok() { echo " PASS: $1"; PASS=$((PASS+1)); }
15
+ bad() { echo " FAIL: $1"; FAIL=$((FAIL+1)); }
16
+
17
+ # --- static: the template must compile + contain the hardened code paths ---
18
+ python3 -m py_compile "$TPL" 2>/dev/null && ok "template compiles" || bad "template syntax error"
19
+
20
+ grep -q "def median_with_ci" "$TPL" && ok "median_with_ci helper present" || bad "no median_with_ci helper"
21
+ grep -q "median_survival_times" "$TPL" && ok "imports median CI util" || bad "median CI util not imported"
22
+ # no bare median print left behind (the old `Median survival = {med:.1f}` form)
23
+ grep -qE 'Median survival[^\n]*median_survival_time_' "$TPL" && bad "bare median print still present" || ok "no bare median print"
24
+ grep -q "cluster_col" "$TPL" && ok "Cox cluster_col (robust SE) param" || bad "no cluster_col param"
25
+ grep -q -- "--cluster" "$TPL" && ok "--cluster CLI arg" || bad "no --cluster CLI arg"
26
+ grep -qiE "EPV =|EPV <" "$TPL" && ok "Cox EPV gate present" || bad "no Cox EPV gate"
27
+
28
+ # --- runtime smoke (optional, lifelines required) ---
29
+ if python3 -c "import lifelines" 2>/dev/null; then
30
+ WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT
31
+ python3 - "$WORK" <<'PY'
32
+ import csv, os, sys, random
33
+ random.seed(0)
34
+ work = sys.argv[1]
35
+ rows = [("t", "e", "g", "age", "pid")]
36
+ for i in range(120):
37
+ rows.append((round(random.expovariate(1/12), 2), int(random.random() < 0.6),
38
+ "A" if i % 2 else "B", round(40 + random.gauss(0, 10), 1), i // 2))
39
+ with open(os.path.join(work, "s.csv"), "w", newline="") as f:
40
+ csv.writer(f).writerows(rows)
41
+ PY
42
+ OUT="$(python3 "$TPL" --input "$WORK/s.csv" --time t --event e --group g \
43
+ --covariates age --cluster pid --output "$WORK/o" 2>&1)"
44
+ echo "$OUT" | grep -q "95% CI" && ok "runtime: median prints 95% CI" || bad "runtime: median CI missing"
45
+ echo "$OUT" | grep -q "EPV =" && ok "runtime: EPV line printed" || bad "runtime: EPV missing"
46
+ echo "$OUT" | grep -q "cluster-sandwich" && ok "runtime: cluster SE applied" || bad "runtime: cluster SE missing"
47
+ else
48
+ echo " SKIP: lifelines not installed (static checks only)"
49
+ fi
50
+
51
+ echo ""
52
+ echo "test_survival_template: $PASS passed, $FAIL failed"
53
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: author-strategy
3
+ description: PubMed author profile analysis. Author name → PubMed fetch → study type classification → visualization → strategy report.
4
+ triggers: author-strategy, 저자 분석, publication analysis, 다작 분석, 연구 전략 분석, author profile, reverse engineer strategy
5
+ tools: Read, Write, Edit, Bash, Glob, Grep
6
+ model: inherit
7
+ ---
8
+
9
+ # /author-strategy — PubMed Author Strategy Analysis
10
+
11
+ ## Purpose
12
+
13
+ Analyze a researcher's PubMed publication portfolio to reverse-engineer their research strategy. Produces a CSV dataset, 7 visualizations, and a strategy report.
14
+
15
+ ## Prerequisites
16
+
17
+ - Python 3.10+ with `biopython`, `pandas`, `matplotlib`, `seaborn`
18
+ - Scripts: `${CLAUDE_SKILL_DIR}/fetch_pubmed.py`, `${CLAUDE_SKILL_DIR}/analyze_patterns.py`
19
+
20
+ ## Workflow
21
+
22
+ ### Step 1: Gather Input
23
+
24
+ Ask the user for:
25
+ 1. **Author name** (PubMed format, e.g., "Kim DK" or "Lee KS")
26
+ 2. **Last name** for position classification (auto-detected if ambiguous)
27
+ 3. **Output directory** (default: `~/.local/cache/author-strategy/{AuthorName}/`)
28
+
29
+ ### Step 2: Fetch PubMed Data
30
+
31
+ ```bash
32
+ python "${CLAUDE_SKILL_DIR}/fetch_pubmed.py" "{Author Name}" \
33
+ --last-name "{LastName}" \
34
+ --output "{output_dir}/data/{name}_publications.csv" \
35
+ --email "{user_email}"
36
+ ```
37
+
38
+ Review the console summary (total count, study type distribution, author position).
39
+ If count is 0, suggest alternative name formats (e.g., "Yon DK" vs "Yon D" vs "Yon Dong Keon").
40
+
41
+ ### Step 3: Generate Visualizations and Report
42
+
43
+ ```bash
44
+ python "${CLAUDE_SKILL_DIR}/analyze_patterns.py" "{output_dir}/data/{name}_publications.csv" \
45
+ --output-dir "{output_dir}/report/" \
46
+ --author-name "{Author Name}"
47
+ ```
48
+
49
+ This produces:
50
+ - 7 PNG charts (01-07)
51
+ - `analysis_report.md` with strategy breakdown
52
+
53
+ ### Step 4: Interpret and Present
54
+
55
+ Read `analysis_report.md` and present to the user:
56
+
57
+ 1. **Executive summary**: total publications, growth trajectory, high-tier rate
58
+ 2. **Primary strategy**: what study type dominates and why
59
+ 3. **Author position analysis**: leadership rate (1st + last) vs middle
60
+ 4. **Topic clusters**: research focus areas
61
+ 5. **ROI quadrant**: which strategies yield high-tier + leadership vs. volume only
62
+ 6. **Replication opportunities**: which patterns are replicable with Claude Code + public databases
63
+
64
+ ### Step 5: Optional — MA Gap Identification
65
+
66
+ If the user asks "what MA topics are feasible with this professor?":
67
+ - Cross-reference topic clusters with existing MA plans in memory
68
+ - Identify gaps where the professor has domain expertise but no MA published
69
+ - Output a prioritized list of MA proposals
70
+
71
+ ## Study Type Classifier
72
+
73
+ The classifier is tuned for Korean epidemiology and public health researchers. Categories:
74
+
75
+ | Type | Detection Pattern |
76
+ |------|------------------|
77
+ | GBD | "global burden" or "gbd" in title/abstract |
78
+ | SR/MA | "systematic review" or "meta-analysis" |
79
+ | NHIS/Claims | "national health insurance", "nhis", "claims database", "nationwide cohort" |
80
+ | Cross-national | Country pairs or "cross-national"/"binational" |
81
+ | National survey | "knhanes", "nhanes", "kchs", "national survey" |
82
+ | Biobank | "biobank" |
83
+ | AI/ML | "machine learning", "deep learning", "artificial intelligence" |
84
+ | Clinical trial | "randomized" or publication type |
85
+ | Case report | "case report" |
86
+ | Letter/Commentary | Publication type = letter/comment/editorial |
87
+
88
+ **Known limitation**: The classifier may undercount NHIS studies when they appear in Cross-national or Other categories. The report notes this.
89
+
90
+ ## Known Limitations
91
+
92
+ - The study type classifier is tuned for epidemiology and public health researchers. May undercount specialized study types for other fields.
93
+ - NHIS studies may be undercounted when they appear in cross-national or "other" categories.
94
+ - PubMed search requires an email for NCBI E-utilities (set via `--email` flag).
95
+
96
+ ## Anti-Hallucination
97
+
98
+ - **Never fabricate publication counts, h-index, or journal metrics.** All numbers must come from PubMed API output.
99
+ - **Never invent study classifications.** If a paper cannot be classified, label it as "Other" rather than guessing.
100
+ - If PubMed returns 0 results, suggest alternative name formats rather than generating fake data.
101
+
102
+ ## Output Structure
103
+
104
+ ```
105
+ {output_dir}/
106
+ data/
107
+ {name}_publications.csv
108
+ report/
109
+ analysis_report.md
110
+ 01_yearly_stacked.png
111
+ 02_study_type_pie.png
112
+ 03_author_position.png
113
+ 04_journal_tier_heatmap.png
114
+ 05_topic_distribution.png
115
+ 06_growth_curve.png
116
+ 07_strategy_roi.png
117
+ ```