medsci-skills 4.7.0 → 4.9.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 (93) hide show
  1. package/README.md +24 -1
  2. package/metadata/distribution_files.json +133 -68
  3. package/metadata/distribution_manifest.json +1 -1
  4. package/package.json +1 -1
  5. package/skills/MAINTENANCE.md +68 -0
  6. package/skills/analyze-stats/SKILL.md +2 -0
  7. package/skills/analyze-stats/scripts/check_generated_code.py +7 -1
  8. package/skills/analyze-stats/scripts/rating_monotonicity.py +132 -0
  9. package/skills/analyze-stats/tests/fixtures/gen_palette.py +22 -0
  10. package/skills/analyze-stats/tests/test_generated_code.sh +12 -0
  11. package/skills/check-reporting/SKILL.md +33 -1
  12. package/skills/check-reporting/references/genai_image_study_object_decision_aid.md +60 -0
  13. package/skills/check-reporting/tests/fixtures/prisma_body.md +7 -0
  14. package/skills/check-reporting/tests/fixtures/prisma_fig_clean.md +10 -0
  15. package/skills/check-reporting/tests/fixtures/prisma_fig_mismatch.md +10 -0
  16. package/skills/check-reporting/tests/test_prisma_figure.sh +50 -0
  17. package/skills/design-ai-benchmarking/SKILL.md +16 -0
  18. package/skills/design-ai-benchmarking/references/anchor_rotate_reader_allocation.md +92 -0
  19. package/skills/design-study/SKILL.md +33 -0
  20. package/skills/find-journal/references/journal_profiles/KJR.md +1 -1
  21. package/skills/manage-project/SKILL.md +1 -1
  22. package/skills/manage-refs/SKILL.md +3 -0
  23. package/skills/manage-refs/citation_styles/README.md +1 -0
  24. package/skills/manage-refs/citation_styles/liver-international.csl +535 -0
  25. package/skills/manage-refs/scripts/check_csl_render.py +85 -22
  26. package/skills/manage-refs/scripts/check_reference_duplication.py +245 -0
  27. package/skills/manage-refs/tests/fixtures/csl_render_sample.bib +19 -0
  28. package/skills/manage-refs/tests/fixtures/refclean_text.md +11 -0
  29. package/skills/manage-refs/tests/fixtures/refdup_text.md +19 -0
  30. package/skills/manage-refs/tests/test_csl_render.sh +60 -0
  31. package/skills/manage-refs/tests/test_reference_duplication.sh +47 -0
  32. package/skills/meta-analysis/SKILL.md +13 -42
  33. package/skills/meta-analysis/references/empirical_lessons.md +53 -0
  34. package/skills/peer-review/SKILL.md +9 -9
  35. package/skills/peer-review/references/domain-probes/ai_overclaiming.md +7 -1
  36. package/skills/peer-review/references/domain-probes/diagnostic_accuracy.md +7 -2
  37. package/skills/peer-review/references/domain-probes/observational_confounding.md +11 -1
  38. package/skills/peer-review/references/domain-probes/sr_ma.md +21 -1
  39. package/skills/peer-review/references/domain-probes/survival_prognostic.md +1 -0
  40. package/skills/revise/SKILL.md +2 -0
  41. package/skills/self-review/SKILL.md +133 -5
  42. package/skills/self-review/references/domain-probes/ai_overclaiming.md +7 -1
  43. package/skills/self-review/references/domain-probes/diagnostic_accuracy.md +7 -2
  44. package/skills/self-review/references/domain-probes/observational_confounding.md +11 -1
  45. package/skills/self-review/references/domain-probes/sr_ma.md +21 -1
  46. package/skills/self-review/references/domain-probes/survival_prognostic.md +1 -0
  47. package/skills/self-review/scripts/check_artifact_coverage.py +91 -2
  48. package/skills/self-review/scripts/check_binning_consistency.py +502 -0
  49. package/skills/self-review/scripts/check_citation_order.py +204 -0
  50. package/skills/self-review/scripts/check_classical_style.py +42 -6
  51. package/skills/self-review/scripts/check_cohort_arithmetic.py +8 -1
  52. package/skills/self-review/scripts/check_null_calibration.py +175 -0
  53. package/skills/self-review/scripts/check_scope_coherence.py +22 -2
  54. package/skills/self-review/scripts/check_supplement_hygiene.py +255 -0
  55. package/skills/self-review/tests/fixtures/binning_clean/primary.R +2 -0
  56. package/skills/self-review/tests/fixtures/binning_clean/sensitivity.R +2 -0
  57. package/skills/self-review/tests/fixtures/binning_drift/primary.R +5 -0
  58. package/skills/self-review/tests/fixtures/binning_drift/sensitivity.R +5 -0
  59. package/skills/self-review/tests/fixtures/citation_order_bad.md +31 -0
  60. package/skills/self-review/tests/fixtures/citation_order_good.md +30 -0
  61. package/skills/self-review/tests/fixtures/cohort_rate_tier_fp.md +4 -0
  62. package/skills/self-review/tests/fixtures/coverage_promised_stat.md +9 -0
  63. package/skills/self-review/tests/fixtures/coverage_promised_stat_ok.md +8 -0
  64. package/skills/self-review/tests/fixtures/derived_clean/canonical.R +6 -0
  65. package/skills/self-review/tests/fixtures/derived_clean/shared.R +6 -0
  66. package/skills/self-review/tests/fixtures/derived_drift/canonical.R +7 -0
  67. package/skills/self-review/tests/fixtures/derived_drift/reanalysis.R +6 -0
  68. package/skills/self-review/tests/fixtures/null_bad.md +11 -0
  69. package/skills/self-review/tests/fixtures/null_clean.md +13 -0
  70. package/skills/self-review/tests/fixtures/scope_disclaimer.md +9 -0
  71. package/skills/self-review/tests/fixtures/style_bad.md +2 -1
  72. package/skills/self-review/tests/fixtures/style_dagger_footnote.md +11 -0
  73. package/skills/self-review/tests/fixtures/supp_clean.md +10 -0
  74. package/skills/self-review/tests/fixtures/supp_dirty.md +14 -0
  75. package/skills/self-review/tests/fixtures/supp_xref_body.md +4 -0
  76. package/skills/self-review/tests/fixtures/supp_xref_supp.md +5 -0
  77. package/skills/self-review/tests/test_artifact_coverage.sh +18 -0
  78. package/skills/self-review/tests/test_binning_consistency.sh +67 -0
  79. package/skills/self-review/tests/test_citation_order.sh +48 -0
  80. package/skills/self-review/tests/test_classical_style.sh +21 -1
  81. package/skills/self-review/tests/test_cohort_arithmetic.sh +13 -0
  82. package/skills/self-review/tests/test_null_calibration.sh +47 -0
  83. package/skills/self-review/tests/test_scope_coherence.sh +13 -0
  84. package/skills/self-review/tests/test_supplement_hygiene.sh +63 -0
  85. package/skills/sync-submission/SKILL.md +5 -2
  86. package/skills/sync-submission/scripts/_yaml_frontmatter.py +35 -0
  87. package/skills/sync-submission/scripts/check_checklist_dump_leak.py +228 -0
  88. package/skills/sync-submission/scripts/check_wordcount_cap.py +4 -12
  89. package/skills/sync-submission/scripts/cover_letter_drift_check.py +4 -18
  90. package/skills/sync-submission/scripts/preflight_gate.py +17 -2
  91. package/skills/sync-submission/tests/test_checklist_dump_leak.sh +89 -0
  92. package/skills/write-paper/references/journal_profiles/KJR.md +18 -0
  93. package/skills/write-paper/references/journal_profiles/Liver_International.md +23 -1
package/README.md CHANGED
@@ -11,6 +11,7 @@
11
11
  [![CI](https://img.shields.io/github/actions/workflow/status/Aperivue/medsci-skills/validate.yml?branch=main&style=flat-square&label=CI)](https://github.com/Aperivue/medsci-skills/actions/workflows/validate.yml)
12
12
  ![Skills](https://img.shields.io/badge/Skills-45-brightgreen?style=flat-square)
13
13
  [![npm](https://img.shields.io/npm/v/medsci-skills?style=flat-square&label=npm&color=cb3837)](https://www.npmjs.com/package/medsci-skills)
14
+ [![Watch the 2-min intro](https://img.shields.io/badge/▶_Watch-2--min_intro-FF0000?style=flat-square&logo=youtube&logoColor=white)](https://youtu.be/MclQ_RIofpE)
14
15
  [![good first issues](https://img.shields.io/github/issues/Aperivue/medsci-skills/good%20first%20issue?style=flat-square&label=good%20first%20issues&color=7057ff)](https://github.com/Aperivue/medsci-skills/contribute)
15
16
 
16
17
  [![Agent Skills](https://img.shields.io/badge/Agent_Skills-standard-blue?style=flat-square)](https://agentskills.io)
@@ -267,6 +268,17 @@ The E2E pipeline (`orchestrate --e2e`) produces everything up to `qc/`. The `sub
267
268
 
268
269
  ## What's New
269
270
 
271
+ **v4.9** — analysis-integrity hardening promoted from real review cycles, plus journal-mechanics additions. Additive and backward-compatible; still 45 skills / 36 guidelines, analysis-integrity detectors **32 → 36**:
272
+
273
+ - **Four new gates** — a **duplicate-bibliography** check (`check_reference_duplication.py`) for the hybrid `[@key]` + hand-typed `## References` build that renders the list twice; a **cross-script binning / composite-indicator** consistency check (`check_binning_consistency.py`, `BINNING_DRIFT` / `DERIVED_DEF_DRIFT`) for a derived categorical or composite indicator defined inconsistently across analysis scripts; a **float citation-order** check (`check_citation_order.py`) for numbered Tables/Figures not first cited in ascending order per series; and an **audit-dump leak** gate (`/sync-submission`) that blocks a `/check-reporting` output mistakenly attached as a submission file.
274
+ - **KJR technical-check conventions + percentage-decimal style**, reader-allocation-under-burden and generative-image-as-study-object reporting (`/design-ai-benchmarking`, `/check-reporting`), and a **Liver International** CSL with that journal's submission mechanics (`/manage-refs`).
275
+
276
+ **v4.8** is the **review-harvest batch** — deterministic detector hardening promoted from real-manuscript review cycles. Additive and backward-compatible; still 45 skills / 36 guidelines, analysis-integrity detectors **30 → 32**:
277
+
278
+ - **Two new gates** — `check_supplement_hygiene.py` lints the rendered supplement / tables / caption files (not just the manuscript) for §-labels, placeholders, build markers, response-letter framing, and unresolved body↔supplement cross-references; `check_null_calibration.py` flags a headline negative/equivalence claim made without a minimum-detectable-effect / power / equivalence statement.
279
+ - **Four detector false-positive fixes** — gates no longer fire on a recommended colorblind-safe palette, author-footnote `§` daggers, a correctly-hedged disclaimer, or a tier-label digit; each with a regression fixture and three newly CI-wired test suites.
280
+ - **Nine reviewer-side domain probes** (SR/MA, observational, diagnostic, AI-overclaiming, survival) plus a `/design-study` design-stage ceiling gate for perceptual/reader-AI studies and a reusable confidence-weighted-rating→AUC monotonicity template.
281
+
270
282
  **v4.7** is the **self-update foundation** — physician-researchers stay current without GitHub, git, or a terminal. Additive and backward-compatible; still 45 skills / 36 guidelines / 30 detectors:
271
283
 
272
284
  - **Transactional, crash-recoverable installer.** Each install runs through a durable journal state machine recovered on the next run (roll back / forward-clean / fail-closed), with per-target SHA-256 inventories — your modified or third-party skills are backed up and never clobbered or auto-deleted.
@@ -349,7 +361,7 @@ Earlier in this series: analysis-integrity guards (confounding completeness, cla
349
361
  | **Battle-tested** | Used on real manuscript submissions by a practicing physician-researcher | Unknown provenance and validation |
350
362
  | **Depth per skill** | 150-600 lines of documentation + bundled reference files (curated journal profile library, checklists, formula sheets, code templates) | Typically thin SKILL.md templates |
351
363
 
352
- **MedSci-Audit** — the verification edge in the first rows above is a named suite of **28 deterministic detectors** (citation & reference integrity, cohort & pool arithmetic, scope/estimand contracts, reporting compliance, and more) that catch fabricated or drifted content before a manuscript reaches a reviewer. See **[`MEDSCI_AUDIT.md`](MEDSCI_AUDIT.md)** for the suite, its six families, and its evaluation evidence.
364
+ **MedSci-Audit** — the verification edge in the first rows above is a named suite of **36 deterministic detectors** (citation & reference integrity, cohort & pool arithmetic, scope/estimand contracts, reporting compliance, and more) that catch fabricated or drifted content before a manuscript reaches a reviewer. See **[`MEDSCI_AUDIT.md`](MEDSCI_AUDIT.md)** for the suite, its six families, and its evaluation evidence.
353
365
 
354
366
  ---
355
367
 
@@ -594,6 +606,17 @@ Projects declare their source-of-truth layout in `SSOT.yaml`, and a `qc/migratio
594
606
  ### Skills Work Together
595
607
  Skills call each other. `check-reporting` invokes `make-figures` for PRISMA diagrams. `write-paper` calls `search-lit` for citation verification. `self-review` delegates reporting compliance to `check-reporting`. `calc-sample-size` output feeds directly into `write-protocol`'s IRB justification section.
596
608
 
609
+ ### Skill boundaries — which to use, and in what order
610
+ The skill set is deliberately *specialized, not consolidated* — each skill owns a distinct artifact or lifecycle step, so the routing stays precise. The boundaries that are easy to confuse:
611
+
612
+ - **Reference pipeline** — `search-lit` (discover candidates) → `lit-sync` (sole writer of `refs.bib`, syncs Zotero/Obsidian) → `manage-refs` (render CSL / inject CWYW / cross-ref QC, sole writer of the rendered DOCX) → `verify-refs` (read-only audit; never edits `refs.bib`). They are one pipeline, not four overlapping tools.
613
+ - **Language passes run in order** — `humanize` (remove AI-writing tells) → `polish-language` (deterministic ESL/house-style consistency: abbreviations, spelling, en-dashes, p-value case) → `academic-aio` (AI-search/GEO visibility). Three sequential passes with non-overlapping jobs.
614
+ - **Manuscript type picks the skill** — `write-paper` (original/IMRAD articles, case reports, MAs) vs `review-paper` (narrative / scoping / systematic literature reviews) vs `revise` (reviewer-response + tracked changes). Different structures and reporting guidelines.
615
+ - **Author vs external reviewer** — `self-review` is your own pre-submission check (anticipated comments); `peer-review` drafts a journal-facing review as an external reviewer. Same domain probes, different user and output.
616
+ - **Project entry** — `intake-project` classifies and scaffolds a *new or messy folder*; `orchestrate` routes a *goal or task* ("help me write a paper"). Start with `intake-project` when you have files but no structure, `orchestrate` when you have a task but no plan.
617
+ - **Study design** — `design-study` covers general validity (analysis unit, leakage, comparator, validation) **and** carries a design-stage ceiling gate for perceptual / observer / reader / visual-Turing-test / image-provenance studies; `design-ai-benchmarking` specializes in AI-vs-human-expert evaluation (rubrics, calibration probes, LLM-as-judge).
618
+ - **Content vs template** — `write-protocol` drafts IRB/ethics scientific content; `fill-protocol` renders that content into an institutional Word template without breaking its formatting.
619
+
597
620
  ### Validation status — available vs CI-gated vs evaluated
598
621
  Be precise about what "validated" means here — the three tiers are different facts:
599
622
  - **Available** — every bundled skill and deterministic detector. The current totals are the single source of truth in [`metadata/catalog_counts.json`](metadata/catalog_counts.json) and [`MEDSCI_AUDIT.md`](MEDSCI_AUDIT.md).
@@ -51,6 +51,11 @@
51
51
  "size": 25500,
52
52
  "sha256": "6a632a88617889a1ac36418822b8af3f2bcab75bfa28169e99ae4fdf0b810365"
53
53
  },
54
+ {
55
+ "path": "skills/MAINTENANCE.md",
56
+ "size": 4061,
57
+ "sha256": "a4eaa6062e7d5879afcdac3bd954fcb783282707eea22b815d5a6f794d5a5217"
58
+ },
54
59
  {
55
60
  "path": "skills/academic-aio/SKILL.md",
56
61
  "size": 31396,
@@ -148,8 +153,8 @@
148
153
  },
149
154
  {
150
155
  "path": "skills/analyze-stats/SKILL.md",
151
- "size": 46340,
152
- "sha256": "427b587784ab62562184299f6fcb9625275c42d9191075635be1f31a3f69def3"
156
+ "size": 47388,
157
+ "sha256": "12121ea6224d8c75d4aa98a6e2ee2947c95cfc17a3902780e7bb8d7ddb0be052"
153
158
  },
154
159
  {
155
160
  "path": "skills/analyze-stats/references/analysis_guides/mediation.md",
@@ -358,8 +363,13 @@
358
363
  },
359
364
  {
360
365
  "path": "skills/analyze-stats/scripts/check_generated_code.py",
361
- "size": 14525,
362
- "sha256": "b9918728e4eac298fdb6adffa2a79faf835b395b65bace69409c190e88c13619"
366
+ "size": 15024,
367
+ "sha256": "b8643d9d9a4b600af428604811135fc27cee6eb2140bdae5e393ed9b3be37fae"
368
+ },
369
+ {
370
+ "path": "skills/analyze-stats/scripts/rating_monotonicity.py",
371
+ "size": 5494,
372
+ "sha256": "b7f8f36c7af060e2dec60f51185ef4cc5a0f2ef20c1d509fb845b36521f420b3"
363
373
  },
364
374
  {
365
375
  "path": "skills/analyze-stats/skill.yml",
@@ -463,8 +473,8 @@
463
473
  },
464
474
  {
465
475
  "path": "skills/check-reporting/SKILL.md",
466
- "size": 32921,
467
- "sha256": "6901d90a56ac4f752988b533310eedb773819241774befc2bbc64bb592d52e9f"
476
+ "size": 35835,
477
+ "sha256": "a11617fb2bcf03b63a788638ad68ab9dac8623281e8b58428706b7c43a02e8c3"
468
478
  },
469
479
  {
470
480
  "path": "skills/check-reporting/references/LICENSES.md",
@@ -661,6 +671,11 @@
661
671
  "size": 4565,
662
672
  "sha256": "f955a0479da6474e43ece05361838f8db95923ec9f7dc56863afbf4cba66174d"
663
673
  },
674
+ {
675
+ "path": "skills/check-reporting/references/genai_image_study_object_decision_aid.md",
676
+ "size": 4287,
677
+ "sha256": "34f79571566ef06eee0fc4c8c646be530806fca658720902d16642faadc8844b"
678
+ },
664
679
  {
665
680
  "path": "skills/check-reporting/references/step4c_registration_timing.md",
666
681
  "size": 4197,
@@ -848,8 +863,13 @@
848
863
  },
849
864
  {
850
865
  "path": "skills/design-ai-benchmarking/SKILL.md",
851
- "size": 10820,
852
- "sha256": "28bc4edc34b28e3d40d176743a1ccaa60b1c559ee1e401ca94c4a14131c10630"
866
+ "size": 12094,
867
+ "sha256": "b8f794a1f6c800d821305a4df8a797bea61cf34a602e0dc0dbea8f2c0c458ca5"
868
+ },
869
+ {
870
+ "path": "skills/design-ai-benchmarking/references/anchor_rotate_reader_allocation.md",
871
+ "size": 4585,
872
+ "sha256": "a763572efd764118e6ee57c950268c175cfeeecca00a43be53412e97c053421d"
853
873
  },
854
874
  {
855
875
  "path": "skills/design-ai-benchmarking/references/benchmark_export_schema.json",
@@ -868,8 +888,8 @@
868
888
  },
869
889
  {
870
890
  "path": "skills/design-study/SKILL.md",
871
- "size": 15849,
872
- "sha256": "41e461909bbf56f0cb810c6d0fe809380b70125911bbea014d9d7b8b397a13e9"
891
+ "size": 18282,
892
+ "sha256": "dfd73871102af6beab3d21f60f650db41ec2e4025d6ee19eae8de61b17851fd4"
873
893
  },
874
894
  {
875
895
  "path": "skills/design-study/skill.yml",
@@ -1193,8 +1213,8 @@
1193
1213
  },
1194
1214
  {
1195
1215
  "path": "skills/find-journal/references/journal_profiles/KJR.md",
1196
- "size": 2553,
1197
- "sha256": "11aea434bb653d304d107133f9af5a74937907b558b22dd28029f7fdba64f31b"
1216
+ "size": 3036,
1217
+ "sha256": "a0814e6d62288389db7528b73a25db870ab91635dc4b946fb0c8bf8af47150a3"
1198
1218
  },
1199
1219
  {
1200
1220
  "path": "skills/find-journal/references/journal_profiles/Korean_Circulation_Journal.md",
@@ -1963,8 +1983,8 @@
1963
1983
  },
1964
1984
  {
1965
1985
  "path": "skills/manage-project/SKILL.md",
1966
- "size": 12313,
1967
- "sha256": "ea1925634e5da4eff202fd34ae874f64b7b76d577ffa0bd49c406a5d84bd4441"
1986
+ "size": 12315,
1987
+ "sha256": "40c3a0098a3729b839e132db3987ad0f3fc5f3eeaf1c5a56dd77673cffdb5dbd"
1968
1988
  },
1969
1989
  {
1970
1990
  "path": "skills/manage-project/references/pre_submission_checklist.md",
@@ -2013,13 +2033,13 @@
2013
2033
  },
2014
2034
  {
2015
2035
  "path": "skills/manage-refs/SKILL.md",
2016
- "size": 17029,
2017
- "sha256": "61441a243ea113e9a5aeba3154ca741db9f1301118051f461b0a3c3de7b61fdf"
2036
+ "size": 18165,
2037
+ "sha256": "49adc82dea2b5d7eb93946b2cd8143d66d50b53169d3ed18f4bd738bfe3af39f"
2018
2038
  },
2019
2039
  {
2020
2040
  "path": "skills/manage-refs/citation_styles/README.md",
2021
- "size": 2001,
2022
- "sha256": "e25f3c5689112527d0eccabcd5dc69a061f56355b3e02c8b71a1d831e04e443d"
2041
+ "size": 2205,
2042
+ "sha256": "d957bbdd13df10884fd54f9eb4efb096a73824c69167f872b0cb9819be031cdf"
2023
2043
  },
2024
2044
  {
2025
2045
  "path": "skills/manage-refs/citation_styles/american-journal-of-roentgenology.csl",
@@ -2056,6 +2076,11 @@
2056
2076
  "size": 5849,
2057
2077
  "sha256": "edde670da20212820d54649dcb96594db835eb55498e88c7de41891dfb370114"
2058
2078
  },
2079
+ {
2080
+ "path": "skills/manage-refs/citation_styles/liver-international.csl",
2081
+ "size": 18264,
2082
+ "sha256": "c7c144ff5df948fc09c9604bf9f8269c6cd427c29bd043da6ead24e75c80971f"
2083
+ },
2059
2084
  {
2060
2085
  "path": "skills/manage-refs/citation_styles/nature.csl",
2061
2086
  "size": 6444,
@@ -2113,8 +2138,13 @@
2113
2138
  },
2114
2139
  {
2115
2140
  "path": "skills/manage-refs/scripts/check_csl_render.py",
2116
- "size": 5151,
2117
- "sha256": "bdaf85f75a2ebfb0224d39b4862ccf31dd914453b540de8f3c1ea6e2a0dccc48"
2141
+ "size": 7718,
2142
+ "sha256": "a1848c33e945024719fa1b7cc996d37555801e011c6280be6644ae4f01642601"
2143
+ },
2144
+ {
2145
+ "path": "skills/manage-refs/scripts/check_reference_duplication.py",
2146
+ "size": 10210,
2147
+ "sha256": "439f02252338e204dadf24dc4de13e38ab3ce7b6ea394e8dee38b8ee1cf92524"
2118
2148
  },
2119
2149
  {
2120
2150
  "path": "skills/manage-refs/scripts/check_xref.py",
@@ -2153,8 +2183,8 @@
2153
2183
  },
2154
2184
  {
2155
2185
  "path": "skills/meta-analysis/SKILL.md",
2156
- "size": 55293,
2157
- "sha256": "d370d5fddffaa5fa26f438a1157d4b96412dbbf7cbe65c9c28cc8474cc736d0b"
2186
+ "size": 49604,
2187
+ "sha256": "4947eae188dc2fcfba68ed991ba126da8315dc79deac0649d2beea558e73025e"
2158
2188
  },
2159
2189
  {
2160
2190
  "path": "skills/meta-analysis/references/LICENSES.md",
@@ -2211,6 +2241,11 @@
2211
2241
  "size": 5538,
2212
2242
  "sha256": "9b2dc03572cb066528e1ef19b0699ec9434ec29cbad8b84f5fbab1492ead5480"
2213
2243
  },
2244
+ {
2245
+ "path": "skills/meta-analysis/references/empirical_lessons.md",
2246
+ "size": 7616,
2247
+ "sha256": "f49ebc21369095d19661d39186d1c41368811fbe689c77762daf60c74cd73ee8"
2248
+ },
2214
2249
  {
2215
2250
  "path": "skills/meta-analysis/references/icmje_coi_guide.md",
2216
2251
  "size": 6043,
@@ -2363,8 +2398,8 @@
2363
2398
  },
2364
2399
  {
2365
2400
  "path": "skills/peer-review/SKILL.md",
2366
- "size": 50226,
2367
- "sha256": "48e0841a8fc2364c54964ae2346c13fb14978c87478ae1ed37964f728e65f02d"
2401
+ "size": 50304,
2402
+ "sha256": "2cabbeb0695e52e6a4aa1f341a0ddeb3cfe088c53e25c9803a2b1b5f3a0b5bd1"
2368
2403
  },
2369
2404
  {
2370
2405
  "path": "skills/peer-review/references/aczel_2021_reviewer2_patterns.md",
@@ -2373,8 +2408,8 @@
2373
2408
  },
2374
2409
  {
2375
2410
  "path": "skills/peer-review/references/domain-probes/ai_overclaiming.md",
2376
- "size": 12790,
2377
- "sha256": "cda5e4c56c37c37e036565f94d05487b8aa2d1c90b2a6a5b2e3113171456b6d7"
2411
+ "size": 14205,
2412
+ "sha256": "565aa362e20ea6ca923510ea393829fb851e0caaae3d732f99144dd48a25b951"
2378
2413
  },
2379
2414
  {
2380
2415
  "path": "skills/peer-review/references/domain-probes/case_report.md",
@@ -2388,8 +2423,8 @@
2388
2423
  },
2389
2424
  {
2390
2425
  "path": "skills/peer-review/references/domain-probes/diagnostic_accuracy.md",
2391
- "size": 7673,
2392
- "sha256": "292a3cefe72e55856084dc2d0ba7cd46ec60d8f52fd488ea57b72534f7ee39f7"
2426
+ "size": 9002,
2427
+ "sha256": "8232e2023d3c4d52e6a2d9003ae335302d6fe78c54d39b81f591c07becaf4df0"
2393
2428
  },
2394
2429
  {
2395
2430
  "path": "skills/peer-review/references/domain-probes/equity_fairness.md",
@@ -2408,8 +2443,8 @@
2408
2443
  },
2409
2444
  {
2410
2445
  "path": "skills/peer-review/references/domain-probes/observational_confounding.md",
2411
- "size": 24897,
2412
- "sha256": "8c21c2b0cde6d46dfdc9757571aeb480e0a692d30aea19d56b06654bbd3ba803"
2446
+ "size": 27378,
2447
+ "sha256": "bbced9817545c65992e7c3430057e32b9f32e092180bc91bd08730f03b2dcf9a"
2413
2448
  },
2414
2449
  {
2415
2450
  "path": "skills/peer-review/references/domain-probes/radiomics.md",
@@ -2423,13 +2458,13 @@
2423
2458
  },
2424
2459
  {
2425
2460
  "path": "skills/peer-review/references/domain-probes/sr_ma.md",
2426
- "size": 13933,
2427
- "sha256": "bcd74a02e89aec5c0436297b93181cd256f7f3a0d676843c214e330fa8d3b036"
2461
+ "size": 17239,
2462
+ "sha256": "486d569f559f16d62b882f7256ccfe7443e3e2b4cc72a407a5cd046162a98b25"
2428
2463
  },
2429
2464
  {
2430
2465
  "path": "skills/peer-review/references/domain-probes/survival_prognostic.md",
2431
- "size": 13073,
2432
- "sha256": "0a5922aa7ca389089de394b3fa569565600384ceabae0bd25bfd50efa901cd13"
2466
+ "size": 13765,
2467
+ "sha256": "af0e0323876424eec8ba07be22fe99b3100356e8e4895b5b79635e9a2d76e98e"
2433
2468
  },
2434
2469
  {
2435
2470
  "path": "skills/peer-review/references/exemplar_reviews/README.md",
@@ -2768,8 +2803,8 @@
2768
2803
  },
2769
2804
  {
2770
2805
  "path": "skills/revise/SKILL.md",
2771
- "size": 27309,
2772
- "sha256": "80d274dbca054955c1f4953e9db4f2bf0a02aaf91a26a54ecedd855546dbaceb"
2806
+ "size": 27775,
2807
+ "sha256": "2da4f80e879c2d3ff31d2af435cb27ecae0ba09f1014b8ebbd799ac2472ff1ea"
2773
2808
  },
2774
2809
  {
2775
2810
  "path": "skills/revise/references/r2r_voice.md",
@@ -2843,13 +2878,13 @@
2843
2878
  },
2844
2879
  {
2845
2880
  "path": "skills/self-review/SKILL.md",
2846
- "size": 84876,
2847
- "sha256": "e4d5cc5d0e75d8d13923cedf5d9260a759077f1ad86d68255f0f9323e8d11616"
2881
+ "size": 93517,
2882
+ "sha256": "92b6e1c0e6cdaa27d5f033ce28e58a210208d619793d221f9ffa944aa1055bba"
2848
2883
  },
2849
2884
  {
2850
2885
  "path": "skills/self-review/references/domain-probes/ai_overclaiming.md",
2851
- "size": 12790,
2852
- "sha256": "cda5e4c56c37c37e036565f94d05487b8aa2d1c90b2a6a5b2e3113171456b6d7"
2886
+ "size": 14205,
2887
+ "sha256": "565aa362e20ea6ca923510ea393829fb851e0caaae3d732f99144dd48a25b951"
2853
2888
  },
2854
2889
  {
2855
2890
  "path": "skills/self-review/references/domain-probes/case_report.md",
@@ -2863,8 +2898,8 @@
2863
2898
  },
2864
2899
  {
2865
2900
  "path": "skills/self-review/references/domain-probes/diagnostic_accuracy.md",
2866
- "size": 7673,
2867
- "sha256": "292a3cefe72e55856084dc2d0ba7cd46ec60d8f52fd488ea57b72534f7ee39f7"
2901
+ "size": 9002,
2902
+ "sha256": "8232e2023d3c4d52e6a2d9003ae335302d6fe78c54d39b81f591c07becaf4df0"
2868
2903
  },
2869
2904
  {
2870
2905
  "path": "skills/self-review/references/domain-probes/equity_fairness.md",
@@ -2883,8 +2918,8 @@
2883
2918
  },
2884
2919
  {
2885
2920
  "path": "skills/self-review/references/domain-probes/observational_confounding.md",
2886
- "size": 24897,
2887
- "sha256": "8c21c2b0cde6d46dfdc9757571aeb480e0a692d30aea19d56b06654bbd3ba803"
2921
+ "size": 27378,
2922
+ "sha256": "bbced9817545c65992e7c3430057e32b9f32e092180bc91bd08730f03b2dcf9a"
2888
2923
  },
2889
2924
  {
2890
2925
  "path": "skills/self-review/references/domain-probes/radiomics.md",
@@ -2898,13 +2933,13 @@
2898
2933
  },
2899
2934
  {
2900
2935
  "path": "skills/self-review/references/domain-probes/sr_ma.md",
2901
- "size": 13933,
2902
- "sha256": "bcd74a02e89aec5c0436297b93181cd256f7f3a0d676843c214e330fa8d3b036"
2936
+ "size": 17239,
2937
+ "sha256": "486d569f559f16d62b882f7256ccfe7443e3e2b4cc72a407a5cd046162a98b25"
2903
2938
  },
2904
2939
  {
2905
2940
  "path": "skills/self-review/references/domain-probes/survival_prognostic.md",
2906
- "size": 13073,
2907
- "sha256": "0a5922aa7ca389089de394b3fa569565600384ceabae0bd25bfd50efa901cd13"
2941
+ "size": 13765,
2942
+ "sha256": "af0e0323876424eec8ba07be22fe99b3100356e8e4895b5b79635e9a2d76e98e"
2908
2943
  },
2909
2944
  {
2910
2945
  "path": "skills/self-review/references/exemplar_findings/README.md",
@@ -2953,8 +2988,18 @@
2953
2988
  },
2954
2989
  {
2955
2990
  "path": "skills/self-review/scripts/check_artifact_coverage.py",
2956
- "size": 12440,
2957
- "sha256": "44a935c657bb597e3596c2e361c8d8ee89c613cb020715f27792cf1844731066"
2991
+ "size": 17113,
2992
+ "sha256": "56096c39ddb0083c04a1254f06bafa6fac9fc8a136c9246f68773f0ba5da96d4"
2993
+ },
2994
+ {
2995
+ "path": "skills/self-review/scripts/check_binning_consistency.py",
2996
+ "size": 19541,
2997
+ "sha256": "e3bf7dd2e0871ce6905abc1d33a26c7afac76a93d184bfe2d431af97d0622f74"
2998
+ },
2999
+ {
3000
+ "path": "skills/self-review/scripts/check_citation_order.py",
3001
+ "size": 8705,
3002
+ "sha256": "38525b4dd3ca8c9d99f090e4d42b65f10baf442f56fc4eac5174fb6ba13d90bb"
2958
3003
  },
2959
3004
  {
2960
3005
  "path": "skills/self-review/scripts/check_claim_artifact.py",
@@ -2963,19 +3008,24 @@
2963
3008
  },
2964
3009
  {
2965
3010
  "path": "skills/self-review/scripts/check_classical_style.py",
2966
- "size": 10067,
2967
- "sha256": "5cf7f9a331a4ebcb6f8523fcb5fd1b872079e3bb6e00bf9821a03d504174fdaa"
3011
+ "size": 12210,
3012
+ "sha256": "c973ee8b776f28515439fb185e1254e08e62c2e1410e260f18a824241a331af0"
2968
3013
  },
2969
3014
  {
2970
3015
  "path": "skills/self-review/scripts/check_cohort_arithmetic.py",
2971
- "size": 23363,
2972
- "sha256": "4ef7bded82091bc6cac8bf35cfa19bc1651acb7e0df2aa8b742bd7a04c8b3991"
3016
+ "size": 23868,
3017
+ "sha256": "55933d25d824bf073c0a8b7abc42d2f160c459a288ab932c50d63cf8c03afd37"
2973
3018
  },
2974
3019
  {
2975
3020
  "path": "skills/self-review/scripts/check_confounding_completeness.py",
2976
3021
  "size": 21506,
2977
3022
  "sha256": "7d3e67074d58a28ffee52ce64b486231f103a3ddcaf6b3b6ee83ba5f89c63bc2"
2978
3023
  },
3024
+ {
3025
+ "path": "skills/self-review/scripts/check_null_calibration.py",
3026
+ "size": 7594,
3027
+ "sha256": "9ddff01722c34efb6ffd757ae762c6ee12f5993bf13b11313c2e20b60b26cab3"
3028
+ },
2979
3029
  {
2980
3030
  "path": "skills/self-review/scripts/check_panel_diversity.py",
2981
3031
  "size": 15324,
@@ -2998,8 +3048,13 @@
2998
3048
  },
2999
3049
  {
3000
3050
  "path": "skills/self-review/scripts/check_scope_coherence.py",
3001
- "size": 9538,
3002
- "sha256": "45915b2736f0356e1b2e827939090e5034a01ba5c310b952dd13ad6f2df45a61"
3051
+ "size": 10818,
3052
+ "sha256": "820dfc264c2a4f62c79c0c7123a3e1a8b59a100b89654617a08ff55deeb25a75"
3053
+ },
3054
+ {
3055
+ "path": "skills/self-review/scripts/check_supplement_hygiene.py",
3056
+ "size": 11088,
3057
+ "sha256": "f89027472cdf0258357c3b0f0b0f3fec09b5ea65cc1373292797b818d1acf444"
3003
3058
  },
3004
3059
  {
3005
3060
  "path": "skills/self-review/skill.yml",
@@ -3023,14 +3078,19 @@
3023
3078
  },
3024
3079
  {
3025
3080
  "path": "skills/sync-submission/SKILL.md",
3026
- "size": 26836,
3027
- "sha256": "7aa91cc5355c3257877e0e9fdb12b60a7315f3865faa225ece32a4cc6a9c2d76"
3081
+ "size": 27787,
3082
+ "sha256": "4da14c76c6c9326d31ee93e9515854291cba2c48692eb85cf5d9f6f4301ce465"
3028
3083
  },
3029
3084
  {
3030
3085
  "path": "skills/sync-submission/references/journal_availability_policy.json",
3031
3086
  "size": 1257,
3032
3087
  "sha256": "6d278675d7c734aa3589165817f5413cc46c44402ea15039e51052ab2f52c0a8"
3033
3088
  },
3089
+ {
3090
+ "path": "skills/sync-submission/scripts/_yaml_frontmatter.py",
3091
+ "size": 1669,
3092
+ "sha256": "028fa8c4f7a4440c72d693a2ba6d4799410de0c565c61bd30d68eb0e7c208c78"
3093
+ },
3034
3094
  {
3035
3095
  "path": "skills/sync-submission/scripts/assemble_supplement.py",
3036
3096
  "size": 8979,
@@ -3051,6 +3111,11 @@
3051
3111
  "size": 13869,
3052
3112
  "sha256": "caba039c6cfbfa09aec681a9840c7e0b5650cccdf9e00ddfd869557b0fec57c8"
3053
3113
  },
3114
+ {
3115
+ "path": "skills/sync-submission/scripts/check_checklist_dump_leak.py",
3116
+ "size": 8745,
3117
+ "sha256": "320765b9e975601fc2d73ce15a65b1419668982630c3b7546d0909158e5a5374"
3118
+ },
3054
3119
  {
3055
3120
  "path": "skills/sync-submission/scripts/check_cross_artifact_stale.py",
3056
3121
  "size": 8286,
@@ -3063,13 +3128,13 @@
3063
3128
  },
3064
3129
  {
3065
3130
  "path": "skills/sync-submission/scripts/check_wordcount_cap.py",
3066
- "size": 10053,
3067
- "sha256": "7d47c194bdde03accbb6fab6347621cb3efdec17131651d7e58b4a69b4f0f0c6"
3131
+ "size": 9788,
3132
+ "sha256": "16fecbceae672e4192a138a0509321ea367f61079ca4ef4d630667b1e64eda58"
3068
3133
  },
3069
3134
  {
3070
3135
  "path": "skills/sync-submission/scripts/cover_letter_drift_check.py",
3071
- "size": 16554,
3072
- "sha256": "3188551ea2557ec7445f668a4d4b64396e94c5d691114b3d5bf52a16ef27cd7b"
3136
+ "size": 16001,
3137
+ "sha256": "347c5b702fbe9375899795791a34e8a60e246253bafb53b15ebb59d51dd45e7d"
3073
3138
  },
3074
3139
  {
3075
3140
  "path": "skills/sync-submission/scripts/cross_document_n_check.py",
@@ -3083,8 +3148,8 @@
3083
3148
  },
3084
3149
  {
3085
3150
  "path": "skills/sync-submission/scripts/preflight_gate.py",
3086
- "size": 20061,
3087
- "sha256": "e3e7a300f258cab373410504c1f48d27a1b75c49a12d7fa5cc0f8ba62ab86c4b"
3151
+ "size": 20954,
3152
+ "sha256": "f4be9edf587ec5ea2b7fb782e4912173b78a4fe2035720e6d0681b3d8f36340f"
3088
3153
  },
3089
3154
  {
3090
3155
  "path": "skills/sync-submission/scripts/scope_drift_check.py",
@@ -3403,8 +3468,8 @@
3403
3468
  },
3404
3469
  {
3405
3470
  "path": "skills/write-paper/references/journal_profiles/KJR.md",
3406
- "size": 10367,
3407
- "sha256": "e74e6454054dc3665c6012b973020222f9d02e469d195a60b2570e850fc23e2c"
3471
+ "size": 12737,
3472
+ "sha256": "ea71f1be90ff7088ba8931c97515f221486ca7ac9c7079fefba25417e7a0e932"
3408
3473
  },
3409
3474
  {
3410
3475
  "path": "skills/write-paper/references/journal_profiles/Korean_Circulation_Journal.md",
@@ -3423,8 +3488,8 @@
3423
3488
  },
3424
3489
  {
3425
3490
  "path": "skills/write-paper/references/journal_profiles/Liver_International.md",
3426
- "size": 9474,
3427
- "sha256": "50b7cc65792c17b406ffa4cb32cfb54963d0972b71e48730d4e92a7172dcbe12"
3491
+ "size": 12174,
3492
+ "sha256": "4a12d53605045b20aabc827e4b803edd73f603b6112ced34ec8acfef965950aa"
3428
3493
  },
3429
3494
  {
3430
3495
  "path": "skills/write-paper/references/journal_profiles/Medical_Image_Analysis.md",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema_version": 1,
3
- "version": "4.7.0",
3
+ "version": "4.9.0",
4
4
  "owned_skills": [
5
5
  "academic-aio",
6
6
  "add-journal",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medsci-skills",
3
- "version": "4.7.0",
3
+ "version": "4.9.0",
4
4
  "description": "MedSci Skills — a medical/scientific research skill suite for AI coding agents (Claude Code, Codex, Cursor, Copilot). The npm package is a terminal-friendly installer shortcut; the canonical distribution remains the GitHub repository and the Claude Code plugin marketplace.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://github.com/Aperivue/medsci-skills#readme",
@@ -0,0 +1,68 @@
1
+ # Skill Script Maintenance — taxonomy & wiring rules
2
+
3
+ Every `.py`/`.sh` under `skills/*/scripts/` and `skills/*/tests/` falls into one of
4
+ four categories. Misclassifying one is how a detector goes "dormant" (counted in the
5
+ catalog but never invoked) or how a regression test gives false coverage (exists but
6
+ never runs in CI). This file is the source of truth for which is which and what each
7
+ category must satisfy.
8
+
9
+ ## 1. Counted analysis-integrity detector
10
+
11
+ A script whose **filename** matches the catalog glob — `check_*.py`, `detect_*.py`,
12
+ `derive_*.py`, or `verify_refs.py` — under `skills/*/scripts/`. The glob is the SSOT:
13
+ `scripts/gen_detectors_catalog_json.py` and `scripts/validate_catalog_consistency.py`
14
+ both count these and they must agree with `metadata/catalog_counts.json`
15
+ (`integrity_detectors`).
16
+
17
+ A counted detector MUST:
18
+ - be registered in `scripts/gen_detectors_catalog_json.py` `FAMILY_BY_ID` (an unmapped id
19
+ fails generation), and bump `metadata/catalog_counts.json` + `MEDSCI_AUDIT.md` when added;
20
+ - be **invoked** from its skill's `SKILL.md` (a named workflow step) — otherwise it is
21
+ dormant (counted but never run on a real manuscript);
22
+ - have a **CI-wired** regression test (a `tests/test_*.sh` step in
23
+ `.github/workflows/validate.yml`) with PII-free synthetic fixtures.
24
+
25
+ > Naming trap: a reusable helper must NOT be named `check_*`/`detect_*` or it inflates the
26
+ > detector count. Prefix helpers with `_` (see category 2).
27
+
28
+ ## 2. Helper / library module
29
+
30
+ Shared logic imported by other scripts in the **same** skill (skills are self-contained —
31
+ no cross-skill imports). Name it with a leading underscore (`_yaml_frontmatter.py`) or a
32
+ plain verb (`fill_journal_abbrev.py`) so the detector glob never counts it. Helpers do not
33
+ need their own SKILL.md step, but if a user runs them directly they should be listed in the
34
+ skill's tool table (e.g. `manage-refs` documents `fill_journal_abbrev.py`).
35
+
36
+ ## 3. Run-once authoring tool
37
+
38
+ A generator a maintainer runs by hand to (re)build a committed asset — NOT invoked at skill
39
+ invocation. These are intentionally not wired into any SKILL.md step. Keep them; document
40
+ their purpose in their own docstring. Current run-once tools:
41
+
42
+ - `skills/make-figures/scripts/build_jacc_template.py` — rebuilds the committed JACC Central
43
+ Illustration PPTX template (`references/visual_abstract_templates/jacc_central_illustration.pptx`).
44
+ - `skills/make-figures/scripts/extract_exemplar_from_pdf.py` — extracts a figure region from a
45
+ PDF page to grow the make-figures Critic-Loop exemplar reference set.
46
+
47
+ ## 4. Test fixture / regression test
48
+
49
+ Lives under `skills/<skill>/tests/`. A `test_*.sh`/`test_*.py` is only real coverage if it
50
+ is wired into `.github/workflows/validate.yml` as a `run:` step. **Adding a test file is not
51
+ enough** — if it is not listed in `validate.yml` it never runs and gives false confidence.
52
+ When you add a detector and its test in the same PR, add the `validate.yml` step in that PR.
53
+
54
+ ## When you touch a skill script — checklist
55
+
56
+ 1. New `check_*`/`detect_*` detector → register in `gen_detectors_catalog_json.py`
57
+ (`FAMILY_BY_ID`) + bump `catalog_counts.json` + `MEDSCI_AUDIT.md` + wire into the skill's
58
+ `SKILL.md` + add a CI-wired test. Then run all three generators in `--check` mode.
59
+ 2. New helper → underscore/plain name (never `check_*`), import only within the same skill.
60
+ 3. New asset/fixture file → re-run `python3 scripts/gen_distribution_manifest.py` (it tracks
61
+ payload files and hashes; tests are excluded from the distributed payload but the manifest
62
+ `--check` still gates on edited payload scripts).
63
+ 4. New/edited test → add its `run:` step to `.github/workflows/validate.yml`.
64
+
65
+ Run the full local CI-mirror before pushing (see the repo `CONTRIBUTING.md` / `validate.yml`
66
+ gates): `validate_skills.sh`, the three `gen_*.py --check`, `validate_catalog_consistency.py`,
67
+ `check_version_consistency.py`, `gen_skill_docs.py --check`, `check_locale_inventory.py`,
68
+ `validate_routing_assets.py --strict`, and the installer tests.
@@ -55,6 +55,8 @@ from `analysis_guides/` to ensure correct methodology and reporting.
55
55
 
56
56
  ### Phase 2: Analysis Plan
57
57
 
58
+ **Precondition (observational studies).** Before proposing an analysis plan for an observational design (cohort, case-control, cross-sectional, registry, or survey), confirm that a literature-grounded variable operationalization exists — a `variable_operationalization.md` from `/define-variables`, or an equivalent codebook-backed definition table. If none exists, **warn** the user and recommend running `/define-variables` first, so exposure / outcome / covariate definitions and cutoffs are citation-backed rather than invented ad hoc from the data dictionary (ad-hoc phenotype/cutoff definitions are a common reviewer-rejection trigger for observational work — see the dictionary-first discipline). This is a WARN, not a hard block: proceed on explicit user confirmation, recording that the operationalization artifact was not available. For stricter projects, treat the missing artifact as a hard stop until `/define-variables` has run. (This mirrors the same precondition already enforced in `/write-protocol` before drafting Methods.)
59
+
58
60
  Based on the data structure and research question, propose an analysis plan:
59
61
 
60
62
  1. **Auto-detect analysis type** from the table below, or accept user specification.
@@ -145,9 +145,15 @@ def check_text_common(src: str, lang: str) -> list[dict]:
145
145
  for m in NUM_LITERAL_BODY.finditer(src):
146
146
  body = m.group(1)
147
147
  # ignore obvious non-data: ranges, single repeated, function-call args with kwargs
148
- nums = NUM_TOKEN.findall(body)
149
148
  if "=" in body: # kwargs like figsize=(8,6) or linspace(0,1,...) — not table data
150
149
  continue
150
+ # A list/tuple of string literals (e.g. a hex-color palette
151
+ # ['#000000','#E69F00',...] — exactly the colorblind-safe WONG palette that
152
+ # make-figures recommends) is NOT hand-typed tabular data. Strip quoted
153
+ # substrings before counting numeric tokens, so digits living inside string
154
+ # literals (the "00" in '#E69F00', RGBA codes, category labels) don't make a
155
+ # string list look table-shaped. Genuine numeric data is unquoted.
156
+ nums = NUM_TOKEN.findall(STR_LITERAL.sub("", body))
151
157
  if len(nums) >= DATA_LITERAL_STANDALONE or (len(nums) >= DATA_LITERAL_MIN and has_read):
152
158
  ln = src[:m.start()].count("\n") + 1
153
159
  claims.append({