|
| 1 | +# Changelog |
| 2 | + |
| 3 | +## 1.4.0 (2026-07-13) |
| 4 | + |
| 5 | +### New output formats |
| 6 | +- **CSV bundle** (`--format bundle`): writes `citing_papers.csv`, `authors.csv` |
| 7 | + (with country + match confidence), `venues.csv`, and `timeline.csv` into one |
| 8 | + directory for spreadsheet analysis. |
| 9 | +- **Citation tree**: interactive terminal tree (menu option 8, groupable by |
| 10 | + year / venue / institution) and a plain-text export (`--format tree`). |
| 11 | +- **HTML report** (`--format html`): a single self-contained HTML file with |
| 12 | + stat tiles, citation timeline chart, world map of citing institutions, |
| 13 | + citation-intent chart with context quotes, scholar/venue tables, and a |
| 14 | + collapsible citation tree. Works offline, light/dark aware. |
| 15 | + |
| 16 | +### International reach |
| 17 | +- Citing authors' institution **countries** are now captured from OpenAlex |
| 18 | + (ISO codes on every author, a per-country breakdown in results, a |
| 19 | + "cited across N countries" grant statement, country column in exports). |
| 20 | + |
| 21 | +### Reliability |
| 22 | +- Live end-to-end testing caught and fixed a crash: OpenAlex returns explicit |
| 23 | + `null` for `summary_stats` / `last_known_institutions` / `affiliations` on |
| 24 | + some records; all parsing sites are now null-safe (regression-tested). |
| 25 | +- `max_citations` is clamped to Semantic Scholar's 1000-limit in API mode |
| 26 | + instead of failing with HTTP 400. |
| 27 | +- Full-diff regression audit confirmed and fixed 10 defects introduced during |
| 28 | + the sprint, including: Google Scholar citation IDs leaking from one analysis |
| 29 | + into the next; OpenAlex title lookups breaking on commas (filter injection); |
| 30 | + author dedup creating "chimera" entries (one person's identity with another's |
| 31 | + h-index); Rich-markup crashes on citation text containing bracket tokens |
| 32 | + (e.g. `[/INST]`, `[sic]`); scripted `-o -` output polluted by progress |
| 33 | + prints (now on stderr); explicit `--h-index-threshold 0` being ignored; |
| 34 | + 12-letter surnames misread as Google Scholar IDs. |
| 35 | +- Data-quality safeguards: correct Semantic Scholar request pacing with an API |
| 36 | + key (was 40 req/s against a ~1 req/s allowance, causing silent mass |
| 37 | + failures), `Retry-After` honored on 429s, per-run API-failure tracking with a |
| 38 | + visible "data may be incomplete" banner in the UI and all report formats, and |
| 39 | + degraded results are no longer written to the 7-day cache. The alarm is |
| 40 | + proportional: a few transient failures produce a note, not the banner. |
| 41 | +- **Batch author fetching**: citing-author profiles are now fetched from |
| 42 | + Semantic Scholar's batch endpoint (one request for up to 500 authors instead |
| 43 | + of one per author), then enriched via OpenAlex as before — analyses make an |
| 44 | + order of magnitude fewer requests and survive strict rate limits. |
| 45 | +- **Adaptive throttle**: consecutive rate-limit failures automatically slow |
| 46 | + request pacing (up to 8×) and recover on success. OpenAlex now runs at half |
| 47 | + its polite-pool allowance by default; set your email in Settings to join the |
| 48 | + polite pool (dramatically more reliable than anonymous access). |
| 49 | + |
| 50 | +## 1.3.1 (2026-07-12) |
| 51 | + |
| 52 | +### Author disambiguation overhaul (fixes reported same-name mix-ups) |
| 53 | +Addresses the reported issue where authors sharing a name could be mistaken |
| 54 | +for each other. Author resolution is now **ID-first with evidence-verified |
| 55 | +fallbacks**: |
| 56 | + |
| 57 | +- Every resolved author profile carries a `match_confidence` provenance: |
| 58 | + `id` (unique Semantic Scholar / Google Scholar identifier), `verified` |
| 59 | + (name search corroborated by the candidate's publication list), or |
| 60 | + `name` (unverified name-only match). |
| 61 | +- Name-keyed author-cache hits are now **gated**: a cached profile that |
| 62 | + merely shares an author's name is only reused when its stored publications |
| 63 | + contain the citing paper. Unverifiable name hits are rejected rather than |
| 64 | + trusted. |
| 65 | +- **Browse Other Authors by name** now shows a disambiguation picker |
| 66 | + (name, affiliation, h-index, paper count from Semantic Scholar author |
| 67 | + search) instead of silently using the first same-named hit. |
| 68 | +- The UI marks each author with ✓ (ID-matched), ≈ (verified), or ? (name-only, |
| 69 | + may be a different person), with a legend; the summary shows |
| 70 | + "Author profiles: N ID-matched, N verified, N name-only", and the Markdown |
| 71 | + export gains a Match column. |
| 72 | +- Exports now use the configured h-index threshold in their labels instead of |
| 73 | + a hardcoded "≥ 20". |
| 74 | + |
| 75 | +## 1.3.0 (2026-07-12) |
| 76 | + |
| 77 | +### New features |
| 78 | +- **Field-normalized impact (FWCI)**: analyses now fetch the Field-Weighted |
| 79 | + Citation Impact and field citation percentile from OpenAlex (1.0 = world |
| 80 | + average for the same field/year), shown in the overview, grant summary, |
| 81 | + impact statements, and exports. Degrades gracefully when unavailable. |
| 82 | +- **Self-citation detection**: every analysis now reports how many citations |
| 83 | + are independent of the original authors (matched by Semantic Scholar author |
| 84 | + ID, falling back to name compatibility) — the number grant reviewers ask for. |
| 85 | +- **"How Your Work Is Used"**: new drill-down (option 7) showing the citation |
| 86 | + intent distribution (methodology / background / result) and sample in-text |
| 87 | + context quotes from citing papers. |
| 88 | +- **Report exporter** (`citationimpact/export.py`): export analyses as |
| 89 | + grant-ready **Markdown**, **LaTeX** (appendix-ready section), **CSV** (all |
| 90 | + citing papers), **BibTeX**, or JSON — from the results screen (`e`) or the CLI. |
| 91 | +- **Non-interactive CLI** (`citationimpact/cli.py`): script the tool without |
| 92 | + menus — `citation-impact analyze "Paper title" --format markdown -o report.md`, |
| 93 | + `citation-impact cache list|clear`, `citation-impact --version`. |
| 94 | + Running `./citation-impact` with no arguments still opens the interactive UI. |
| 95 | +- **Test suite**: 200+ pytest tests covering exporters, models, categorization, |
| 96 | + rankings, caches, analyzer logic, clients, UI helpers, and the CLI. |
| 97 | +- **CI**: GitHub Actions workflow running the suite on Python 3.9–3.12. |
| 98 | + |
| 99 | +### Bug fixes (72 verified defects, found by multi-agent audit) |
| 100 | +Highlights — full details in git history: |
| 101 | +- **Institution misclassification (critical)**: substring matching classified |
| 102 | + Princeton/Cincinnati as *Industry* (`'inc'`), and any "Department of …", |
| 103 | + Newcastle, or NIST-like affiliation as *Government* (`'epa'`, `'cas'`, |
| 104 | + `'nist'` substrings). Now word-boundary matched. |
| 105 | +- **Wrong university credit**: fuzzy matchers gave "National University" NUS's |
| 106 | + Top-10 rank and matched arbitrary superstring venues; QS range ranks |
| 107 | + (601-610 etc., 60% of the file) were silently dropped; ICORE junk strings |
| 108 | + ("Unranked", "TBR") were surfaced as ranks. |
| 109 | +- **Dead features revived**: methodological citations (S2 returns lowercase |
| 110 | + intents), Crossref citation-count/venue merging (key mismatch/unreachable |
| 111 | + branch), S2 DOI enrichment (externalIds never requested), ORCID fallback |
| 112 | + (wrong class name + list/dict mismatch), DBLP author publications |
| 113 | + (nonexistent endpoint), GS-only papers yielding 0 citations in |
| 114 | + comprehensive mode. |
| 115 | +- **Crashes fixed**: google_scholar mode signature mismatches, unified |
| 116 | + search_paper on zero-score results, null citationCounts, ORCID null-name |
| 117 | + records, QS range-rank parsing, None affiliations. |
| 118 | +- **Correctness**: author dedup no longer merges distinct authors (first-initial |
| 119 | + guard) and no longer loses repeat citers' papers; publication-overlap cache |
| 120 | + matching no longer attributes co-authors' profiles to each other; author-profile |
| 121 | + cache no longer merges same-name researchers; grant statements no longer |
| 122 | + conflate author counts with university counts and respect the configured |
| 123 | + h-index threshold; citation URLs no longer dropped by an operator-precedence |
| 124 | + bug; "recent citations" now really spans 2 years. |
| 125 | +- **Robustness**: config writes are atomic (API keys can't be destroyed by a |
| 126 | + failed save); connection errors are retried; cache expiry handles unlink |
| 127 | + races; UTF-8 enforced for profile files; shared client no longer reused |
| 128 | + across data-source switches (stale-mode analyses); browse-author-by-name |
| 129 | + works in API mode; Selenium clients are tracked and closed. |
| 130 | + |
| 131 | +### Packaging & hygiene |
| 132 | +- `setup.py` console entry point referenced a nonexistent module; now installs |
| 133 | + working `citation-impact` / `citationimpact-ui` commands; version |
| 134 | + single-sourced from `citationimpact/__init__.py` (was 0.1.0 vs 1.2.0). |
| 135 | +- Added `pyproject.toml`, `.gitignore` (the `.citationimpact/` folder holding |
| 136 | + plaintext API keys was previously trackable), and untracked committed |
| 137 | + `__pycache__` files. |
| 138 | + |
| 139 | +## 1.2.0 |
| 140 | + |
| 141 | +- Prior release (see git history). |
0 commit comments