Skip to content
Back to skills

Extract Contributions

ASecurity

Extract the stated scientific contribution of a cited paper from its full text, to check that a citation says what the paper actually claims. Companion to extract-futureworks: that one mines what a corpus says remains to be done, this one mines what each paper says it did. Two modes. Mode validate: for one manuscript, pair every cited key with its paper's own contribution sentences and flag the citations whose claim the paper does not support. Mode mine: sweep a refs/ corpus and tabulate what...

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 9, 2026
researchpythonbash

Works with

  • cli

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned October 9, 2026

npx -y skills add LARi-UQAC/ResearchTools --skill extract-contributions --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Extract Contributions?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Extract Contributions
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lari-uqac-extract-contributions-researchtools/badge)](https://www.skillsdirectory.com/skills/lari-uqac-extract-contributions-researchtools)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: extract-contributions
description: "Extract the stated scientific contribution of a cited paper from its full text, to check that a citation says what the paper actually claims. Companion to extract-futureworks: that one mines what a corpus says remains to be done, this one mines what each paper says it did. Two modes. Mode validate: for one manuscript, pair every cited key with its paper's own contribution sentences and flag the citations whose claim the paper does not support. Mode mine: sweep a refs/ corpus and tabulate what each paper contributes, for a related-work section or a novelty probe. Trigger on: validate a citation against the article, check that a reference supports the sentence citing it, contribution of each cited paper, extract-contributions, cohérence citation article."
---

# extract-contributions

## Why this exists

Measured 2026-09-12 on the BuildingGIS MITACS proposal. Fourteen references
were retained, and their claims written into the text, on the strength of their
**abstract alone**. Worse, six of the fourteen "full texts" were one-page
publisher previews, so even that abstract-level check had run on a stub.

The professor's objection is the whole specification of this skill:

> Je dois valider l'article et le contenu du texte de la demande. Si je n'ai pas
> l'article, je ne peux pas faire de validation. Il est strictement interdit
> d'inventer quelque chose qui n'est pas écrit.

An abstract states what a paper is *about*. It does not always state what the
paper *contributes*, and the sentence a citing author needs — "to the best of
our knowledge this is the first...", "unlike previous work, we..." — often lives
only in the introduction's contributions paragraph. Citing from the abstract is
how a reference ends up supporting a sentence it never made.

## Precondition, not an option

The full text must be in `refs/` **and verified**. `download_pdf.py` now refuses
a one-page paywall preview and continues its tier chain, but check anyway: a
paper whose text could not be read and a paper that states no contribution are
different findings, and this script keeps them apart (`unreadable`, `empty`,
`no-contribution`, `ok`).

## Modes

### Mode validate — one manuscript

```bash
python "$S" refs/ --manuscript paper.tex --json
python "$S" refs/ --manuscript paper.tex --write-contributions refs/_contributions
```

The script reads every `\cite{key}` of the manuscript, finds the sentence that
carries it, pairs that sentence with the cited paper's own contribution
sentences out of `refs/<key>.*`, and cross-checks every figure the citing
sentence attributes to the paper against the paper's full text. Then YOU judge,
one by one: does the citing sentence assert something the paper's own words
support? Emit a flagged finding for every citation where it does not.

What it does mechanically, so that a thirty-figure audit does not become an
impression:

- **Comments are blanked, not removed.** A commented-out `\cite` is not in the
  manuscript and auditing it would invent work, while removing the text would
  move every line number after it.
- **A multi-key `\cite{a,b}` is reported under both keys.** The sentence
  asserts something of both papers, so both are judged against it.
- **Structure ends a sentence.** A claim in the first sentence of a section
  would otherwise be handed to the reader carrying the section title.
- **Figures survive the decimal comma.** The manuscript may be French and the
  corpus English: "52,5 AP" and "52.5 AP" are one claim. A number `in_paper:
  false` is evidence, never a verdict - it may be the manuscript's own
  arithmetic, or a figure from a table the extractor lost.
- **A cited key with no file in `refs/` is `no-fulltext`**, never
  `no-contribution`. A retrieval gap is not a silent paper.

`--write-contributions DIR` keeps one Markdown note per cited paper: what the
paper says it contributes, and every sentence of the manuscript that cites it.
Put it under `refs/_contributions`; the leading underscore is what stops a later
corpus scan from reading those notes back as though they were papers.

The judgment is the agent's. The script only supplies the evidence, and
supplies it verbatim.

### Mode mine — a corpus

Sweep `refs/` and tabulate what each paper claims to contribute, by kind. Feeds
a related-work section, and feeds a novelty probe: a claim of the form "no
published framework does X" is worth far more when it is set against what every
paper in the corpus says it does.

## Usage

```bash
S=.claude/skills/extract-contributions/scripts/extract_contributions.py

python "$S" refs/amer2017roofstacking.pdf            # one paper, plain text
python "$S" refs/ --json > contributions.json        # whole corpus
python "$S" refs/ --only munda2012noncompensatory --only otto2026sanborn
python "$S" refs/ --strict                           # exit 1 if any paper is silent
```

Output per paper: `citekey`, `file`, `chars`, `status`, `kinds_found`, and the
contribution `sentences`, each with its `kind`, the `marker` that matched, and
a `position` between 0 and 1. Position is the sentence index over the sentence
count, so a contributions paragraph in the introduction (near 0.05) is
distinguishable from a claim restated in the conclusion (near 0.9) without
needing page numbers, which the text extractors do not preserve.

## What it does not do

**It does not decide.** It surfaces candidate sentences. The marker list is a
heuristic and it has false positives: on `amer2017roofstacking`, "The first
method is densification by filling the backyards" matched the `novelty` kind,
where "first" enumerates rather than claims priority. A reader settles that in
a second; a regex cannot. Treat `kinds_found` as a sorting aid, never as a
verdict.

**It does not read what is not there.** A paper that never states a
contribution returns `no-contribution`, which is a fact about the paper. An
unreadable PDF returns `unreadable` with the reason. Neither is ever reported
as the other.

## Where the pieces live

- `scripts/extract_contributions.py` — the CLI and the scan.
- `scripts/contribution_markers.json` — the phrases, as DATA (R6). Four kinds:
  `contribution`, `novelty`, `result`, `method`. Extend this file, not the
  module. A missing or empty catalogue is an explicit error (R3), because
  scanning with no markers would return "no contribution found" for every
  paper, which reads like a measurement and is not one.
- The PDF and HTML readers are **reused** from
  `extract-statistic/scripts/extract_text.py` (R18: one owner per capability).
  This skill ships no reader of its own.
- `scripts/Test/test_extract_contributions.py` — offline, no PDF, no network.

Files in this skill

  • SKILL.md6.6 KB
  • scripts/Test/test_extract_contributions.py32.3 KB
  • scripts/contribution_markers.json7.1 KB
  • scripts/extract_contributions.py28.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.