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.
- package/LICENSE +50 -0
- package/README.md +602 -0
- package/README_FIRST.md +27 -0
- package/bin/medsci-skills.js +159 -0
- package/installers/install-macos.command +19 -0
- package/installers/install-windows.cmd +26 -0
- package/installers/install-windows.ps1 +17 -0
- package/installers/install.py +218 -0
- package/metadata/skills_catalog.json +452 -0
- package/package.json +48 -0
- package/skills/academic-aio/SKILL.md +408 -0
- package/skills/academic-aio/references/case_studies/kjr_mllm_2025.md +82 -0
- package/skills/academic-aio/references/checklists/AIO_GENERAL.md +354 -0
- package/skills/academic-aio/references/journal_summarybox_templates.yaml +126 -0
- package/skills/academic-aio/references/oac_funding_checklist.yaml +129 -0
- package/skills/academic-aio/references/reporting_guideline_mapping.md +39 -0
- package/skills/academic-aio/references/schema_markup_templates/CodeRepository.jsonld +32 -0
- package/skills/academic-aio/references/schema_markup_templates/Dataset.jsonld +36 -0
- package/skills/academic-aio/references/schema_markup_templates/Person.jsonld +30 -0
- package/skills/academic-aio/references/schema_markup_templates/README.md +43 -0
- package/skills/academic-aio/references/schema_markup_templates/ScholarlyArticle.jsonld +55 -0
- package/skills/academic-aio/scripts/batch_metadata_audit.py +169 -0
- package/skills/academic-aio/scripts/validate_schema.py +118 -0
- package/skills/academic-aio/skill.yml +36 -0
- package/skills/academic-aio/templates/aio_audit_checklist.md.j2 +108 -0
- package/skills/add-journal/SKILL.md +482 -0
- package/skills/add-journal/skill.yml +33 -0
- package/skills/analyze-stats/SKILL.md +598 -0
- package/skills/analyze-stats/references/analysis_guides/missing_data.md +109 -0
- package/skills/analyze-stats/references/analysis_guides/nhis_icd10_mapping.md +247 -0
- package/skills/analyze-stats/references/analysis_guides/propensity_score.md +132 -0
- package/skills/analyze-stats/references/analysis_guides/regression.md +115 -0
- package/skills/analyze-stats/references/analysis_guides/repeated_measures.md +160 -0
- package/skills/analyze-stats/references/analysis_guides/survey_weighted.md +366 -0
- package/skills/analyze-stats/references/analysis_guides/test_selection.md +86 -0
- package/skills/analyze-stats/references/style/figure_style.mplstyle +69 -0
- package/skills/analyze-stats/references/style/theme_publication.R +147 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/ajr.yaml +51 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/european_radiology.yaml +55 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/jama.yaml +66 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/lancet.yaml +57 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/nejm.yaml +51 -0
- package/skills/analyze-stats/references/table-standards/journal-profiles/radiology.yaml +66 -0
- package/skills/analyze-stats/references/table-standards/table-standards.md +287 -0
- package/skills/analyze-stats/references/table-standards/table-types/diagnostic_accuracy.md +36 -0
- package/skills/analyze-stats/references/table-standards/table-types/meta_analysis.md +58 -0
- package/skills/analyze-stats/references/table-standards/table-types/model_comparison.md +36 -0
- package/skills/analyze-stats/references/table-standards/table-types/regression_results.md +50 -0
- package/skills/analyze-stats/references/table-standards/table-types/table1_demographics.md +51 -0
- package/skills/analyze-stats/references/table-standards/tool-comparison.md +79 -0
- package/skills/analyze-stats/references/templates/agreement_analysis.py +436 -0
- package/skills/analyze-stats/references/templates/dca_plot.R +237 -0
- package/skills/analyze-stats/references/templates/diagnostic_accuracy.py +401 -0
- package/skills/analyze-stats/references/templates/dta_meta_analysis.R +384 -0
- package/skills/analyze-stats/references/templates/forest_plot.py +412 -0
- package/skills/analyze-stats/references/templates/likert_summary.py +356 -0
- package/skills/analyze-stats/references/templates/meta_analysis.R +365 -0
- package/skills/analyze-stats/references/templates/propensity_score.py +478 -0
- package/skills/analyze-stats/references/templates/regression.py +425 -0
- package/skills/analyze-stats/references/templates/repeated_measures.py +434 -0
- package/skills/analyze-stats/references/templates/sample_size.R +382 -0
- package/skills/analyze-stats/references/templates/survey_weighted_analysis.py +411 -0
- package/skills/analyze-stats/references/templates/survival_analysis.py +325 -0
- package/skills/analyze-stats/references/templates/table1_demographics.py +287 -0
- package/skills/analyze-stats/scripts/check_generated_code.py +335 -0
- package/skills/analyze-stats/skill.yml +38 -0
- package/skills/analyze-stats/tests/fixtures/gen_bad.R +16 -0
- package/skills/analyze-stats/tests/fixtures/gen_bad.py +24 -0
- package/skills/analyze-stats/tests/fixtures/gen_clean.py +21 -0
- package/skills/analyze-stats/tests/test_generated_code.sh +59 -0
- package/skills/analyze-stats/tests/test_survival_template.sh +53 -0
- package/skills/author-strategy/SKILL.md +117 -0
- package/skills/author-strategy/analyze_patterns.py +303 -0
- package/skills/author-strategy/fetch_pubmed.py +374 -0
- package/skills/author-strategy/skill.yml +34 -0
- package/skills/batch-cohort/SKILL.md +223 -0
- package/skills/batch-cohort/references/base_template_knhanes.R +210 -0
- package/skills/batch-cohort/references/batch_template_generator.R +222 -0
- package/skills/batch-cohort/references/variable_coding_registry.md +136 -0
- package/skills/batch-cohort/skill.yml +35 -0
- package/skills/calc-sample-size/SKILL.md +491 -0
- package/skills/calc-sample-size/references/formulas.md +655 -0
- package/skills/calc-sample-size/references/observational_cohort.md +49 -0
- package/skills/calc-sample-size/skill.yml +51 -0
- package/skills/check-reporting/SKILL.md +534 -0
- package/skills/check-reporting/references/LICENSES.md +41 -0
- package/skills/check-reporting/references/checklists/AMSTAR2.md +54 -0
- package/skills/check-reporting/references/checklists/ARRIVE_2.md +234 -0
- package/skills/check-reporting/references/checklists/CARE.md +102 -0
- package/skills/check-reporting/references/checklists/CLAIM_2024.md +128 -0
- package/skills/check-reporting/references/checklists/CLEAR.md +113 -0
- package/skills/check-reporting/references/checklists/CONSORT.md +86 -0
- package/skills/check-reporting/references/checklists/COSMIN_RoB.md +136 -0
- package/skills/check-reporting/references/checklists/GRRAS.md +61 -0
- package/skills/check-reporting/references/checklists/MI_CLEAR_LLM.md +167 -0
- package/skills/check-reporting/references/checklists/MOOSE.md +85 -0
- package/skills/check-reporting/references/checklists/NOS.md +88 -0
- package/skills/check-reporting/references/checklists/PRISMA_2020.md +135 -0
- package/skills/check-reporting/references/checklists/PRISMA_DTA.md +36 -0
- package/skills/check-reporting/references/checklists/PRISMA_P.md +56 -0
- package/skills/check-reporting/references/checklists/PROBAST.md +75 -0
- package/skills/check-reporting/references/checklists/PROBAST_AI.md +130 -0
- package/skills/check-reporting/references/checklists/QUADAS2.md +77 -0
- package/skills/check-reporting/references/checklists/QUADAS_C.md +131 -0
- package/skills/check-reporting/references/checklists/ROBINS_E.md +179 -0
- package/skills/check-reporting/references/checklists/ROBINS_I.md +87 -0
- package/skills/check-reporting/references/checklists/ROBIS.md +114 -0
- package/skills/check-reporting/references/checklists/ROB_ME.md +126 -0
- package/skills/check-reporting/references/checklists/RoB2.md +79 -0
- package/skills/check-reporting/references/checklists/RoB_NMA.md +96 -0
- package/skills/check-reporting/references/checklists/SPIRIT.md +112 -0
- package/skills/check-reporting/references/checklists/SQUIRE_2.md +68 -0
- package/skills/check-reporting/references/checklists/STARD.md +129 -0
- package/skills/check-reporting/references/checklists/STARD_AI.md +211 -0
- package/skills/check-reporting/references/checklists/STROBE.md +80 -0
- package/skills/check-reporting/references/checklists/SWiM.md +33 -0
- package/skills/check-reporting/references/checklists/TRIPOD.md +157 -0
- package/skills/check-reporting/references/checklists/TRIPOD_AI.md +140 -0
- package/skills/check-reporting/references/step4c_registration_timing.md +93 -0
- package/skills/check-reporting/references/step4d_prisma_figure_audit.md +137 -0
- package/skills/check-reporting/scripts/check_checklist_exists.py +183 -0
- package/skills/check-reporting/scripts/check_checklist_version.py +168 -0
- package/skills/check-reporting/scripts/check_framework_naming.py +206 -0
- package/skills/check-reporting/scripts/check_prisma_figure.py +209 -0
- package/skills/check-reporting/scripts/prisma_cascade_check.py +274 -0
- package/skills/check-reporting/skill.yml +41 -0
- package/skills/check-reporting/tests/fixtures/framework_bad.md +8 -0
- package/skills/check-reporting/tests/fixtures/framework_clean.md +7 -0
- package/skills/check-reporting/tests/test_checklist_fail_fast.sh +77 -0
- package/skills/check-reporting/tests/test_checklist_version.sh +72 -0
- package/skills/check-reporting/tests/test_framework_naming.sh +45 -0
- package/skills/check-reporting/tests/test_prisma_cascade.sh +104 -0
- package/skills/clean-data/SKILL.md +180 -0
- package/skills/clean-data/references/cleaning_patterns.md +299 -0
- package/skills/clean-data/references/profiling_template.py +304 -0
- package/skills/clean-data/scripts/check_structural_zero.py +174 -0
- package/skills/clean-data/skill.yml +35 -0
- package/skills/clean-data/tests/fixtures/smoking.csv +8 -0
- package/skills/clean-data/tests/test_structural_zero.sh +49 -0
- package/skills/cross-national/SKILL.md +264 -0
- package/skills/cross-national/skill.yml +37 -0
- package/skills/define-variables/SKILL.md +146 -0
- package/skills/define-variables/references/common_definitions.md +190 -0
- package/skills/define-variables/skill.yml +34 -0
- package/skills/define-variables/templates/variable_operationalization.md +64 -0
- package/skills/deidentify/SKILL.md +203 -0
- package/skills/deidentify/deidentify.py +1224 -0
- package/skills/deidentify/locales/_template.json +45 -0
- package/skills/deidentify/locales/au.json +43 -0
- package/skills/deidentify/locales/ca.json +44 -0
- package/skills/deidentify/locales/cn.json +47 -0
- package/skills/deidentify/locales/de.json +48 -0
- package/skills/deidentify/locales/fr.json +48 -0
- package/skills/deidentify/locales/in.json +48 -0
- package/skills/deidentify/locales/jp.json +48 -0
- package/skills/deidentify/locales/kr.json +48 -0
- package/skills/deidentify/locales/uk.json +45 -0
- package/skills/deidentify/locales/us.json +43 -0
- package/skills/deidentify/references/date_shift_guide.md +82 -0
- package/skills/deidentify/references/hipaa_18_identifiers.md +48 -0
- package/skills/deidentify/references/korean_phi_patterns.md +135 -0
- package/skills/deidentify/skill.yml +43 -0
- package/skills/deidentify/tests/README.md +26 -0
- package/skills/deidentify/tests/test_clean.csv +16 -0
- package/skills/deidentify/tests/test_edge_cases.csv +11 -0
- package/skills/deidentify/tests/test_phi_korean.csv +11 -0
- package/skills/design-ai-benchmarking/SKILL.md +214 -0
- package/skills/design-ai-benchmarking/references/benchmark_export_schema.json +69 -0
- package/skills/design-ai-benchmarking/references/elicitation_rubric_template.md +37 -0
- package/skills/design-ai-benchmarking/skill.yml +38 -0
- package/skills/design-study/SKILL.md +298 -0
- package/skills/design-study/skill.yml +33 -0
- package/skills/fill-icmje-coi/SKILL.md +216 -0
- package/skills/fill-icmje-coi/scripts/fill_icmje_coi.py +140 -0
- package/skills/fill-icmje-coi/skill.yml +35 -0
- package/skills/fill-icmje-coi/templates/icmje_coi_seed_synthetic.docx +0 -0
- package/skills/fill-protocol/SKILL.md +248 -0
- package/skills/fill-protocol/examples/example_irb_template.yaml +53 -0
- package/skills/fill-protocol/references/best_practices.md +121 -0
- package/skills/fill-protocol/scripts/doc_to_docx.py +111 -0
- package/skills/fill-protocol/scripts/fill_form.py +611 -0
- package/skills/fill-protocol/scripts/inspect_template.py +61 -0
- package/skills/fill-protocol/setup.sh +162 -0
- package/skills/fill-protocol/skill.yml +37 -0
- package/skills/find-cohort-gap/SKILL.md +309 -0
- package/skills/find-cohort-gap/references/cohort_profile_template.md +93 -0
- package/skills/find-cohort-gap/references/onepager_template.md +84 -0
- package/skills/find-cohort-gap/references/pattern_scoring_rubric.md +169 -0
- package/skills/find-cohort-gap/references/saturation_query_templates.md +143 -0
- package/skills/find-cohort-gap/skill.yml +35 -0
- package/skills/find-journal/POLICY.md +87 -0
- package/skills/find-journal/SKILL.md +340 -0
- package/skills/find-journal/references/journal_profiles/AJNR.md +29 -0
- package/skills/find-journal/references/journal_profiles/AJR.md +30 -0
- package/skills/find-journal/references/journal_profiles/Abdominal_Radiology.md +30 -0
- package/skills/find-journal/references/journal_profiles/Academic_Radiology.md +30 -0
- package/skills/find-journal/references/journal_profiles/Annals_of_Internal_Medicine.md +33 -0
- package/skills/find-journal/references/journal_profiles/Artificial_Intelligence_in_Medicine.md +28 -0
- package/skills/find-journal/references/journal_profiles/BMC_Medicine.md +31 -0
- package/skills/find-journal/references/journal_profiles/British_Journal_of_Radiology.md +39 -0
- package/skills/find-journal/references/journal_profiles/CVIR.md +30 -0
- package/skills/find-journal/references/journal_profiles/Chest.md +39 -0
- package/skills/find-journal/references/journal_profiles/Clinical_Radiology.md +30 -0
- package/skills/find-journal/references/journal_profiles/Clinical_and_Molecular_Hepatology.md +32 -0
- package/skills/find-journal/references/journal_profiles/Diabetes_Metabolism_Journal.md +36 -0
- package/skills/find-journal/references/journal_profiles/Diagnostic_and_Interventional_Radiology.md +32 -0
- package/skills/find-journal/references/journal_profiles/Endocrinology_and_Metabolism.md +37 -0
- package/skills/find-journal/references/journal_profiles/European_Journal_of_Preventive_Cardiology.md +39 -0
- package/skills/find-journal/references/journal_profiles/European_Radiology.md +29 -0
- package/skills/find-journal/references/journal_profiles/Hepatology_Communications.md +40 -0
- package/skills/find-journal/references/journal_profiles/Hepatology_International.md +37 -0
- package/skills/find-journal/references/journal_profiles/IEEE_JBHI.md +28 -0
- package/skills/find-journal/references/journal_profiles/IEEE_TMI.md +28 -0
- package/skills/find-journal/references/journal_profiles/INSI.md +29 -0
- package/skills/find-journal/references/journal_profiles/Investigative_Radiology.md +25 -0
- package/skills/find-journal/references/journal_profiles/JACC_Advances.md +41 -0
- package/skills/find-journal/references/journal_profiles/JACC_Asia.md +30 -0
- package/skills/find-journal/references/journal_profiles/JACR.md +28 -0
- package/skills/find-journal/references/journal_profiles/JAMA.md +40 -0
- package/skills/find-journal/references/journal_profiles/JAMA_Network_Open.md +30 -0
- package/skills/find-journal/references/journal_profiles/JCSM.md +39 -0
- package/skills/find-journal/references/journal_profiles/JKMS.md +32 -0
- package/skills/find-journal/references/journal_profiles/JMIR.md +29 -0
- package/skills/find-journal/references/journal_profiles/JMIR_Medical_Education.md +29 -0
- package/skills/find-journal/references/journal_profiles/JNIS.md +35 -0
- package/skills/find-journal/references/journal_profiles/JVIR.md +31 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Biomedical_Informatics.md +29 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Clinical_Endocrinology_and_Metabolism.md +40 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Magnetic_Resonance_Imaging.md +30 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Nuclear_Medicine.md +31 -0
- package/skills/find-journal/references/journal_profiles/Journal_of_Stroke.md +32 -0
- package/skills/find-journal/references/journal_profiles/KJR.md +38 -0
- package/skills/find-journal/references/journal_profiles/Korean_Circulation_Journal.md +38 -0
- package/skills/find-journal/references/journal_profiles/Korean_Journal_of_Internal_Medicine.md +36 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Diabetes_and_Endocrinology.md +40 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Gastroenterology_and_Hepatology.md +49 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Infectious_Diseases.md +38 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Neurology.md +39 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Oncology.md +40 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Psychiatry.md +38 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Public_Health.md +30 -0
- package/skills/find-journal/references/journal_profiles/Lancet_Respiratory_Medicine.md +39 -0
- package/skills/find-journal/references/journal_profiles/Liver_International.md +33 -0
- package/skills/find-journal/references/journal_profiles/Medical_Image_Analysis.md +28 -0
- package/skills/find-journal/references/journal_profiles/NEJM.md +33 -0
- package/skills/find-journal/references/journal_profiles/Nature_Machine_Intelligence.md +31 -0
- package/skills/find-journal/references/journal_profiles/Nature_Medicine.md +39 -0
- package/skills/find-journal/references/journal_profiles/Neuroradiology.md +31 -0
- package/skills/find-journal/references/journal_profiles/Nutrition_Metabolism_and_Cardiovascular_Diseases.md +39 -0
- package/skills/find-journal/references/journal_profiles/PLOS_Medicine.md +32 -0
- package/skills/find-journal/references/journal_profiles/RYAI.md +28 -0
- package/skills/find-journal/references/journal_profiles/Radiology.md +29 -0
- package/skills/find-journal/references/journal_profiles/Skeletal_Radiology.md +31 -0
- package/skills/find-journal/references/journal_profiles/Stroke.md +37 -0
- package/skills/find-journal/references/journal_profiles/The_BMJ.md +31 -0
- package/skills/find-journal/references/journal_profiles/The_Lancet.md +31 -0
- package/skills/find-journal/references/journal_profiles/The_Lancet_Digital_Health.md +29 -0
- package/skills/find-journal/references/journal_profiles/World_Journal_of_Hepatology.md +53 -0
- package/skills/find-journal/references/journal_profiles/npj_Digital_Medicine.md +29 -0
- package/skills/find-journal/skill.yml +34 -0
- package/skills/fulltext-retrieval/SKILL.md +174 -0
- package/skills/fulltext-retrieval/fetch_oa.py +433 -0
- package/skills/fulltext-retrieval/pdf_to_md.py +160 -0
- package/skills/fulltext-retrieval/skill.yml +41 -0
- package/skills/generate-codebook/SKILL.md +155 -0
- package/skills/generate-codebook/references/codebook_schema.md +76 -0
- package/skills/generate-codebook/scripts/generate_codebook.py +278 -0
- package/skills/generate-codebook/skill.yml +35 -0
- package/skills/generate-codebook/tests/test_generate_codebook.sh +76 -0
- package/skills/grant-builder/SKILL.md +251 -0
- package/skills/grant-builder/skill.yml +34 -0
- package/skills/humanize/SKILL.md +251 -0
- package/skills/humanize/references/ai_patterns.md +571 -0
- package/skills/humanize/skill.yml +33 -0
- package/skills/intake-project/SKILL.md +264 -0
- package/skills/intake-project/skill.yml +34 -0
- package/skills/lit-sync/SKILL.md +448 -0
- package/skills/lit-sync/references/locale/ko/note_templates.md +110 -0
- package/skills/lit-sync/skill.yml +52 -0
- package/skills/lit-sync/tests/test_poll_logic.sh +92 -0
- package/skills/ma-scout/SKILL.md +640 -0
- package/skills/ma-scout/references/project_readme_template.md +95 -0
- package/skills/ma-scout/references/project_readme_template_ko.md +82 -0
- package/skills/ma-scout/skill.yml +33 -0
- package/skills/make-figures/SKILL.md +957 -0
- package/skills/make-figures/references/critic_rubrics/data_plot.md +166 -0
- package/skills/make-figures/references/critic_rubrics/flow_diagram.md +169 -0
- package/skills/make-figures/references/design_principles.md +181 -0
- package/skills/make-figures/references/exemplar_diagrams/README.md +65 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_input.yaml +37 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/consort/template_output_600.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/other/other_02.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/other/other_02.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/other/other_02_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_01_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_03_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_04_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_05_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_06_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_07_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_08_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_09_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10.meta.yaml +4 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/pipeline/pipeline_10_why.md +13 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_input.yaml +47 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/prisma/template_output_600.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/README.md +15 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_input.yaml +40 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/stard/template_output_600.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_input.yaml +43 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_input_pptx.yaml +43 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.pdf +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.png +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output.pptx +0 -0
- package/skills/make-figures/references/exemplar_diagrams/strobe/template_output_600.png +0 -0
- package/skills/make-figures/references/figure_specs.md +291 -0
- package/skills/make-figures/references/flow_diagram_lessons.md +164 -0
- package/skills/make-figures/references/jacc_central_illustration_principles.md +91 -0
- package/skills/make-figures/references/medical_illustration_sources.md +98 -0
- package/skills/make-figures/references/pipeline_concepts_medical_ai.md +240 -0
- package/skills/make-figures/references/reporting_guideline_figure_map.md +104 -0
- package/skills/make-figures/references/visual_abstract_templates/european_radiology.pptx +0 -0
- package/skills/make-figures/references/visual_abstract_templates/jacc_central_illustration.pptx +0 -0
- package/skills/make-figures/references/visual_abstract_templates/medsci_default.pptx +0 -0
- package/skills/make-figures/references/visual_abstract_templates/template_guide.md +114 -0
- package/skills/make-figures/scripts/build_jacc_template.py +77 -0
- package/skills/make-figures/scripts/build_prisma2020_template.py +371 -0
- package/skills/make-figures/scripts/build_strobe_template.py +351 -0
- package/skills/make-figures/scripts/critic_figure.py +264 -0
- package/skills/make-figures/scripts/derive_figure_legend_counts.py +138 -0
- package/skills/make-figures/scripts/extract_exemplar_from_pdf.py +186 -0
- package/skills/make-figures/scripts/fetch_official_templates.sh +88 -0
- package/skills/make-figures/scripts/fill_prisma_template.py +142 -0
- package/skills/make-figures/scripts/generate_flow_diagram.R +133 -0
- package/skills/make-figures/scripts/generate_image.py +99 -0
- package/skills/make-figures/scripts/generate_visual_abstract.py +438 -0
- package/skills/make-figures/scripts/validate_pptx_mac_compat.py +233 -0
- package/skills/make-figures/skill.yml +52 -0
- package/skills/make-figures/templates/official/NOTES.md +62 -0
- package/skills/make-figures/templates/official/consort2010/CONSORT_2025_editable_checklist.docx +0 -0
- package/skills/make-figures/templates/official/consort2010/CONSORT_2025_flow_diagram.docx +0 -0
- package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_new_v1.pptx +0 -0
- package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_new_v2.pptx +0 -0
- package/skills/make-figures/templates/official/prisma2020/PRISMA_2020_flow_updated_v2.pptx +0 -0
- package/skills/make-figures/templates/official/spirit2013/SPIRIT_2025_editable_checklist.docx +0 -0
- package/skills/make-figures/templates/official/spirit2013/SPIRIT_2025_participant_timeline.docx +0 -0
- package/skills/make-figures/templates/official/stard2015/STARD_2015_checklist.docx +0 -0
- package/skills/make-figures/templates/official/stard2015/STARD_2015_flow_diagram.pdf +0 -0
- package/skills/make-figures/tests/fixtures/figure1_flow.yaml +8 -0
- package/skills/make-figures/tests/fixtures/manuscript_ok.md +9 -0
- package/skills/make-figures/tests/fixtures/manuscript_stale.md +4 -0
- package/skills/make-figures/tests/test_legend_reconcile.sh +36 -0
- package/skills/manage-project/SKILL.md +358 -0
- package/skills/manage-project/references/pre_submission_checklist.md +53 -0
- package/skills/manage-project/references/project_state_template.json +37 -0
- package/skills/manage-project/references/scaffold_templates.md +118 -0
- package/skills/manage-project/references/status_output_format.md +44 -0
- package/skills/manage-project/references/timeline_example.md +20 -0
- package/skills/manage-project/skill.yml +36 -0
- package/skills/manage-project/templates/SSOT.yaml.template +41 -0
- package/skills/manage-refs/LICENSE.zotero-mcp +21 -0
- package/skills/manage-refs/NOTICE.md +29 -0
- package/skills/manage-refs/SKILL.md +289 -0
- package/skills/manage-refs/citation_styles/README.md +40 -0
- package/skills/manage-refs/citation_styles/american-journal-of-roentgenology.csl +211 -0
- package/skills/manage-refs/citation_styles/cardiovascular-and-interventional-radiology.csl +19 -0
- package/skills/manage-refs/citation_styles/european-radiology.csl +19 -0
- package/skills/manage-refs/citation_styles/journal-of-cachexia-sarcopenia-and-muscle.csl +150 -0
- package/skills/manage-refs/citation_styles/journal-of-korean-medical-science-strict.csl +533 -0
- package/skills/manage-refs/citation_styles/journal-of-korean-medical-science.csl +16 -0
- package/skills/manage-refs/citation_styles/korean-journal-of-radiology.csl +155 -0
- package/skills/manage-refs/citation_styles/nature.csl +189 -0
- package/skills/manage-refs/citation_styles/nlm-citation-sequence.csl +535 -0
- package/skills/manage-refs/citation_styles/radiology.csl +228 -0
- package/skills/manage-refs/citation_styles/springer-basic-brackets.csl +187 -0
- package/skills/manage-refs/citation_styles/springer-vancouver-brackets.csl +276 -0
- package/skills/manage-refs/citation_styles/vancouver-superscript.csl +536 -0
- package/skills/manage-refs/citation_styles/vancouver.csl +535 -0
- package/skills/manage-refs/references/REFERENCE_STYLE_SPECS.md +59 -0
- package/skills/manage-refs/references/check_xref_symptoms.md +35 -0
- package/skills/manage-refs/scripts/_vendor_citation_writer.py +600 -0
- package/skills/manage-refs/scripts/check_citation_keys.py +112 -0
- package/skills/manage-refs/scripts/check_csl_render.py +102 -0
- package/skills/manage-refs/scripts/check_xref.py +633 -0
- package/skills/manage-refs/scripts/fill_journal_abbrev.py +104 -0
- package/skills/manage-refs/scripts/inject_zotero_cwyw.py +133 -0
- package/skills/manage-refs/scripts/md_marker_convert.py +193 -0
- package/skills/manage-refs/scripts/pre_submission_gate.sh +238 -0
- package/skills/manage-refs/scripts/render_pandoc.sh +88 -0
- package/skills/manage-refs/skill.yml +70 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/README.md +32 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/manuscript.md +10 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/refs.bib +34 -0
- package/skills/manage-refs/tests/fixtures/pre_submission_gate/run.sh +117 -0
- package/skills/manage-refs/tests/test_vN_docx_check.sh +145 -0
- package/skills/meta-analysis/SKILL.md +739 -0
- package/skills/meta-analysis/references/LICENSES.md +21 -0
- package/skills/meta-analysis/references/PROSPERO_template.md +221 -0
- package/skills/meta-analysis/references/ai_pre_screening_template.py +245 -0
- package/skills/meta-analysis/references/checklists/JBI_Case_Series.md +45 -0
- package/skills/meta-analysis/references/checklists/NOS.md +88 -0
- package/skills/meta-analysis/references/checklists/PRISMA_DTA.md +36 -0
- package/skills/meta-analysis/references/checklists/PROBAST.md +75 -0
- package/skills/meta-analysis/references/checklists/QUADAS2.md +77 -0
- package/skills/meta-analysis/references/checklists/ROBINS_I.md +87 -0
- package/skills/meta-analysis/references/checklists/RoB2.md +79 -0
- package/skills/meta-analysis/references/data_integrity_checklist.md +57 -0
- package/skills/meta-analysis/references/icmje_coi_guide.md +181 -0
- package/skills/meta-analysis/references/phase10_recovery.md +136 -0
- package/skills/meta-analysis/references/phase4_km_composite.md +58 -0
- package/skills/meta-analysis/references/phase6_statistical_synthesis.md +148 -0
- package/skills/meta-analysis/references/phase9_circulation.md +84 -0
- package/skills/meta-analysis/references/post_submission_release_ops.md +41 -0
- package/skills/meta-analysis/references/r_templates.md +132 -0
- package/skills/meta-analysis/references/review_orchestration.md +40 -0
- package/skills/meta-analysis/references/submission_package_drift.md +71 -0
- package/skills/meta-analysis/scripts/check_pool_consistency.py +201 -0
- package/skills/meta-analysis/scripts/cohort_overlap_check.py +242 -0
- package/skills/meta-analysis/scripts/dta_extraction_qc.py +137 -0
- package/skills/meta-analysis/scripts/screening_reconcile.py +160 -0
- package/skills/meta-analysis/skill.yml +47 -0
- package/skills/meta-analysis/templates/FINAL_POOL_LOCK.yaml.template +70 -0
- package/skills/meta-analysis/templates/extraction_form_v2.md +129 -0
- package/skills/meta-analysis/templates/supplementary_8file_checklist.md +94 -0
- package/skills/meta-analysis/tests/test_pool_consistency.sh +123 -0
- package/skills/orchestrate/SKILL.md +501 -0
- package/skills/orchestrate/references/dialogue_nodes.md +196 -0
- package/skills/orchestrate/references/report_template.md +109 -0
- package/skills/orchestrate/references/report_template_ko.md +88 -0
- package/skills/orchestrate/skill.yml +44 -0
- package/skills/peer-review/SKILL.md +381 -0
- package/skills/peer-review/references/aczel_2021_reviewer2_patterns.md +88 -0
- package/skills/peer-review/references/domain-probes/ai_overclaiming.md +47 -0
- package/skills/peer-review/references/domain-probes/narrative_review.md +44 -0
- package/skills/peer-review/references/domain-probes/observational_confounding.md +48 -0
- package/skills/peer-review/references/domain-probes/radiomics.md +38 -0
- package/skills/peer-review/references/domain-probes/sr_ma.md +87 -0
- package/skills/peer-review/references/domain-probes/survival_prognostic.md +68 -0
- package/skills/peer-review/references/exemplar_reviews/README.md +43 -0
- package/skills/peer-review/references/exemplar_reviews/ai_overclaiming.md +47 -0
- package/skills/peer-review/references/exemplar_reviews/calibration_missing.md +44 -0
- package/skills/peer-review/references/exemplar_reviews/data_leakage.md +48 -0
- package/skills/peer-review/references/exemplar_reviews/reference_standard_validity.md +45 -0
- package/skills/peer-review/references/narrative_review_audit.md +67 -0
- package/skills/peer-review/references/reviewer_calibration/README.md +34 -0
- package/skills/peer-review/references/reviewer_calibration/compliance_floor.md +52 -0
- package/skills/peer-review/references/reviewer_profiles/AJR.md +82 -0
- package/skills/peer-review/references/reviewer_profiles/EURE.md +64 -0
- package/skills/peer-review/references/reviewer_profiles/INSI.md +57 -0
- package/skills/peer-review/references/reviewer_profiles/KJR.md +100 -0
- package/skills/peer-review/references/reviewer_profiles/README.md +32 -0
- package/skills/peer-review/references/reviewer_profiles/RYAI.md +86 -0
- package/skills/peer-review/skill.yml +39 -0
- package/skills/present-paper/SKILL.md +675 -0
- package/skills/present-paper/references/critic_rubrics/slide.md +155 -0
- package/skills/present-paper/references/generate_pptx_templates.py +604 -0
- package/skills/present-paper/references/medical_presentation_templates.md +277 -0
- package/skills/present-paper/references/slide_design_principles.md +202 -0
- package/skills/present-paper/references/slide_visual_styles/nature_lancet.md +168 -0
- package/skills/present-paper/references/workflow-checklist.md +109 -0
- package/skills/present-paper/scripts/extract_pdf_figures.py +243 -0
- package/skills/present-paper/scripts/inject_pronunciation_notes.py +178 -0
- package/skills/present-paper/scripts/inject_speaker_notes.py +133 -0
- package/skills/present-paper/scripts/strip_notes_for_sharing.py +140 -0
- package/skills/present-paper/scripts/trim_caption.py +271 -0
- package/skills/present-paper/skill.yml +41 -0
- package/skills/present-paper/templates/build_pptx_nature_lancet.py +688 -0
- package/skills/publish-skill/SKILL.md +370 -0
- package/skills/publish-skill/references/license-compatibility-matrix.md +132 -0
- package/skills/publish-skill/references/pii-patterns.md +130 -0
- package/skills/publish-skill/scripts/audit_skill.sh +278 -0
- package/skills/publish-skill/skill.yml +35 -0
- package/skills/render-pdf-doc/SKILL.md +146 -0
- package/skills/render-pdf-doc/references/known_pitfalls.md +53 -0
- package/skills/render-pdf-doc/references/pandoc_korean_cheatsheet.md +77 -0
- package/skills/render-pdf-doc/scripts/check_deps.sh +42 -0
- package/skills/render-pdf-doc/scripts/infer_colwidths.py +164 -0
- package/skills/render-pdf-doc/scripts/render_pdf.sh +98 -0
- package/skills/render-pdf-doc/skill.yml +57 -0
- package/skills/render-pdf-doc/templates/anchor-doc.md +27 -0
- package/skills/render-pdf-doc/templates/anchor-doc_ko.md +25 -0
- package/skills/render-pdf-doc/templates/briefing-handout.md +33 -0
- package/skills/render-pdf-doc/templates/briefing-handout_ko.md +31 -0
- package/skills/render-pdf-doc/templates/proposal-cover.md +33 -0
- package/skills/render-pdf-doc/templates/proposal-cover_ko.md +31 -0
- package/skills/render-pdf-doc/templates/reference-table.md +22 -0
- package/skills/render-pdf-doc/templates/reference-table_ko.md +20 -0
- package/skills/replicate-study/SKILL.md +150 -0
- package/skills/replicate-study/references/harmonization_3country.csv +47 -0
- package/skills/replicate-study/references/harmonization_knhanes_nhanes.csv +68 -0
- package/skills/replicate-study/references/methodology_extraction_template.md +134 -0
- package/skills/replicate-study/skill.yml +37 -0
- package/skills/review-paper/SKILL.md +104 -0
- package/skills/review-paper/references/macro_skeleton.md +6 -0
- package/skills/review-paper/skill.yml +25 -0
- package/skills/revise/SKILL.md +515 -0
- package/skills/revise/references/r2r_voice.md +346 -0
- package/skills/revise/skill.yml +43 -0
- package/skills/search-lit/SKILL.md +443 -0
- package/skills/search-lit/references/parse_pubmed.py +326 -0
- package/skills/search-lit/references/pubmed_eutils.sh +111 -0
- package/skills/search-lit/skill.yml +46 -0
- package/skills/self-review/SKILL.md +1045 -0
- package/skills/self-review/references/domain-probes/ai_overclaiming.md +47 -0
- package/skills/self-review/references/domain-probes/narrative_review.md +44 -0
- package/skills/self-review/references/domain-probes/observational_confounding.md +48 -0
- package/skills/self-review/references/domain-probes/radiomics.md +38 -0
- package/skills/self-review/references/domain-probes/sr_ma.md +87 -0
- package/skills/self-review/references/domain-probes/survival_prognostic.md +68 -0
- package/skills/self-review/references/exemplar_findings/README.md +43 -0
- package/skills/self-review/references/exemplar_findings/cohort_arithmetic_mismatch.md +35 -0
- package/skills/self-review/references/exemplar_findings/estimand_drift_posthoc_primary.md +39 -0
- package/skills/self-review/references/exemplar_findings/scope_overreach_cross_sectional.md +35 -0
- package/skills/self-review/references/exemplar_findings/unadjusted_confounder.md +36 -0
- package/skills/self-review/references/panel_review_template.md +177 -0
- package/skills/self-review/scripts/check_artifact_coverage.py +301 -0
- package/skills/self-review/scripts/check_claim_artifact.py +248 -0
- package/skills/self-review/scripts/check_classical_style.py +185 -0
- package/skills/self-review/scripts/check_cohort_arithmetic.py +481 -0
- package/skills/self-review/scripts/check_confounding_completeness.py +287 -0
- package/skills/self-review/scripts/check_panel_diversity.py +336 -0
- package/skills/self-review/scripts/check_reference_adequacy.py +392 -0
- package/skills/self-review/scripts/check_reviewer_team_consistency.py +412 -0
- package/skills/self-review/scripts/check_scope_coherence.py +177 -0
- package/skills/self-review/skill.yml +47 -0
- package/skills/self-review/tests/fixtures/claim_manuscript.md +17 -0
- package/skills/self-review/tests/fixtures/claim_prereg.md +6 -0
- package/skills/self-review/tests/fixtures/cohort_bad.md +21 -0
- package/skills/self-review/tests/fixtures/cohort_clean.md +21 -0
- package/skills/self-review/tests/fixtures/cohort_partition.csv +5 -0
- package/skills/self-review/tests/fixtures/coverage_analysis/31_delong_nested_added_value.csv +3 -0
- package/skills/self-review/tests/fixtures/coverage_analysis/table1_demographics.csv +3 -0
- package/skills/self-review/tests/fixtures/coverage_clean.md +13 -0
- package/skills/self-review/tests/fixtures/coverage_manuscript.md +11 -0
- package/skills/self-review/tests/fixtures/panel_collapse.json +27 -0
- package/skills/self-review/tests/fixtures/panel_good.json +32 -0
- package/skills/self-review/tests/fixtures/panel_monoculture.json +32 -0
- package/skills/self-review/tests/fixtures/refadeq_letter.md +13 -0
- package/skills/self-review/tests/fixtures/refadeq_original_fixed.md +42 -0
- package/skills/self-review/tests/fixtures/refadeq_original_uncited.md +40 -0
- package/skills/self-review/tests/fixtures/scope_bad.md +9 -0
- package/skills/self-review/tests/fixtures/scope_clean.md +8 -0
- package/skills/self-review/tests/fixtures/scope_surrogate.md +8 -0
- package/skills/self-review/tests/fixtures/style_bad.md +13 -0
- package/skills/self-review/tests/fixtures/style_clean.md +11 -0
- package/skills/self-review/tests/fixtures/table1_by_exposure.csv +11 -0
- package/skills/self-review/tests/test_artifact_coverage.sh +44 -0
- package/skills/self-review/tests/test_claim_artifact.sh +50 -0
- package/skills/self-review/tests/test_classical_style.sh +44 -0
- package/skills/self-review/tests/test_cohort_arithmetic.sh +49 -0
- package/skills/self-review/tests/test_confounding_completeness.sh +66 -0
- package/skills/self-review/tests/test_panel_diversity.sh +55 -0
- package/skills/self-review/tests/test_panel_mode.sh +69 -0
- package/skills/self-review/tests/test_reference_adequacy.sh +68 -0
- package/skills/self-review/tests/test_reviewer_team_consistency.sh +138 -0
- package/skills/self-review/tests/test_scope_coherence.sh +46 -0
- package/skills/setup-medsci/SKILL.md +110 -0
- package/skills/setup-medsci/references/setup-checklist.md +51 -0
- package/skills/setup-medsci/skill.yml +30 -0
- package/skills/sync-submission/SKILL.md +382 -0
- package/skills/sync-submission/scripts/author_registry_example.yaml +36 -0
- package/skills/sync-submission/scripts/blind_sweep.py +203 -0
- package/skills/sync-submission/scripts/check_asset_anonymization.py +300 -0
- package/skills/sync-submission/scripts/check_cross_artifact_stale.py +211 -0
- package/skills/sync-submission/scripts/cover_letter_drift_check.py +451 -0
- package/skills/sync-submission/scripts/cross_document_n_check.py +486 -0
- package/skills/sync-submission/scripts/detect_copy_divergence.py +136 -0
- package/skills/sync-submission/scripts/preflight_gate.py +458 -0
- package/skills/sync-submission/scripts/scope_drift_check.py +362 -0
- package/skills/sync-submission/scripts/sync_submission.py +169 -0
- package/skills/sync-submission/skill.yml +43 -0
- package/skills/sync-submission/tests/fixtures/copy_ok.md +5 -0
- package/skills/sync-submission/tests/fixtures/copy_stale.md +5 -0
- package/skills/sync-submission/tests/fixtures/ssot.md +5 -0
- package/skills/sync-submission/tests/test_asset_anonymization.sh +99 -0
- package/skills/sync-submission/tests/test_copy_divergence.sh +44 -0
- package/skills/sync-submission/tests/test_cross_artifact_stale.sh +80 -0
- package/skills/sync-submission/tests/test_cross_document_n.sh +132 -0
- package/skills/sync-submission/tests/test_preflight_gate.sh +112 -0
- package/skills/sync-submission/tests/test_scope_drift.sh +122 -0
- package/skills/sync-submission/tests/test_vN_docx_assertion.sh +51 -0
- package/skills/verify-refs/SKILL.md +177 -0
- package/skills/verify-refs/references/manual_checkpoint_guide.md +100 -0
- package/skills/verify-refs/scripts/verify_cli.sh +62 -0
- package/skills/verify-refs/scripts/verify_refs.py +782 -0
- package/skills/verify-refs/skill.yml +44 -0
- package/skills/verify-refs/tests/fixtures/pagination_placeholder.bib +17 -0
- package/skills/verify-refs/tests/test_pagination_placeholder.sh +42 -0
- package/skills/version-dataset/SKILL.md +143 -0
- package/skills/version-dataset/references/manifest_schema.md +72 -0
- package/skills/version-dataset/scripts/version_dataset.py +242 -0
- package/skills/version-dataset/skill.yml +35 -0
- package/skills/version-dataset/tests/test_version_dataset.sh +52 -0
- package/skills/write-paper/SKILL.md +1148 -0
- package/skills/write-paper/references/exemplar_methods/README.md +38 -0
- package/skills/write-paper/references/exemplar_methods/ai_validation_tripod_claim.md +47 -0
- package/skills/write-paper/references/exemplar_methods/diagnostic_accuracy_stard.md +50 -0
- package/skills/write-paper/references/exemplar_methods/observational_cohort_strobe.md +43 -0
- package/skills/write-paper/references/journal_profiles/AJNR.md +185 -0
- package/skills/write-paper/references/journal_profiles/AJR.md +149 -0
- package/skills/write-paper/references/journal_profiles/Abdominal_Radiology.md +139 -0
- package/skills/write-paper/references/journal_profiles/Academic_Radiology.md +90 -0
- package/skills/write-paper/references/journal_profiles/Annals_of_Internal_Medicine.md +150 -0
- package/skills/write-paper/references/journal_profiles/Artificial_Intelligence_in_Medicine.md +82 -0
- package/skills/write-paper/references/journal_profiles/British_Journal_of_Radiology.md +161 -0
- package/skills/write-paper/references/journal_profiles/CVIR.md +157 -0
- package/skills/write-paper/references/journal_profiles/Chest.md +270 -0
- package/skills/write-paper/references/journal_profiles/Clinical_Radiology.md +160 -0
- package/skills/write-paper/references/journal_profiles/Clinical_and_Molecular_Hepatology.md +147 -0
- package/skills/write-paper/references/journal_profiles/Diabetes_Metabolism_Journal.md +163 -0
- package/skills/write-paper/references/journal_profiles/Diagnostic_and_Interventional_Radiology.md +216 -0
- package/skills/write-paper/references/journal_profiles/Endocrinology_and_Metabolism.md +167 -0
- package/skills/write-paper/references/journal_profiles/European_Journal_of_Preventive_Cardiology.md +192 -0
- package/skills/write-paper/references/journal_profiles/European_Radiology.md +159 -0
- package/skills/write-paper/references/journal_profiles/Hepatology_Communications.md +110 -0
- package/skills/write-paper/references/journal_profiles/Hepatology_International.md +106 -0
- package/skills/write-paper/references/journal_profiles/IEEE_TMI.md +180 -0
- package/skills/write-paper/references/journal_profiles/INSI.md +163 -0
- package/skills/write-paper/references/journal_profiles/Investigative_Radiology.md +86 -0
- package/skills/write-paper/references/journal_profiles/JACC_Advances.md +197 -0
- package/skills/write-paper/references/journal_profiles/JACC_Asia.md +168 -0
- package/skills/write-paper/references/journal_profiles/JACR.md +87 -0
- package/skills/write-paper/references/journal_profiles/JAMA.md +188 -0
- package/skills/write-paper/references/journal_profiles/JAMA_Network_Open.md +170 -0
- package/skills/write-paper/references/journal_profiles/JCSM.md +266 -0
- package/skills/write-paper/references/journal_profiles/JKMS.md +201 -0
- package/skills/write-paper/references/journal_profiles/JMIR.md +88 -0
- package/skills/write-paper/references/journal_profiles/JMIR_Medical_Education.md +86 -0
- package/skills/write-paper/references/journal_profiles/JNIS.md +227 -0
- package/skills/write-paper/references/journal_profiles/JVIR.md +158 -0
- package/skills/write-paper/references/journal_profiles/Journal_of_Clinical_Endocrinology_and_Metabolism.md +191 -0
- package/skills/write-paper/references/journal_profiles/Journal_of_Stroke.md +176 -0
- package/skills/write-paper/references/journal_profiles/KJR.md +185 -0
- package/skills/write-paper/references/journal_profiles/Korean_Circulation_Journal.md +184 -0
- package/skills/write-paper/references/journal_profiles/Korean_Journal_of_Internal_Medicine.md +178 -0
- package/skills/write-paper/references/journal_profiles/Lancet_Gastroenterology_and_Hepatology.md +127 -0
- package/skills/write-paper/references/journal_profiles/Liver_International.md +165 -0
- package/skills/write-paper/references/journal_profiles/Medical_Image_Analysis.md +147 -0
- package/skills/write-paper/references/journal_profiles/NEJM.md +147 -0
- package/skills/write-paper/references/journal_profiles/Nature_Medicine.md +181 -0
- package/skills/write-paper/references/journal_profiles/Neuroradiology.md +151 -0
- package/skills/write-paper/references/journal_profiles/Nutrition_Metabolism_and_Cardiovascular_Diseases.md +184 -0
- package/skills/write-paper/references/journal_profiles/PLOS_Medicine.md +166 -0
- package/skills/write-paper/references/journal_profiles/RYAI.md +124 -0
- package/skills/write-paper/references/journal_profiles/Radiology.md +173 -0
- package/skills/write-paper/references/journal_profiles/Skeletal_Radiology.md +135 -0
- package/skills/write-paper/references/journal_profiles/Stroke.md +210 -0
- package/skills/write-paper/references/journal_profiles/The_BMJ.md +121 -0
- package/skills/write-paper/references/journal_profiles/The_Lancet.md +112 -0
- package/skills/write-paper/references/journal_profiles/The_Lancet_Digital_Health.md +104 -0
- package/skills/write-paper/references/journal_profiles/World_Journal_of_Hepatology.md +106 -0
- package/skills/write-paper/references/journal_profiles/npj_Digital_Medicine.md +93 -0
- package/skills/write-paper/references/paper_types/ai_validation.md +270 -0
- package/skills/write-paper/references/paper_types/animal_study.md +194 -0
- package/skills/write-paper/references/paper_types/case_report.md +237 -0
- package/skills/write-paper/references/paper_types/cross_national.md +328 -0
- package/skills/write-paper/references/paper_types/letter.md +127 -0
- package/skills/write-paper/references/paper_types/meta_analysis.md +181 -0
- package/skills/write-paper/references/paper_types/nhis_cohort.md +297 -0
- package/skills/write-paper/references/paper_types/original_article.md +221 -0
- package/skills/write-paper/references/paper_types/technical_note.md +131 -0
- package/skills/write-paper/references/section_guides/discussion.md +155 -0
- package/skills/write-paper/references/section_guides/introduction.md +108 -0
- package/skills/write-paper/references/section_guides/methods.md +144 -0
- package/skills/write-paper/references/section_guides/results.md +113 -0
- package/skills/write-paper/references/section_guides/step7_1_classical_qc.md +67 -0
- package/skills/write-paper/references/section_guides/step7_4a_audit_recovery.md +74 -0
- package/skills/write-paper/references/section_guides/title_abstract.md +123 -0
- package/skills/write-paper/references/section_templates/methods_statistical.md +147 -0
- package/skills/write-paper/scripts/check_placeholders.py +182 -0
- package/skills/write-paper/skill.yml +48 -0
- package/skills/write-paper/tests/test_placeholders.sh +107 -0
- package/skills/write-protocol/SKILL.md +243 -0
- package/skills/write-protocol/references/ethics_checklist.md +150 -0
- package/skills/write-protocol/references/protocol_template.md +304 -0
- 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
|
+
```
|