sciwrite-lint 0.2.0__py3-none-any.whl

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 (76) hide show
  1. sciwrite_lint/__init__.py +3 -0
  2. sciwrite_lint/__main__.py +527 -0
  3. sciwrite_lint/_network.py +195 -0
  4. sciwrite_lint/api.py +1484 -0
  5. sciwrite_lint/checks/__init__.py +1 -0
  6. sciwrite_lint/checks/_section_utils.py +111 -0
  7. sciwrite_lint/checks/cite_purpose.py +122 -0
  8. sciwrite_lint/checks/claim_support.py +96 -0
  9. sciwrite_lint/checks/cross_section_consistency.py +185 -0
  10. sciwrite_lint/checks/dangling_cite.py +93 -0
  11. sciwrite_lint/checks/dangling_ref.py +116 -0
  12. sciwrite_lint/checks/full_paper_consistency.py +604 -0
  13. sciwrite_lint/checks/ref_internal_checks.py +919 -0
  14. sciwrite_lint/checks/reference_accuracy.py +277 -0
  15. sciwrite_lint/checks/reference_exists.py +119 -0
  16. sciwrite_lint/checks/reference_unreliable.py +244 -0
  17. sciwrite_lint/checks/registry.py +136 -0
  18. sciwrite_lint/checks/retracted_cite.py +96 -0
  19. sciwrite_lint/checks/structure_promises.py +115 -0
  20. sciwrite_lint/checks/unreferenced_figure.py +70 -0
  21. sciwrite_lint/claims.py +330 -0
  22. sciwrite_lint/claude_backend.py +94 -0
  23. sciwrite_lint/claude_cli.py +405 -0
  24. sciwrite_lint/cli/__init__.py +1 -0
  25. sciwrite_lint/cli/check.py +480 -0
  26. sciwrite_lint/cli/config.py +229 -0
  27. sciwrite_lint/cli/fetch.py +250 -0
  28. sciwrite_lint/cli/misc.py +1202 -0
  29. sciwrite_lint/cli/rank.py +470 -0
  30. sciwrite_lint/cli/verify.py +437 -0
  31. sciwrite_lint/config.py +646 -0
  32. sciwrite_lint/cross_paper.py +174 -0
  33. sciwrite_lint/eval_claims.py +1196 -0
  34. sciwrite_lint/fulltext.py +851 -0
  35. sciwrite_lint/llm_utils.py +386 -0
  36. sciwrite_lint/local_pdfs.py +122 -0
  37. sciwrite_lint/manuscript_store.py +674 -0
  38. sciwrite_lint/models.py +139 -0
  39. sciwrite_lint/pdf/__init__.py +1 -0
  40. sciwrite_lint/pdf/grobid.py +785 -0
  41. sciwrite_lint/pdf/pdf_download.py +258 -0
  42. sciwrite_lint/pipeline.py +2694 -0
  43. sciwrite_lint/prompt_safety.py +30 -0
  44. sciwrite_lint/rate_limiter.py +227 -0
  45. sciwrite_lint/references/__init__.py +1 -0
  46. sciwrite_lint/references/citations.py +715 -0
  47. sciwrite_lint/references/crossref.py +282 -0
  48. sciwrite_lint/references/embedding_store.py +380 -0
  49. sciwrite_lint/references/matching.py +273 -0
  50. sciwrite_lint/references/metadata.py +273 -0
  51. sciwrite_lint/references/reference_store.py +823 -0
  52. sciwrite_lint/references/retraction_watch.py +178 -0
  53. sciwrite_lint/references/workspace_db.py +1390 -0
  54. sciwrite_lint/report.py +163 -0
  55. sciwrite_lint/schemas.py +260 -0
  56. sciwrite_lint/scoring/__init__.py +1 -0
  57. sciwrite_lint/scoring/chain.py +716 -0
  58. sciwrite_lint/scoring/contribution.py +322 -0
  59. sciwrite_lint/scoring/scilint_score.py +611 -0
  60. sciwrite_lint/tex_parser.py +248 -0
  61. sciwrite_lint/usage.py +594 -0
  62. sciwrite_lint/vision/__init__.py +1 -0
  63. sciwrite_lint/vision/cache.py +140 -0
  64. sciwrite_lint/vision/describe.py +311 -0
  65. sciwrite_lint/vision/image_extraction.py +491 -0
  66. sciwrite_lint/vision/pipeline.py +207 -0
  67. sciwrite_lint/vllm/__init__.py +1 -0
  68. sciwrite_lint/vllm/metrics.py +157 -0
  69. sciwrite_lint/vllm/vllm_server.py +445 -0
  70. sciwrite_lint/web.py +369 -0
  71. sciwrite_lint-0.2.0.dist-info/METADATA +268 -0
  72. sciwrite_lint-0.2.0.dist-info/RECORD +76 -0
  73. sciwrite_lint-0.2.0.dist-info/WHEEL +5 -0
  74. sciwrite_lint-0.2.0.dist-info/entry_points.txt +2 -0
  75. sciwrite_lint-0.2.0.dist-info/licenses/LICENSE +21 -0
  76. sciwrite_lint-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,139 @@
1
+ """Data models for sciwrite-lint."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Literal
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class Finding(BaseModel):
11
+ """A single issue found by a check."""
12
+
13
+ level: Literal["error", "warning", "info"]
14
+ rule_id: str # check ID, e.g., "dangling-cite", "reference-exists"
15
+ message: str
16
+ file: str = ""
17
+ line: int | None = None
18
+ context: str = ""
19
+
20
+
21
+ class CheckMeta(BaseModel):
22
+ """Metadata for a registered check."""
23
+
24
+ id: str # "dangling-cite", "cross-section-consistency", etc.
25
+ severity: Literal["error", "warning", "info"]
26
+ category: Literal["manuscript", "reference-db", "local-llm"]
27
+ description: str
28
+
29
+
30
+ # Legacy alias for backwards compatibility
31
+ RuleMeta = CheckMeta
32
+
33
+
34
+ class CheckResult(BaseModel):
35
+ """Result from running checks on a paper."""
36
+
37
+ checker: str # e.g., "check", "verify"
38
+ paper: str # e.g., "my_paper" or filename
39
+ findings: list[Finding] = Field(default_factory=list)
40
+
41
+ @property
42
+ def errors(self) -> list[Finding]:
43
+ return [f for f in self.findings if f.level == "error"]
44
+
45
+ @property
46
+ def warnings(self) -> list[Finding]:
47
+ return [f for f in self.findings if f.level == "warning"]
48
+
49
+ @property
50
+ def ok(self) -> bool:
51
+ return not self.errors
52
+
53
+
54
+ class Citation(BaseModel):
55
+ """A citation extracted from a .tex file."""
56
+
57
+ key: str
58
+ raw_text: str
59
+ authors: list[str] = Field(default_factory=list)
60
+ title: str = ""
61
+ year: str = ""
62
+ venue: str = ""
63
+ doi: str = ""
64
+ url: str = ""
65
+ arxiv_id: str = "" # e.g. "2310.01798"
66
+ pmid: str = "" # e.g. "12345678"
67
+ pmc_id: str = "" # e.g. "PMC1234567"
68
+ isbn: str = "" # e.g. "9780226458113"
69
+ lccn: str = "" # e.g. "2019012345"
70
+ source_paper: str = ""
71
+ bib_format: str = "" # "simple", "natbib", or "bib"
72
+ entry_type: str = "" # BibTeX entry type: "article", "misc", etc.
73
+
74
+ # Local source
75
+ local_status: Literal["pdf", "md", "none"] = "none"
76
+ local_path: str = ""
77
+
78
+ # API verification
79
+ api_match: Literal[
80
+ "",
81
+ "verified",
82
+ "mismatch",
83
+ "not_found",
84
+ "skipped",
85
+ "web_verified",
86
+ "web_dead",
87
+ "manual",
88
+ ] = ""
89
+ api_source: str = ""
90
+ api_data: dict = Field(default_factory=dict)
91
+ issues: list[str] = Field(default_factory=list)
92
+
93
+ # Tier (computed from metadata)
94
+ tier: Literal["T1", "T2", "T3", ""] = ""
95
+
96
+
97
+ class CitationMetadata(BaseModel):
98
+ """Persistent per-citation verification record stored as JSON."""
99
+
100
+ key: str
101
+ verified_date: str = ""
102
+ api_source: str = "" # "crossref", "openalex", "semantic_scholar"
103
+ api_match: Literal[
104
+ "",
105
+ "verified",
106
+ "mismatch",
107
+ "not_found",
108
+ "skipped",
109
+ "web_verified",
110
+ "web_dead",
111
+ "manual",
112
+ ] = ""
113
+
114
+ # Canonical data from API (what the world says)
115
+ canonical: dict[str, Any] = Field(default_factory=dict)
116
+
117
+ # What our .tex bibitem says
118
+ bibitem: dict[str, Any] = Field(default_factory=dict)
119
+
120
+ # Access status
121
+ access: dict[str, Any] = Field(default_factory=dict)
122
+
123
+ mismatches: list[str] = Field(default_factory=list)
124
+ issues: list[str] = Field(default_factory=list)
125
+
126
+ # Manual override
127
+ manual_override: dict[str, Any] = Field(default_factory=dict)
128
+
129
+
130
+ class SectionInfo(BaseModel):
131
+ """A section in a LaTeX document."""
132
+
133
+ label: str # e.g., "sec:intro" (empty if no label)
134
+ title: str
135
+ depth: int # 0=section, 1=subsection, 2=subsubsection
136
+ start_line: int
137
+ end_line: int
138
+ word_count: int
139
+ cite_count: int = 0
@@ -0,0 +1 @@
1
+ """PDF acquisition and parsing: GROBID and download utilities."""