medsci-skills 5.26.0 → 5.26.2

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 (42) hide show
  1. package/metadata/distribution_files.json +64 -54
  2. package/metadata/distribution_manifest.json +1 -1
  3. package/package.json +1 -1
  4. package/skills/fulltext-retrieval/SKILL.md +47 -12
  5. package/skills/fulltext-retrieval/fetch_oa.py +182 -36
  6. package/skills/fulltext-retrieval/fetch_oa_report_challenge/expected/projection.json +2 -1
  7. package/skills/fulltext-retrieval/fetch_oa_report_challenge/extracted_text.json +2 -2
  8. package/skills/fulltext-retrieval/skill.yml +6 -4
  9. package/skills/fulltext-retrieval/tests/test_source_identity.py +233 -0
  10. package/skills/lit-sync/SKILL.md +13 -4
  11. package/skills/polish-language/SKILL.md +4 -4
  12. package/skills/polish-language/scripts/lint_challenge/fixture/consistent_uk.md +9 -0
  13. package/skills/polish-language/scripts/lint_challenge/fixture/consistent_us.md +12 -0
  14. package/skills/polish-language/scripts/lint_challenge/problem.md +16 -4
  15. package/skills/polish-language/scripts/lint_challenge/verify.sh +12 -0
  16. package/skills/polish-language/scripts/lint_consistency.py +12 -5
  17. package/skills/polish-language/skill.yml +2 -1
  18. package/skills/polish-language/tests/test_consistency_controls.py +85 -0
  19. package/skills/present-paper/SKILL.md +18 -1
  20. package/skills/present-paper/references/slide_visual_styles/nature_lancet.md +48 -23
  21. package/skills/present-paper/scripts/check_font_portability.py +2 -1
  22. package/skills/present-paper/scripts/check_text_overflow.py +8 -3
  23. package/skills/present-paper/scripts/check_text_overflow_challenge/make_fixtures.py +4 -4
  24. package/skills/present-paper/scripts/check_text_overflow_challenge/verify.sh +3 -2
  25. package/skills/present-paper/skill.yml +3 -0
  26. package/skills/present-paper/templates/build_pptx_nature_lancet.py +87 -43
  27. package/skills/present-paper/tests/test_builder_layout.py +149 -0
  28. package/skills/present-paper/tests/test_overflow_pdf.py +95 -0
  29. package/skills/render-pdf-doc/SKILL.md +27 -4
  30. package/skills/render-pdf-doc/scripts/check_deps.sh +1 -0
  31. package/skills/render-pdf-doc/scripts/render_pdf.sh +28 -14
  32. package/skills/render-pdf-doc/scripts/scan_glyph_coverage.py +66 -22
  33. package/skills/render-pdf-doc/skill.yml +4 -1
  34. package/skills/render-pdf-doc/tests/test_font_faces.py +178 -0
  35. package/skills/render-pdf-doc/tests/test_render_pdf.py +120 -0
  36. package/skills/search-lit/SKILL.md +9 -2
  37. package/skills/self-review/tests/fixtures/binning_drift/sensitivity.R +1 -1
  38. package/skills/self-review/tests/fixtures/citation_order_bad.md +9 -12
  39. package/skills/self-review/tests/test_citation_order.sh +2 -2
  40. package/skills/sync-submission/SKILL.md +5 -5
  41. package/skills/verify-refs/scripts/verify_refs.py +3 -5
  42. package/skills/verify-refs/tests/test_fabricated_author.sh +2 -3
@@ -1823,23 +1823,23 @@
1823
1823
  },
1824
1824
  {
1825
1825
  "path": "skills/fulltext-retrieval/SKILL.md",
1826
- "size": 8248,
1827
- "sha256": "d97c19a64d92f66e3c8a1445d893c0f55364f21dc99404fb6f012a3566556e73"
1826
+ "size": 10954,
1827
+ "sha256": "4d1defdcb710f727c15779fbeb9a10dee6088a1b70b250f6fe2339c87a76c3a1"
1828
1828
  },
1829
1829
  {
1830
1830
  "path": "skills/fulltext-retrieval/fetch_oa.py",
1831
- "size": 24810,
1832
- "sha256": "12bfbf094d338ac461267cea133c0a63a66bc0d2dadd28727921149bc5b72855"
1831
+ "size": 32245,
1832
+ "sha256": "09ca16bec5232d778940e2e3b49681c2e548720a1f20184130c39b23ca23d73e"
1833
1833
  },
1834
1834
  {
1835
1835
  "path": "skills/fulltext-retrieval/fetch_oa_report_challenge/expected/projection.json",
1836
- "size": 522,
1837
- "sha256": "f24bdb507f66932c0429acefc171abf5221bd644cacdeba5cd7b5c07670b04aa"
1836
+ "size": 614,
1837
+ "sha256": "cd983f0ce56d9fd500eeff4f8432bbb66759cc4b56983214d548ea40cf2ecccd"
1838
1838
  },
1839
1839
  {
1840
1840
  "path": "skills/fulltext-retrieval/fetch_oa_report_challenge/extracted_text.json",
1841
- "size": 351,
1842
- "sha256": "9b512bbea3780727e79355dd4b3689be182f086d4afb4184737524449fc44e4d"
1841
+ "size": 407,
1842
+ "sha256": "b55cd1dc0704527ca9c34ff6320e49cfa14a5b1310b50c7a8e7c39f1c2d9d3d2"
1843
1843
  },
1844
1844
  {
1845
1845
  "path": "skills/fulltext-retrieval/fetch_oa_report_challenge/results.json",
@@ -1873,8 +1873,8 @@
1873
1873
  },
1874
1874
  {
1875
1875
  "path": "skills/fulltext-retrieval/skill.yml",
1876
- "size": 2420,
1877
- "sha256": "7a457e5f5fde09f57a8ef9d2207dbaab241e56a9bca59ba577d26351bf225346"
1876
+ "size": 2831,
1877
+ "sha256": "cce683497dcb52905d603d7bab326dfc480d83436350d9435b75f7f67cdb9ed4"
1878
1878
  },
1879
1879
  {
1880
1880
  "path": "skills/generate-codebook/SKILL.md",
@@ -1943,8 +1943,8 @@
1943
1943
  },
1944
1944
  {
1945
1945
  "path": "skills/lit-sync/SKILL.md",
1946
- "size": 22758,
1947
- "sha256": "b0fc43eed00b1813f453614b89d9a29d2573115789c00daacca2f82a65d6350c"
1946
+ "size": 23559,
1947
+ "sha256": "d41481e90c1b4ca804f9686d4dcb066d5a2ba23504ed9e0080581991e45061ae"
1948
1948
  },
1949
1949
  {
1950
1950
  "path": "skills/lit-sync/references/bbt_lookup.md",
@@ -3688,14 +3688,24 @@
3688
3688
  },
3689
3689
  {
3690
3690
  "path": "skills/polish-language/SKILL.md",
3691
- "size": 7649,
3692
- "sha256": "27c9d79d48c6b4b3e5a840e30962c4e731f8486e9dab75c16ac70d6067bc4c76"
3691
+ "size": 7709,
3692
+ "sha256": "db2a3d7705c611185daed6d363d606cbda11b5e041bc84c41a61c5b28dc45058"
3693
3693
  },
3694
3694
  {
3695
3695
  "path": "skills/polish-language/scripts/lint_challenge/expected/report.txt",
3696
3696
  "size": 1032,
3697
3697
  "sha256": "bf7be677cd12d583fd958468a6e5ee7f08493cc5fd01a4f7c27af3770331da66"
3698
3698
  },
3699
+ {
3700
+ "path": "skills/polish-language/scripts/lint_challenge/fixture/consistent_uk.md",
3701
+ "size": 524,
3702
+ "sha256": "1b77ed2c859da126ce1aa6a8557d180e8e845c97271b2b898ca718df10e3de0c"
3703
+ },
3704
+ {
3705
+ "path": "skills/polish-language/scripts/lint_challenge/fixture/consistent_us.md",
3706
+ "size": 763,
3707
+ "sha256": "3bd1ce288b08e27296dd67a5a2ad1261e61e1219344c3e2c59b9070e8f6ccda4"
3708
+ },
3699
3709
  {
3700
3710
  "path": "skills/polish-language/scripts/lint_challenge/fixture/manuscript.md",
3701
3711
  "size": 709,
@@ -3703,18 +3713,18 @@
3703
3713
  },
3704
3714
  {
3705
3715
  "path": "skills/polish-language/scripts/lint_challenge/problem.md",
3706
- "size": 2169,
3707
- "sha256": "69037c9d85cf1a29a77dc77cd61e879b9a6befcec945b808d71468fff4278490"
3716
+ "size": 2949,
3717
+ "sha256": "df7c892a1131d76ee2f7614b465e0d677d09d595492eef2ece4f21bd9ff36583"
3708
3718
  },
3709
3719
  {
3710
3720
  "path": "skills/polish-language/scripts/lint_challenge/verify.sh",
3711
- "size": 615,
3712
- "sha256": "31ddc7fb64ac2f9180cdfa6a6ee15a29844c2e9c0955b83250b2c1b62f9e8fa6"
3721
+ "size": 1132,
3722
+ "sha256": "6b3faa91892bb4651795e4943b04171ef87e6162acce58a65390446e14251560"
3713
3723
  },
3714
3724
  {
3715
3725
  "path": "skills/polish-language/scripts/lint_consistency.py",
3716
- "size": 15665,
3717
- "sha256": "f380439fae1fd41b966862957ca4232467a1d1701dd5a19c35c1864b3df9aea2"
3726
+ "size": 16136,
3727
+ "sha256": "cc892d682ea4ccd648effb1facf8d404503d9c5d89b2cf954acfedd12a967857"
3718
3728
  },
3719
3729
  {
3720
3730
  "path": "skills/polish-language/scripts/lint_figure_locale.py",
@@ -3733,8 +3743,8 @@
3733
3743
  },
3734
3744
  {
3735
3745
  "path": "skills/polish-language/skill.yml",
3736
- "size": 2033,
3737
- "sha256": "1a513a7d532d5a335acd6fa91566a551b5dc17d6ba3021f9d39a52848a7df571"
3746
+ "size": 2081,
3747
+ "sha256": "aff8fcd8108ca1df38de11ce594005dfa94baec8947e14dba9214538e77b1eaa"
3738
3748
  },
3739
3749
  {
3740
3750
  "path": "skills/preprocess-imaging/SKILL.md",
@@ -3828,8 +3838,8 @@
3828
3838
  },
3829
3839
  {
3830
3840
  "path": "skills/present-paper/SKILL.md",
3831
- "size": 53093,
3832
- "sha256": "d94632764cd473f79ccf594bb6ecbd49bc270447a81d1f9cfce3d1d43701bbea"
3841
+ "size": 54313,
3842
+ "sha256": "f57f6bfcfdf4a016defcce34732e264c7ac11258f825e1244c681d0d6a52db5d"
3833
3843
  },
3834
3844
  {
3835
3845
  "path": "skills/present-paper/references/ai_slide_tells.md",
@@ -3898,8 +3908,8 @@
3898
3908
  },
3899
3909
  {
3900
3910
  "path": "skills/present-paper/references/slide_visual_styles/nature_lancet.md",
3901
- "size": 9116,
3902
- "sha256": "fd70cbe0edbc39b05a8c6f53da5637913c15182aeb4878983615a77af20c5846"
3911
+ "size": 10721,
3912
+ "sha256": "7f6bc69354220de042a8074d00e5e015972f232384efda72587208fbacd078e6"
3903
3913
  },
3904
3914
  {
3905
3915
  "path": "skills/present-paper/references/spoken_notes_and_bilingual.md",
@@ -3943,8 +3953,8 @@
3943
3953
  },
3944
3954
  {
3945
3955
  "path": "skills/present-paper/scripts/check_font_portability.py",
3946
- "size": 15788,
3947
- "sha256": "192f7107e47364ebe14e6db287d4e3c91b62d6c24391ac5669532f0461695c98"
3956
+ "size": 15874,
3957
+ "sha256": "182a214f32f4f9c73b7e4717d334cd81e94da77c78bc660a7367d69921451528"
3948
3958
  },
3949
3959
  {
3950
3960
  "path": "skills/present-paper/scripts/check_font_portability_challenge/make_fixtures.py",
@@ -3973,18 +3983,18 @@
3973
3983
  },
3974
3984
  {
3975
3985
  "path": "skills/present-paper/scripts/check_text_overflow.py",
3976
- "size": 11729,
3977
- "sha256": "211a6fd3b73d5d8b107f24648db2b0de5628ae6f52c7331253ec9f7664d8179b"
3986
+ "size": 12150,
3987
+ "sha256": "c0dde521a02b7f3d495a627003430c29eae199cd8fa4e1c5be4f778b32ff6c5b"
3978
3988
  },
3979
3989
  {
3980
3990
  "path": "skills/present-paper/scripts/check_text_overflow_challenge/make_fixtures.py",
3981
- "size": 4169,
3982
- "sha256": "6f9d577e43f10ad6f9d98bfa3d8a02f0cf1bb8a5b7c722c11054363dacf39b67"
3991
+ "size": 4162,
3992
+ "sha256": "473b8a58e8fefc62c1d3cf0f974aeb1b7ca1ddb3bb31abf2aa7ec612bded3fdd"
3983
3993
  },
3984
3994
  {
3985
3995
  "path": "skills/present-paper/scripts/check_text_overflow_challenge/verify.sh",
3986
- "size": 4013,
3987
- "sha256": "77366b614425a859c09942b233a9616b21bd1f33c50fdf20d5ca25a18eba837e"
3996
+ "size": 4126,
3997
+ "sha256": "5467d119389fb9b2787d18b5f67283c804cd22a5b112c3c82ece55f6ed720269"
3988
3998
  },
3989
3999
  {
3990
4000
  "path": "skills/present-paper/scripts/extract_pdf_figures.py",
@@ -4018,13 +4028,13 @@
4018
4028
  },
4019
4029
  {
4020
4030
  "path": "skills/present-paper/skill.yml",
4021
- "size": 3238,
4022
- "sha256": "6d45223886fa651661d13afbe18a8cd80907f11cbe1afadd94656630a83729ba"
4031
+ "size": 3482,
4032
+ "sha256": "28d8a5a32fc4a0c5ab63c7a506911e3c022a1b8c77ecccef350298b1755d0e37"
4023
4033
  },
4024
4034
  {
4025
4035
  "path": "skills/present-paper/templates/build_pptx_nature_lancet.py",
4026
- "size": 30327,
4027
- "sha256": "8a08bb4e981c76aa8b3d262037c7456dc4eab2ef12c809a26297c85be9508f6e"
4036
+ "size": 32525,
4037
+ "sha256": "9e14b3845d961d3bb9ab12bffc9709414ac1b517b08c345a85556868a619afb3"
4028
4038
  },
4029
4039
  {
4030
4040
  "path": "skills/profile-imaging/SKILL.md",
@@ -4153,8 +4163,8 @@
4153
4163
  },
4154
4164
  {
4155
4165
  "path": "skills/render-pdf-doc/SKILL.md",
4156
- "size": 9236,
4157
- "sha256": "97af21fac95af6dcd0e47bc6a547f6413f47d431c74d310174899c36cb86da17"
4166
+ "size": 10667,
4167
+ "sha256": "cb3856e4b0aefb6dd0f038a7c8389620c4b933d381d7ff6f653c1f5246abb16a"
4158
4168
  },
4159
4169
  {
4160
4170
  "path": "skills/render-pdf-doc/references/known_pitfalls.md",
@@ -4168,8 +4178,8 @@
4168
4178
  },
4169
4179
  {
4170
4180
  "path": "skills/render-pdf-doc/scripts/check_deps.sh",
4171
- "size": 2183,
4172
- "sha256": "782efdda541c0a84a8d978bb076d43a1d3a026a00b878205dd6d922a197186f6"
4181
+ "size": 2218,
4182
+ "sha256": "587b5890f82890a95647fb7f8b764f8f1c559c2c2806796387b88cfa90c803a7"
4173
4183
  },
4174
4184
  {
4175
4185
  "path": "skills/render-pdf-doc/scripts/infer_colwidths.py",
@@ -4178,18 +4188,18 @@
4178
4188
  },
4179
4189
  {
4180
4190
  "path": "skills/render-pdf-doc/scripts/render_pdf.sh",
4181
- "size": 3958,
4182
- "sha256": "b5a9ebcbb25b1ec85577c9864f60f4f363e90f88896903cff48f7626f5b6b95a"
4191
+ "size": 4711,
4192
+ "sha256": "0892681945d7599ca5c4dc5411297f8904a8595efe8f7401004c3dac06d68764"
4183
4193
  },
4184
4194
  {
4185
4195
  "path": "skills/render-pdf-doc/scripts/scan_glyph_coverage.py",
4186
- "size": 6602,
4187
- "sha256": "09415f60ef9fd96e4baee36bcd38da36dde604baf0656c436cde9f75fb001a17"
4196
+ "size": 9266,
4197
+ "sha256": "4795edba22e36e1ca28e30588f696628e203a573862e066961648896b7f6699d"
4188
4198
  },
4189
4199
  {
4190
4200
  "path": "skills/render-pdf-doc/skill.yml",
4191
- "size": 3133,
4192
- "sha256": "77fe112e5a013d3169290132f9882fbb05b3ebe9317729960582895509c21568"
4201
+ "size": 3329,
4202
+ "sha256": "3d7f542a2fe9a5d0de2e2e462f4177f68424dfbdc6f34a69758d847a954752cd"
4193
4203
  },
4194
4204
  {
4195
4205
  "path": "skills/render-pdf-doc/templates/anchor-doc.md",
@@ -4328,8 +4338,8 @@
4328
4338
  },
4329
4339
  {
4330
4340
  "path": "skills/search-lit/SKILL.md",
4331
- "size": 24427,
4332
- "sha256": "7b3b355e1cf8089b061e1dd5412cf69338a82b993c2e64bc6afd50708051c84d"
4341
+ "size": 24942,
4342
+ "sha256": "f16110416385b53317c0367da792cce91e1e86c5c1a35cff2afc2224fc5fd24e"
4333
4343
  },
4334
4344
  {
4335
4345
  "path": "skills/search-lit/references/parse_pubmed.py",
@@ -5468,8 +5478,8 @@
5468
5478
  },
5469
5479
  {
5470
5480
  "path": "skills/sync-submission/SKILL.md",
5471
- "size": 40770,
5472
- "sha256": "016b88b1d495a094104d7154724632178751f843623683fb8ebe447735ff5557"
5481
+ "size": 40790,
5482
+ "sha256": "45b228823952b028f0ec8160cd3e457f95b37a0a8fe692a09349a49d1e91054a"
5473
5483
  },
5474
5484
  {
5475
5485
  "path": "skills/sync-submission/references/journal_availability_policy.json",
@@ -5828,8 +5838,8 @@
5828
5838
  },
5829
5839
  {
5830
5840
  "path": "skills/verify-refs/scripts/verify_refs.py",
5831
- "size": 49238,
5832
- "sha256": "5e631278ab1b38960d6ba1865cc360855fb2d600024fb67a8e3a9c5a82d5ba9c"
5841
+ "size": 49027,
5842
+ "sha256": "289a91883045bbc38d8e16f65d3e858a106edbb3413ecf6e2d723f353b733362"
5833
5843
  },
5834
5844
  {
5835
5845
  "path": "skills/verify-refs/skill.yml",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema_version": 1,
3
- "version": "5.26.0",
3
+ "version": "5.26.2",
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": "5.26.0",
3
+ "version": "5.26.2",
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",
@@ -43,7 +43,8 @@ python fetch_oa.py dois.txt -o pdfs/ -e your@email.com --verbose
43
43
  10.1002/mp.12524
44
44
  ```
45
45
 
46
- **TSV / CSV with header** — must contain a `DOI` column; optional `PMID` and `Title` columns:
46
+ **TSV / CSV with header** — must contain a `DOI` column; optional `PMID`, `Title`, and
47
+ `FirstAuthor` columns (first author's surname or full name for corroboration):
47
48
  ```tsv
48
49
  ID Title DOI PMID Year
49
50
  1 Some paper 10.1007/s00330-010-1783-x 20628747 2010
@@ -56,7 +57,9 @@ ID Title DOI PMID Year
56
57
  | 10.1007/s00330-010-1783-x | 20628747 | Some paper |
57
58
  ```
58
59
 
59
- When a PMID is available, the PMC lookup is more reliable (PMID → PMCID conversion). When a `Title` column is present, downloaded PDFs get a best-effort title cross-check (see *Retrieval report* below).
60
+ When a PMID is available, the PMC lookup is more reliable (PMID → PMCID conversion).
61
+ Supply `Title` where available: a DOI-only worklist can download a PDF but cannot
62
+ establish title agreement. `FirstAuthor` is optional additional evidence.
60
63
 
61
64
  ## PMC Download (JS-Challenge Resistant)
62
65
 
@@ -100,22 +103,54 @@ override with `--report PATH`):
100
103
 
101
104
  ```json
102
105
  {
103
- "schema_version": 1,
106
+ "schema_version": 2,
104
107
  "generated_by": "fetch_oa.py",
105
- "counts": {"total": 10, "retrieved": 6, "not_retrieved": 4, "title_mismatch": 1},
108
+ "counts": {"total": 4, "retrieved": 3, "not_retrieved": 1, "title_mismatch": 1,
109
+ "source_identity": {"consistent": 1, "conflict": 1, "unresolved": 1, "unavailable": 1}},
106
110
  "items": [
107
- {"doi": "10.1007/...", "pmid": "20628747", "title": "...",
108
- "status": "oa", "source": "unpaywall", "file": "10.1007_....pdf",
109
- "size_bytes": 482113, "title_match": "match"}
111
+ {"doi": "10.1000/synthetic.example", "pmid": "", "title": "Example title",
112
+ "first_author": "", "status": "oa", "source": "unpaywall",
113
+ "file": "10.1000_synthetic.example.pdf", "size_bytes": 482113,
114
+ "file_sha256": "<SHA-256 of the downloaded file>", "title_match": "match",
115
+ "source_identity": {"status": "consistent", "reason": "title_and_identifier_agree",
116
+ "text_scope": "first_page_front_matter", "title_match": "match",
117
+ "doi_match": "match", "observed_identifiers": ["10.1000/synthetic.example"],
118
+ "first_author_match": "unavailable"}}
110
119
  ]
111
120
  }
112
121
  ```
113
122
 
114
- - `status` ∈ `arxiv | oa | pmc | skip | fail`; `source` names the resolver that succeeded.
115
- - `title_match` ∈ `match | mismatch | unavailable` (tri-state). It is **best-effort**:
116
- it needs a `Title` column **and** `pdftotext` (poppler). When either is missing it is
117
- `unavailable`; a `mismatch` is **flagged** for review and **never** auto-rejects a PDF
118
- (guards against a publisher serving a wrong/redirect PDF that still passes the `%PDF-` check).
123
+ The example abbreviates `items`. Legacy `status` (`arxiv | oa | pmc | skip | fail`),
124
+ `source`, and `counts.retrieved` retain their resolver-result meaning, including existing
125
+ files (`skip`). **They do not count identity-verified papers.** Report schema 2 adds the
126
+ file hash and separate identity evidence; no PDF is automatically deleted or rejected.
127
+
128
+ | `source_identity.status` | Meaning / action |
129
+ |---|---|
130
+ | `consistent` | Complete normalized title and a compatible DOI/arXiv identifier occur in the bounded first-page front matter; an optional supplied author must also match. Evidence agrees, but this is not independent source verification or claim validation. |
131
+ | `conflict` | Both the title and observed identifier differ. Inspect the PDF and requested record. |
132
+ | `unresolved` | Evidence is incomplete or ambiguous: title-only, DOI-only, missing author, multiple identifiers, or a matching title with another DOI/version. Inspect before using as evidence. |
133
+ | `unavailable` | No usable extracted text, Poppler unavailable, no output PDF, or the PDF changed during assessment. No current identity assessment was possible. |
134
+
135
+ `title_match` keeps its tri-state shape. A `match` now requires the complete normalized
136
+ title on up to six consecutive front-matter lines. Case, punctuation and line wrapping
137
+ are normalized. Scattered matching words cannot establish a match; partial overlap is
138
+ `unavailable`, and low overlap is an advisory `mismatch`.
139
+
140
+ Evidence is limited to the first page, before a recognized abstract/body/reference
141
+ heading, at most 40 lines / 4,000 characters. Thus a title cited in the body or references
142
+ does not establish a title match. These are conservative layout heuristics: cover sheets,
143
+ unrecognized headings, short or changed titles, unusual reading order and DOI footers
144
+ outside that area can remain unresolved. PDF metadata and the filename alone are not
145
+ identity evidence. The CLI compares hashes before extraction and when reporting;
146
+ changed files cannot inherit the previous text's assessment. Explicit arXiv versions
147
+ must agree; preprint/published-version DOI
148
+ differences require review rather than automatic rejection.
149
+
150
+ Downstream reports must preserve `source_identity` and `file_sha256`, keep unresolved
151
+ items visible, and check the hash still identifies the file being used. Older reports
152
+ without identity evidence remain **unassessed**; do not infer identity from `retrieved`
153
+ or `title_match=match`. Full-text conversion does not resolve an identity warning.
119
154
 
120
155
  ## Attach PDFs into Zotero ("Find Available PDF")
121
156