linkml-reference-validator 0.2.1rc2__tar.gz → 0.2.1rc3__tar.gz
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.
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/PKG-INFO +1 -1
- linkml_reference_validator-0.2.1rc3/docs/assets/zotero-find-full-text.png +0 -0
- linkml_reference_validator-0.2.1rc3/docs/how-to/export-cache-to-zotero.md +114 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/fetch-full-text-and-pdfs.md +102 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/reference/cli.md +63 -0
- linkml_reference_validator-0.2.1rc3/docs/superpowers/plans/2026-08-05-private-library-full-text.md +190 -0
- linkml_reference_validator-0.2.1rc3/docs/superpowers/specs/2026-08-05-private-library-full-text-design.md +309 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/mkdocs.yml +1 -0
- linkml_reference_validator-0.2.1rc3/src/linkml_reference_validator/cli/cache.py +373 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/cli/lookup.py +3 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/acquire.py +80 -1
- linkml_reference_validator-0.2.1rc3/src/linkml_reference_validator/etl/csl_export.py +73 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/__init__.py +2 -0
- linkml_reference_validator-0.2.1rc3/src/linkml_reference_validator/etl/fulltext/zotero.py +252 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/identifiers.py +19 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/reference_fetcher.py +192 -46
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/pmid.py +109 -27
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/models.py +45 -0
- linkml_reference_validator-0.2.1rc3/tests/test_acquire.py +224 -0
- linkml_reference_validator-0.2.1rc3/tests/test_cli_cache_enrich.py +227 -0
- linkml_reference_validator-0.2.1rc3/tests/test_cli_cache_export.py +246 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_models.py +13 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_reference_fetcher.py +215 -1
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_sources.py +149 -0
- linkml_reference_validator-0.2.1rc3/tests/test_zotero_provider.py +277 -0
- linkml_reference_validator-0.2.1rc2/src/linkml_reference_validator/cli/cache.py +0 -143
- linkml_reference_validator-0.2.1rc2/tests/test_acquire.py +0 -116
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.claude/.mcp.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.claude/settings.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.copier-answers.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.devcontainer/devcontainer.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.devcontainer/post_create.sh +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.editorconfig +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/actions/claude-code-action/action.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/actions/claude-issue-summarize-action/action.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/actions/claude-issue-triage-action/action.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/ai-controllers.json +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/copilot-instructions.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/copilot-setup-steps.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/dependabot.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/claude-code-review.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/claude-issue-summarize.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/claude-issue-triage.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/claude-ontology-review.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/claude.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/deploy-docs.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/dragon-ai.yml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/main.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.github/workflows/pypi-publish.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.gitignore +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.goosehints +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.pre-commit-config.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/.yamllint.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/AGENTS.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/BUG_GEO_ACCESSION_TO_UID.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/BUG_ZENODO_DOI_AND_URL_HANDLING.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/CLAUDE.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/CLI-ISSUES.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/CODE_OF_CONDUCT.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/CONTRIBUTING.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/FEATURE_REQUEST_REPAIR.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/LICENSE +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/REVIEW2.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/REVIEW3.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/ai.just +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/copilot-instructions.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/about.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/concepts/content-types.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/concepts/editorial-conventions.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/concepts/how-it-works.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/elements/.gitkeep +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/add-reference-source.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/repair-validation-errors.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/skip-unsupported-references.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/use-local-files-and-urls.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/validate-clinical-trials.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/validate-dois.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/validate-entrez.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/validate-obo-files.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/validate-titles.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/how-to/validate-urls.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/index.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/notebooks/01_getting_started.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/notebooks/02_advanced_usage.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/notebooks/03_python_api.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/notebooks/04_obo_validation.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/notebooks/05_geo_validation.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/quickstart.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/setup-guide.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/superpowers/plans/2026-06-12-modular-pdf-fulltext-fetching.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/superpowers/specs/2026-06-12-modular-pdf-fulltext-fetching-design.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/templates-linkml/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/todo.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/troubleshooting.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/tutorials/complete-workflow.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/examples/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/justfile +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/mypy.ini +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/notebooks/01_getting_started.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/notebooks/02_advanced_usage.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/notebooks/03_python_api.ipynb +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/notebooks/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/project/README.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/project.justfile +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/pyproject.toml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/pytest.ini +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/_version.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/cli/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/cli/repair.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/cli/shared.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/cli/validate.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/extract/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/extract/base.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/extract/html.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/extract/pdf.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/extract/xml.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/base.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/epmc_preprint.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/json_api.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/loader.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/openalex.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/pmc.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/fulltext/unpaywall.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/base.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/clinicaltrials.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/doi.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/entrez.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/file.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/json_api.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/loader.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/ppr.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/url.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/sources/utils.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/etl/text_extractor.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/field_detection.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/plugins/REVIEW.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/plugins/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/plugins/reference_validation_plugin.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/validation/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/validation/fuzzy_text_utils.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/validation/repairer.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/src/linkml_reference_validator/validation/supporting_text_validator.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/__init__.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/conftest.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/data/test_data_deep_nesting_invalid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/data/test_data_deep_nesting_valid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/data/test_data_invalid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/data/test_data_valid.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/data/test_schema.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/data/test_schema_deep_nesting.yaml +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/CLINICALTRIALS_NCT00000001.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/GEO_GSE12345.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMC_TEST001.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMC_TEST001.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMC_TEST002.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMC_TEST002.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMID_TEST001.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMID_TEST001.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMID_TEST002.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMID_TEST002.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMID_TEST003.md +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/PMID_TEST003.txt +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/fixtures/sample.obo +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_cli.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_cli_lookup.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_cli_repair.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_clinicaltrials_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_deep_nesting.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_doi_preprint.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_e2e_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_epmc_preprint_provider.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_extractors.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_field_detection.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_fulltext_loader.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_fulltext_providers.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_fuzzy_suggestions.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_geo_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_identifiers.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_json_api_source.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_optional_linkml_dependency.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_plugin_integration.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_pmc_fulltext.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_ppr_source.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_real_validation.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_repair.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_source_utils.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_supporting_text_validator.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_text_extractor.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_title_validation.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_unknown_slot_traversal.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/tests/test_validation_config.py +0 -0
- {linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/uv.lock +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Export a Reference Cache to Zotero
|
|
2
|
+
|
|
3
|
+
This workflow turns a checked-in public reference cache into a Zotero collection,
|
|
4
|
+
asks Zotero to find available PDFs, and then inventories the resulting attachments
|
|
5
|
+
without putting closed manuscripts into the project repository.
|
|
6
|
+
|
|
7
|
+
The three stores remain separate:
|
|
8
|
+
|
|
9
|
+
| Store | Purpose | Safe to commit? |
|
|
10
|
+
|---|---|---:|
|
|
11
|
+
| Project `references_cache` | Reproducible public validation evidence | Yes |
|
|
12
|
+
| Zotero library | User-managed references and PDF attachments | No |
|
|
13
|
+
| Private research cache | Extracted user-library text for agent context | No |
|
|
14
|
+
|
|
15
|
+
Normal validation reads only the first store.
|
|
16
|
+
|
|
17
|
+
## 1. Export metadata from the public cache
|
|
18
|
+
|
|
19
|
+
Run the exporter from the `linkml-reference-validator` checkout. For dismech:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv run linkml-reference-validator cache export \
|
|
23
|
+
--cache-dir /Users/cjm/repos/dismech/references_cache \
|
|
24
|
+
--needs-full-text \
|
|
25
|
+
--output /Users/cjm/Downloads/dismech-zotero.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`--needs-full-text` is the default. It excludes cache entries that already have
|
|
29
|
+
full text, excludes non-publication identifiers, and deduplicates by normalized
|
|
30
|
+
DOI and then PMID. The CSL JSON output uses an explicit metadata allowlist:
|
|
31
|
+
|
|
32
|
+
- title and authors;
|
|
33
|
+
- journal and year;
|
|
34
|
+
- DOI; or
|
|
35
|
+
- PMID and its public PubMed URL.
|
|
36
|
+
|
|
37
|
+
It never contains cached article text, excerpts, provenance, PDFs, local paths,
|
|
38
|
+
or private-cache data. The command refuses to replace an existing output file;
|
|
39
|
+
use `--force` only after checking the destination. Use `--all` if you explicitly
|
|
40
|
+
want eligible references that already contain full text.
|
|
41
|
+
|
|
42
|
+
## 2. Import the file into Zotero
|
|
43
|
+
|
|
44
|
+
In Zotero:
|
|
45
|
+
|
|
46
|
+
1. Choose **File → Import**.
|
|
47
|
+
2. Choose **A file**.
|
|
48
|
+
3. Select `dismech-zotero.json`.
|
|
49
|
+
4. Keep the imported records in a project-specific collection such as
|
|
50
|
+
**dismech**.
|
|
51
|
+
|
|
52
|
+
CSL JSON is a standard format supported by Zotero. Importing the file adds only
|
|
53
|
+
bibliographic records; it does not copy anything from the validator's caches.
|
|
54
|
+
|
|
55
|
+
## 3. Ask Zotero to find PDFs
|
|
56
|
+
|
|
57
|
+
Select one or more top-level journal articles in the center item list,
|
|
58
|
+
right-click the selection, and choose **Find Full Text**. It is a built-in Zotero
|
|
59
|
+
command, not a plugin.
|
|
60
|
+
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
The command appears for an eligible parent item that has a DOI and does not
|
|
64
|
+
already have a file attachment. It may also be unavailable in a group library
|
|
65
|
+
where files cannot be added. If it is absent, first test a single article in
|
|
66
|
+
your personal library and confirm that its DOI field is populated.
|
|
67
|
+
|
|
68
|
+
For a large import, start with a modest batch rather than all records at once.
|
|
69
|
+
Publishers can temporarily rate-limit repeated requests, and a later retry may
|
|
70
|
+
find additional files. Zotero reports **Full Text PDF** or **No file found** for
|
|
71
|
+
each attempted item.
|
|
72
|
+
|
|
73
|
+
## 4. Inventory the enriched Zotero library
|
|
74
|
+
|
|
75
|
+
Once Zotero finishes, scan the project cache again:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv run linkml-reference-validator cache enrich \
|
|
79
|
+
--provider zotero \
|
|
80
|
+
--cache-dir /Users/cjm/repos/dismech/references_cache \
|
|
81
|
+
--dry-run
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
This read-only scan matches exact DOI, PMID, or PMCID identifiers and reports
|
|
85
|
+
which cached references now have usable Zotero text or PDF attachments. It does
|
|
86
|
+
not invoke **Find Full Text** and does not modify Zotero.
|
|
87
|
+
|
|
88
|
+
After reviewing the matches, materialize them into the separate private research
|
|
89
|
+
cache:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
uv run linkml-reference-validator cache enrich \
|
|
93
|
+
--provider zotero \
|
|
94
|
+
--cache-dir /Users/cjm/repos/dismech/references_cache \
|
|
95
|
+
--apply
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Apply mode leaves `references_cache` unchanged. Private content goes to
|
|
99
|
+
`~/.cache/linkml-reference-validator/private` by default with owner-only
|
|
100
|
+
permissions. Agents may inspect it for context, but validation cannot use it as
|
|
101
|
+
evidence.
|
|
102
|
+
|
|
103
|
+
## 5. Validate reproducibly
|
|
104
|
+
|
|
105
|
+
Run validation normally. Results remain reproducible because the validator
|
|
106
|
+
reads the public project cache and accepts only public full-text provider results.
|
|
107
|
+
Neither the contents of Zotero nor the machine-specific private cache affect
|
|
108
|
+
validation.
|
|
109
|
+
|
|
110
|
+
## See also
|
|
111
|
+
|
|
112
|
+
- [Fetching Full Text and PDFs](fetch-full-text-and-pdfs.md)
|
|
113
|
+
- [Zotero: importing standardized formats](https://www.zotero.org/support/kb/importing_standardized_formats)
|
|
114
|
+
- [Zotero: adding files to a library](https://www.zotero.org/support/attaching_files)
|
|
@@ -46,9 +46,11 @@ your config YAML or on the `ReferenceValidationConfig` object):
|
|
|
46
46
|
|-----|---------|-------------|
|
|
47
47
|
| `fetch_full_text` | `true` | Attempt to obtain full text via the provider chain when a metadata source does not already return full text. |
|
|
48
48
|
| `full_text_providers` | `[pmc, epmc_preprint, unpaywall, openalex]` | Ordered list of provider names to try until one yields usable full text. |
|
|
49
|
+
| `private_cache_dir` | `~/.cache/linkml-reference-validator/private` | Separate research cache for closed/user-library full text; never read by validation. |
|
|
49
50
|
| `pdf_backend` | `pypdf` | Name of the PDF text-extraction backend. |
|
|
50
51
|
| `download_pdfs` | `true` | If true, persist downloaded PDFs to the files cache directory. |
|
|
51
52
|
| `full_text_providers_file` | `null` | Optional path to a YAML file defining custom full-text providers. |
|
|
53
|
+
| `zotero_base_url` | `http://localhost:23119/api/users/0` | Read-only Zotero local API library used by the opt-in `zotero` provider. |
|
|
52
54
|
|
|
53
55
|
Two existing keys are also reused by the full-text machinery:
|
|
54
56
|
|
|
@@ -71,6 +73,106 @@ pdf_backend: pypdf
|
|
|
71
73
|
download_pdfs: true
|
|
72
74
|
```
|
|
73
75
|
|
|
76
|
+
## Private manuscripts in Zotero
|
|
77
|
+
|
|
78
|
+
The opt-in **`zotero`** provider can find non-open manuscripts that are already
|
|
79
|
+
in your personal Zotero library. It matches exact DOI, PMID, or PMCID identifiers;
|
|
80
|
+
it does not automatically accept fuzzy title matches.
|
|
81
|
+
|
|
82
|
+
Zotero must be running, and its local API must be enabled in Zotero's advanced
|
|
83
|
+
settings. Inventory the reference cache before changing it:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
linkml-reference-validator cache enrich \
|
|
87
|
+
--provider zotero \
|
|
88
|
+
--cache-dir references_cache \
|
|
89
|
+
--dry-run
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The report distinguishes `found`, `not_found`, `already_full_text`, and `error`.
|
|
93
|
+
Dry-run is the default and never changes cache files. After reviewing exact
|
|
94
|
+
matches, apply usable text with:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
linkml-reference-validator cache enrich \
|
|
98
|
+
--provider zotero \
|
|
99
|
+
--cache-dir references_cache \
|
|
100
|
+
--apply
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Apply mode does **not** modify `references_cache`. It writes the enriched entry
|
|
104
|
+
to a separate research cache at `~/.cache/linkml-reference-validator/private`
|
|
105
|
+
by default. Agents may inspect that cache for background context, but ordinary
|
|
106
|
+
validation never reads it and never cites it as evidence. Validation therefore
|
|
107
|
+
has the same inputs locally, in CI, and on another contributor's machine.
|
|
108
|
+
|
|
109
|
+
To keep the research cache in a private repository or another secured location:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
linkml-reference-validator cache enrich \
|
|
113
|
+
--provider zotero \
|
|
114
|
+
--cache-dir references_cache \
|
|
115
|
+
--private-cache-dir /path/to/private-reference-cache \
|
|
116
|
+
--apply
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The same location can be configured for all commands:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
cache_dir: references_cache
|
|
123
|
+
private_cache_dir: /path/to/private-reference-cache
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Zotero-indexed text is preferred. If Zotero has not indexed an attachment, the
|
|
127
|
+
provider downloads it from Zotero's local PDF endpoint and sends it through the
|
|
128
|
+
normal PDF extractor. The source attachment key and `user_library` access type
|
|
129
|
+
are persisted, but the ephemeral localhost URL is not.
|
|
130
|
+
|
|
131
|
+
!!! warning "Keep research caches private"
|
|
132
|
+
|
|
133
|
+
Private cache entries contain extracted manuscript text and may contain a
|
|
134
|
+
copied PDF. Do not place this cache in a public repository or share it
|
|
135
|
+
unless you have permission to redistribute that content.
|
|
136
|
+
|
|
137
|
+
Do not add `zotero` to `full_text_providers`. Even if it is configured there,
|
|
138
|
+
ordinary validation rejects its `user_library` result and continues to public
|
|
139
|
+
providers. Use `cache enrich` when you want to search Zotero.
|
|
140
|
+
|
|
141
|
+
Support for reproducible validation backed by private manuscripts is a future,
|
|
142
|
+
separate feature. The proposed design is a trusted offline job that emits a
|
|
143
|
+
minimal signed excerpt attestation into the public cache. The validator would
|
|
144
|
+
verify the signature using a checked-in public key; neither agents nor CI would
|
|
145
|
+
have the signing key or permission to generate those files directly.
|
|
146
|
+
|
|
147
|
+
## Export a cache to a Zotero collection
|
|
148
|
+
|
|
149
|
+
Export references that still need full text as metadata-only CSL JSON:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
linkml-reference-validator cache export \
|
|
153
|
+
--cache-dir references_cache \
|
|
154
|
+
--format csl-json \
|
|
155
|
+
--needs-full-text \
|
|
156
|
+
--output project-zotero.json
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The default `--needs-full-text` mode excludes cache entries that already contain
|
|
160
|
+
full text. It also excludes non-publication identifiers, deduplicates by
|
|
161
|
+
normalized DOI and then PMID, and exports only an explicit metadata allowlist:
|
|
162
|
+
title, authors, journal, year, DOI, PMID, and PubMed URL. Cached article text,
|
|
163
|
+
excerpts, provenance, PDFs, and local paths are never exported. Use `--all` only
|
|
164
|
+
when you deliberately want eligible records that already have full text.
|
|
165
|
+
|
|
166
|
+
The exporter refuses to replace an existing output file unless `--force` is
|
|
167
|
+
given. Review the reported counts, then in Zotero choose **File → Import → A
|
|
168
|
+
file**, select the JSON file, and place the imported items in a project-specific
|
|
169
|
+
collection. Zotero supports CSL JSON as a standard import format. After import,
|
|
170
|
+
select the collection and run **Find Full Text**, then rerun `cache enrich`.
|
|
171
|
+
|
|
172
|
+
See [Zotero's standardized-format import instructions](https://www.zotero.org/support/kb/importing_standardized_formats).
|
|
173
|
+
For the complete workflow with screenshots, see
|
|
174
|
+
[Export a Reference Cache to Zotero](export-cache-to-zotero.md).
|
|
175
|
+
|
|
74
176
|
## Preprints
|
|
75
177
|
|
|
76
178
|
Preprints are first-class references. They are increasingly cited for early
|
{linkml_reference_validator-0.2.1rc2 → linkml_reference_validator-0.2.1rc3}/docs/reference/cli.md
RENAMED
|
@@ -761,6 +761,69 @@ linkml-reference-validator cache lookup PMID:16888623 --content
|
|
|
761
761
|
linkml-reference-validator cache lookup PMID:16888623 --no-cache
|
|
762
762
|
```
|
|
763
763
|
|
|
764
|
+
## cache export
|
|
765
|
+
|
|
766
|
+
Export public bibliographic metadata to CSL JSON for Zotero import.
|
|
767
|
+
|
|
768
|
+
```bash
|
|
769
|
+
linkml-reference-validator cache export --output project-zotero.json [OPTIONS]
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
**Options:**
|
|
773
|
+
|
|
774
|
+
- `--output PATH, -o PATH` - Required destination file
|
|
775
|
+
- `--format TEXT` - Export format (default and currently supported: `csl-json`)
|
|
776
|
+
- `--needs-full-text` - Export only publication records needing full text (default)
|
|
777
|
+
- `--all` - Include eligible records that already contain full text
|
|
778
|
+
- `--cache-dir PATH, -c PATH` - Public reference cache directory
|
|
779
|
+
- `--force, -f` - Replace an existing output file
|
|
780
|
+
- `--config PATH` - Validation configuration file
|
|
781
|
+
- `--verbose, -v` - Enable detailed logging
|
|
782
|
+
|
|
783
|
+
```bash
|
|
784
|
+
linkml-reference-validator cache export \
|
|
785
|
+
--cache-dir references_cache \
|
|
786
|
+
--needs-full-text \
|
|
787
|
+
--output project-zotero.json
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
The output is a DOI/PMID-deduplicated metadata allowlist. It never includes
|
|
791
|
+
cached article content, excerpts, PDFs, local paths, or private-cache data.
|
|
792
|
+
|
|
793
|
+
---
|
|
794
|
+
|
|
795
|
+
## cache enrich
|
|
796
|
+
|
|
797
|
+
Inventory or enrich existing abstract-only cache entries through one full-text
|
|
798
|
+
provider. This is primarily intended for opt-in private-library providers such
|
|
799
|
+
as Zotero.
|
|
800
|
+
|
|
801
|
+
```bash
|
|
802
|
+
linkml-reference-validator cache enrich [OPTIONS]
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
**Options:**
|
|
806
|
+
|
|
807
|
+
- `--provider TEXT` - Registered provider name (default: `zotero`)
|
|
808
|
+
- `--cache-dir PATH, -c PATH` - Reference cache directory
|
|
809
|
+
- `--private-cache-dir PATH` - Separate private research-cache destination (default: `~/.cache/linkml-reference-validator/private`)
|
|
810
|
+
- `--dry-run` - Report matches without changing files (default)
|
|
811
|
+
- `--apply` - Materialize usable matches into the private research cache
|
|
812
|
+
- `--config PATH` - Validation configuration file
|
|
813
|
+
- `--verbose, -v` - Enable detailed logging
|
|
814
|
+
|
|
815
|
+
```bash
|
|
816
|
+
# Safe inventory
|
|
817
|
+
linkml-reference-validator cache enrich --provider zotero --dry-run
|
|
818
|
+
|
|
819
|
+
# Apply reviewed exact matches
|
|
820
|
+
linkml-reference-validator cache enrich --provider zotero --apply
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
The public source cache is never modified by this command, and validation never
|
|
824
|
+
reads the private destination. Private-library content may be copyrighted; keep
|
|
825
|
+
the research cache private.
|
|
826
|
+
|
|
764
827
|
---
|
|
765
828
|
|
|
766
829
|
## Reference ID Formats
|
linkml_reference_validator-0.2.1rc3/docs/superpowers/plans/2026-08-05-private-library-full-text.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Private Library Full-Text Integration — Implementation Plan
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-08-05
|
|
4
|
+
**Design:** [Private Library Full-Text Integration](../specs/2026-08-05-private-library-full-text-design.md)
|
|
5
|
+
|
|
6
|
+
All implementation tasks follow test-driven development: add a failing test,
|
|
7
|
+
implement the smallest production change, then run the focused test and the full
|
|
8
|
+
`just test` suite. Network tests use realistic recorded/constructed API responses;
|
|
9
|
+
live tests remain opt-in.
|
|
10
|
+
|
|
11
|
+
## Phase 1: Zotero local API minimum viable workflow
|
|
12
|
+
|
|
13
|
+
### 1. Generalize full-text locations
|
|
14
|
+
|
|
15
|
+
Add tests for materializing a local PDF path, rejecting a path over the size cap,
|
|
16
|
+
rejecting a non-PDF file with a `.pdf` suffix, and passing ephemeral request
|
|
17
|
+
headers without persisting them.
|
|
18
|
+
|
|
19
|
+
Then:
|
|
20
|
+
|
|
21
|
+
- add `local_path`, `headers`, `access_type`, and `source_item_id` to
|
|
22
|
+
`FullTextLocation`;
|
|
23
|
+
- teach `ReferenceFetcher._materialize()` to read a local file under the same size
|
|
24
|
+
and format-sniffing rules as HTTP content;
|
|
25
|
+
- teach `ContentAcquirer` to accept per-location headers;
|
|
26
|
+
- add private provenance fields to `ReferenceContent` and cache round-tripping;
|
|
27
|
+
- ensure secrets and localhost URLs are not written to frontmatter.
|
|
28
|
+
|
|
29
|
+
### 2. Add a Zotero API client and exact identifier index
|
|
30
|
+
|
|
31
|
+
Add contract tests using representative Zotero v3 JSON for:
|
|
32
|
+
|
|
33
|
+
- local API availability detection;
|
|
34
|
+
- paginated top-level item loading;
|
|
35
|
+
- DOI normalization;
|
|
36
|
+
- PMID/PMCID extraction from structured fields and `extra`;
|
|
37
|
+
- incremental index refresh metadata;
|
|
38
|
+
- duplicate and ambiguous identifiers;
|
|
39
|
+
- child attachment selection;
|
|
40
|
+
- indexed-full-text success and PDF fallback.
|
|
41
|
+
|
|
42
|
+
Then implement a small read-only client rather than coupling HTTP and matching
|
|
43
|
+
logic directly inside the provider. The default base URL is
|
|
44
|
+
`http://localhost:23119/api`; web mode remains disabled in this phase.
|
|
45
|
+
|
|
46
|
+
### 3. Add `ZoteroFullTextProvider`
|
|
47
|
+
|
|
48
|
+
Add provider tests showing:
|
|
49
|
+
|
|
50
|
+
- no identifier returns `None`;
|
|
51
|
+
- an exact DOI/PMID hit returns Zotero indexed text when usable;
|
|
52
|
+
- short or absent indexed text returns the PDF file location;
|
|
53
|
+
- ambiguity returns no location and a diagnostic;
|
|
54
|
+
- connection errors remain retryable in the provider chain;
|
|
55
|
+
- provenance is `provider=zotero` and `access_type=user_library` with no OA claim.
|
|
56
|
+
|
|
57
|
+
Register `zotero` for the explicit `cache enrich` workflow. Ordinary validation
|
|
58
|
+
must reject its `user_library` locations even if it is accidentally included in
|
|
59
|
+
the configured provider chain.
|
|
60
|
+
|
|
61
|
+
### 4. Add `cache enrich`
|
|
62
|
+
|
|
63
|
+
Add CLI tests first for dry-run, apply, misses, ambiguity, provider-unavailable,
|
|
64
|
+
and stable tabular output. Implement:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
cache enrich --provider zotero --cache-dir PATH [--dry-run]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The command enumerates Markdown cache files, loads them through `ReferenceFetcher`,
|
|
71
|
+
and runs only the selected private provider even if `full_text_attempted` is
|
|
72
|
+
already true. Apply mode reuses the normal materialization path but writes an
|
|
73
|
+
owner-only private research cache outside the project by default.
|
|
74
|
+
|
|
75
|
+
### 5. Positive local smoke test
|
|
76
|
+
|
|
77
|
+
Run the dry-run command against a temporary cache entry whose DOI is known to
|
|
78
|
+
exist in the local Zotero library while Zotero is running. Verify:
|
|
79
|
+
|
|
80
|
+
- exact DOI match;
|
|
81
|
+
- at least 500 extracted characters;
|
|
82
|
+
- cache provenance and checksum;
|
|
83
|
+
- no credential or private URL leakage;
|
|
84
|
+
- the source Zotero library remains unchanged.
|
|
85
|
+
|
|
86
|
+
The checked-in test suite must not depend on the developer's personal library.
|
|
87
|
+
|
|
88
|
+
## Phase 2: Zotero Web API
|
|
89
|
+
|
|
90
|
+
### 6. Add authenticated read-only web mode
|
|
91
|
+
|
|
92
|
+
Test and implement user/group library configuration, pagination, `since`-based
|
|
93
|
+
index refresh, backoff/rate-limit headers, attachment download authentication,
|
|
94
|
+
and Zotero storage/WebDAV absence behavior.
|
|
95
|
+
|
|
96
|
+
Credentials come from `ZOTERO_API_KEY` or a credential callback. Add explicit
|
|
97
|
+
configuration for user/group library ID; never accept API keys in URLs.
|
|
98
|
+
|
|
99
|
+
### 7. Operational documentation
|
|
100
|
+
|
|
101
|
+
Document how to enable the local API, create a read-only Zotero key, scan before
|
|
102
|
+
applying, protect private caches, and keep private content out of validation.
|
|
103
|
+
|
|
104
|
+
## Phase 3: Paperpile local sync
|
|
105
|
+
|
|
106
|
+
### 8. Build a generic local library index
|
|
107
|
+
|
|
108
|
+
Extract identifier normalization and match reporting from the Zotero client into
|
|
109
|
+
a source-neutral index. Add BibTeX ingestion with tests for DOI, PMID, title,
|
|
110
|
+
year, author, duplicate keys, and malformed entries. Add a cacheable PDF probe
|
|
111
|
+
that reads metadata/first-page text only once per file and stores its checksum.
|
|
112
|
+
|
|
113
|
+
### 9. Add `PaperpileFullTextProvider` for local files
|
|
114
|
+
|
|
115
|
+
Test and implement configuration for:
|
|
116
|
+
|
|
117
|
+
- a local Paperpile/Google Drive PDF root;
|
|
118
|
+
- a Paperpile automatic BibTeX export file or HTTPS download link;
|
|
119
|
+
- an optional manual Paperpile JSON export.
|
|
120
|
+
|
|
121
|
+
Only exact DOI/PMID matches apply automatically. Title/year/author candidates are
|
|
122
|
+
reported by `cache enrich --dry-run` and require explicit user confirmation in a
|
|
123
|
+
future task.
|
|
124
|
+
|
|
125
|
+
### 10. Measure matching quality
|
|
126
|
+
|
|
127
|
+
Run dry-run evaluation on a representative private cache and record precision,
|
|
128
|
+
coverage, ambiguity, and unmatched reasons separately. Do not weaken matching
|
|
129
|
+
thresholds to improve coverage. Use findings to decide whether guarded metadata
|
|
130
|
+
matching should ever be enabled for apply mode.
|
|
131
|
+
|
|
132
|
+
## Phase 4: Paperpile via Google Drive
|
|
133
|
+
|
|
134
|
+
### 11. Add a read-only Drive adapter
|
|
135
|
+
|
|
136
|
+
Test with Google Drive API fixtures, then implement OAuth read-only listing and
|
|
137
|
+
download, incremental change tracking, native Google shortcut handling, and
|
|
138
|
+
streamed size limits. Reuse the Paperpile BibTeX identity index from Phase 3.
|
|
139
|
+
|
|
140
|
+
This phase must not mutate Drive or Paperpile. Tokens use the system credential
|
|
141
|
+
store and are excluded from logs and config serialization.
|
|
142
|
+
|
|
143
|
+
## Phase 5: Privacy hardening and signed attestations
|
|
144
|
+
|
|
145
|
+
### 12. Separate private content from shareable cache metadata
|
|
146
|
+
|
|
147
|
+
Completed in the first implementation: private content uses an owner-only
|
|
148
|
+
research cache outside the project by default. Validation reads only the public
|
|
149
|
+
cache, and its ordinary provider chain rejects explicitly non-open locations.
|
|
150
|
+
|
|
151
|
+
### 13. Specify and implement offline signed excerpt attestations
|
|
152
|
+
|
|
153
|
+
Define a canonical, versioned `excerpts.yaml` schema and bind each record to its
|
|
154
|
+
reference ID, claim hash, normalized excerpt hash, private source checksum,
|
|
155
|
+
location, result, generator version, timestamp, and key ID. A trusted offline
|
|
156
|
+
job reads the private cache and signs with Ed25519. Only the verification key is
|
|
157
|
+
checked in; agents and CI cannot write trusted attestations. Add tests for valid,
|
|
158
|
+
tampered, wrong-reference, wrong-claim, unknown-key, expired-key, and unsigned
|
|
159
|
+
artifacts before enabling this optional validation mode.
|
|
160
|
+
|
|
161
|
+
## Phase 6: Browse a cache in Zotero
|
|
162
|
+
|
|
163
|
+
### 14. Export cache metadata for Zotero import
|
|
164
|
+
|
|
165
|
+
Implemented `cache export --format csl-json` with deterministic DOI/PMID
|
|
166
|
+
deduplication and missing-full-text filtering. It exports an explicit
|
|
167
|
+
bibliographic metadata allowlist and always excludes cached text, excerpts,
|
|
168
|
+
provenance, PDFs, private-cache data, and local paths. The command refuses to
|
|
169
|
+
overwrite an output file without `--force`.
|
|
170
|
+
|
|
171
|
+
### 15. Consider an opt-in Zotero collection sync
|
|
172
|
+
|
|
173
|
+
Only after export is stable, design an idempotent write integration that creates
|
|
174
|
+
or updates a dedicated Zotero collection through the documented write API. It
|
|
175
|
+
must require explicit write authorization and a dry-run diff; it must never
|
|
176
|
+
alter unrelated Zotero items or attach private files implicitly.
|
|
177
|
+
|
|
178
|
+
## Definition of done for the minimal first task
|
|
179
|
+
|
|
180
|
+
- `cache enrich --provider zotero --dry-run` inventories an existing reference
|
|
181
|
+
cache without modifying it.
|
|
182
|
+
- Exact DOI/PMID matches identify PDF attachments in the supported Zotero local
|
|
183
|
+
API.
|
|
184
|
+
- Apply mode extracts usable text into the private research cache without changing the
|
|
185
|
+
public source cache.
|
|
186
|
+
- Normal validation ignores the private research cache and rejects private
|
|
187
|
+
provider results.
|
|
188
|
+
- Misses and ambiguities are visible and safe.
|
|
189
|
+
- No private API, direct SQLite dependency, secret persistence, or library write.
|
|
190
|
+
- Focused tests, doctests, mypy, Ruff, and the full `just test` suite pass.
|