---
name: abstract_writing_basics
description: "Write the short academic abstract for a finished paper or thesis: pull the background, method, results, and conclusion moves from the paper itself, hold a word budget, copy result numbers exactly, keep citations out, pick keywords from terms the paper uses, and check every number in the abstract against the paper. Use when a paper or thesis is finished and needs an abstract, or when an existing abstract needs a check against its paper."
metadata: { "includeInPrompt": true }
---

# Abstract Writing Basics

## Purpose

Write an abstract that reports the paper in front of you, in a short space, without adding anything the paper does not say. The routine extracts four moves from the finished paper itself, drafts them in order, holds a stated word budget, copies result numbers exactly, keeps citations out, picks keywords from terms the paper actually uses, and runs a final check that every number and claim in the abstract appears in the paper.

Scope:
- executive-summary-writing writes a decision summary of an existing long document (conclusion, evidence, costs, ask). This skill does not write that summary.
- reading-papers reads papers and pulls claims from abstracts. This skill does not read a paper for someone else. It writes the abstract for a paper.
- white-paper-writing writes a full evidence document. This skill does not write the full document. It writes the short text that sits at its head when the document is a paper or thesis.
- This skill writes the short academic abstract for a paper or thesis: structured moves (background, method, results, conclusion), word budget, no citations in the abstract, keywords, and a check that every number in the abstract appears in the paper.
- This skill works from the finished paper as plain text or in any ordinary document form. It names no submission system, no journal platform, and no reference manager.
- Verification note, 2026-10-21: abstract_check.py below was run with Python 3.12.3, the version `python3 --version` returned on the drafting machine, against a fixture built by the script itself in a temporary directory. The fixture run returned abstract_word_count: 42, budget_status: below, citations_found: 1, numbers_total: 2, numbers_missing_from_paper: 1, move_method_signal: missing, move_result_signal: present, verdict: REVIEW. The script uses only the Python standard library (`os`, `re`, and `sys`), so no package version is quoted and no install step is needed. What was NOT verified: no specific journal or university abstract limit was checked, and no specific venue limit is claimed. Word ranges in this skill are guidance to confirm with the target venue.

## Workflow

1. Confirm the paper is finished and get the venue limit.
   - Start only when the paper is finished, or when the parts the abstract will report are finished and stable. An abstract drafted before the results settle invites numbers and claims that the final paper does not hold.
   - Get the abstract limit from the submission guidance supplied for the task, when guidance was supplied. Record whether it is a maximum, a range, or a target, and record the exact number or numbers.
   - When no venue limit was supplied, use 150 to 250 words as a common range and as guidance only. Label it that way in the working notes. Venue limits vary, so the range does not stand in for a limit that still needs checking.
   - Write the budget at the top of the working notes before drafting. Cuts made to fit a budget set in advance are planned cuts. Cuts made after drafting with no budget tend to remove the results first, which is the wrong order.

2. Extract the background and gap move from the paper.
   - Read the introduction of the paper. Find three things in its own wording: the problem or topic, what is already known, and the gap, question, or reason the study was done.
   - Compress those three things to one or two sentences. The background move sets up the study. It does not retell the whole introduction and it does not add context the paper does not contain.
   - Use the terms the paper uses for its topic and population. A new term coined for the abstract can read as a different topic from the one the paper studies.
   - If the paper states no clear gap, report the stated question or aim instead. Do not invent a gap to make the opening sound stronger.

3. Extract the method move from the paper.
   - Read the method section. Note the design, who or what was studied, the main procedure, and the main measure or analysis, in that order.
   - Copy any number that belongs in this move exactly as the paper gives it: sample size, group counts, duration, dose, or number of cases. Check each digit, decimal place, and unit against the paper.
   - Compress the method to one or two sentences. Name the design and the main procedure. Leave routine detail, equipment lists, and step by step procedure for the paper itself.
   - Keep the tense and the level of detail consistent with what the paper reports. A planned step that the paper reports as planned does not become a completed step in the abstract.

4. Extract the results move from the paper.
   - Read the results section. Put the main finding first, then the one or two supporting findings that the paper itself treats as central.
   - Copy the key numbers exactly from the paper: values, percentages, group means, differences, counts, and time points. Check each number digit by digit against the paper before it enters the draft.
   - Do not round a number, change its unit, or combine two numbers into a new number the paper does not state. A combined or converted value is a new number, and the final check will flag it because it does not appear in the paper.
   - Leave secondary and exploratory results out when the budget is tight. The results move carries the findings a reader needs to judge the paper.

5. Extract the conclusion move from the paper.
   - Read the discussion and the closing section of the paper. Note what the paper says its results mean, the main implication it states, and any limit it states plainly.
   - Compress that material to one sentence, two at most. State the takeaway the paper supports, in the strength the paper supports it.
   - Match claim strength to the paper. When the paper says a result may help, suggests an effect, or applies to a stated sample, the abstract keeps that wording. It does not upgrade a cautious claim into a proved claim.
   - Do not add an application, a recommendation, or a future step that the paper does not state. A new claim in the final sentence is still a new claim, and the final check treats it the same as any other.

6. Draft in move order and hold the word budget.
   - Draft in this order: background, method, results, conclusion. One short paragraph is the usual shape unless the supplied venue guidance asks for headed sections.
   - Count words as the draft grows, not only at the end. A simple whitespace count, the count the checker uses, is close enough for drafting when the same method is used throughout.
   - When the draft runs over budget, cut in this order: background detail first, method routine detail second, supporting results third. Cut the main result numbers and the conclusion claim last, and only by shortening wording around them.
   - When the draft runs well under a stated minimum, add back material from the paper in the same order in reverse: a supporting result, a method detail that helps a reader judge the work, then background. Do not pad with general statements about the field.

7. Keep citations out and keep the wording self contained.
   - Remove every citation marker from the abstract: bracket numbers, author and year parentheses, footnote marks, and links or identifiers that point to a reference list. The abstract stands alone, away from the paper and its reference list, so a citation in it points at nothing.
   - When prior work matters to the background move, state the gap or the known point in plain words without naming a citation. The paper carries the citations. The abstract carries the point.
   - Define an abbreviation on first use when the abstract needs it, and use the same form the paper uses. A reader who sees only the abstract has no glossary from the paper to fall back on.
   - Check names, group labels, and measure names against the paper. A shortened label that the paper never uses can read as a different group or a different measure.

8. Pick keywords from terms the paper actually uses.
   - Build the candidate list from the paper itself: title terms, heading terms, and the exact terms used for the topic, the population, the method, and the main outcome.
   - Pick the keywords from that candidate list only. Copy each keyword with the spelling and form the paper uses, singular or plural as the paper has it.
   - Do not add a popular term the paper does not use, even when it sounds close. A keyword that names a concept absent from the paper misstates what the paper covers.
   - When supplied venue guidance states a keyword count or a place for the list, follow that guidance and record it in the budget record. When it states neither, place the list after the abstract and mark the count as a working choice, not a rule.

9. Run the checker and fix each flag at its source.
   - Save the script from the Operating Rules section as abstract_check.py. Save the draft abstract as a plain text file and the paper as a plain text file. Plain text keeps the word count and the number check honest, with no markup counted as words.
   - Run the checker: `python3 abstract_check.py ABSTRACT_FILE PAPER_FILE`, adding `--budget-min N --budget-max N` when the venue limit differs from the default 150 to 250 range. The checker changes no file. It reports word count against the budget, citation markers found, numbers in the abstract that do not appear in the paper, and method and result move signals.
   - Read the move signals as signals, not proof. A missing method signal means no method term from the check list appeared, which is a prompt to reread the method move. A present signal means a term appeared. It does not prove the method move is complete or correct.
   - Fix each flag in the draft, not in the checker output: remove the citation marker, correct or remove a flagged number by checking the paper, add the missing move from the paper, and trim or expand to the budget. Then rerun the checker and keep the new output.

10. Do the final number and claim check by hand.
    - The checker covers numbers, citations, word count, and two move signals. Claims need a hand check, because a claim can use no flagged number and still say something the paper does not say.
    - Go sentence by sentence. For each sentence, point to the section of the paper that supports it: introduction for background, method section for method, results section for results, closing section for the conclusion move. A sentence with no supporting section gets rewritten from the paper or removed.
    - Go number by number through the final draft, including numbers in the method move and the keyword list setting. Confirm each one appears in the paper with the same value and unit. The checker list from step 9 is the starting list for this pass, not a substitute for it.
    - Read the abstract once alone, with the paper closed. It should state the problem, the method, the main result with its numbers, and the takeaway, without needing the paper to make sense. Then read it once against the paper, which is the check that it adds nothing.

## Output Contract

Deliver these items, in this order:

1. Abstract draft: the final abstract text, in move order (background, method, results, conclusion), within the stated budget, with no citation markers, and with a keyword list after it when the task calls for one.
2. Move map: one line per move, naming the move and the section of the paper it was extracted from, so a reader can trace each part of the abstract back to the paper.
3. Checker output: the full output of abstract_check.py for the final run. On the worked fixture in the Operating Rules section the headline numbers are: abstract_word_count: 42, budget_status: below, citations_found: 1, numbers_total: 2, numbers_missing_from_paper: 1, move_method_signal: missing, move_result_signal: present, verdict: REVIEW.
4. Number and claim check: one row per number in the abstract, with the number, where it appears in the paper, and a match or fixed note, plus one row per main claim, with the claim in short form and the supporting section of the paper.
5. Keywords: the keyword list as delivered, with the paper term each keyword was taken from. A keyword with no paper term does not belong on the list.
6. Budget record: the venue limit when supplied guidance stated one, or a note that the common range of 150 to 250 words was used as guidance to confirm with the target venue, plus the final word count from the checker output.
7. Limits: anything the draft did not cover, stated plainly (for example a venue limit that was never supplied, a paper section that was missing or unfinished, or a claim left out because the paper did not support it).

## Operating Rules

1. The paper is the only source. Every number, term, and claim in the abstract comes from the paper. Material from memory, from another paper, or from general knowledge about the field stays out, even when it is true.
2. Numbers are copied exactly. Value, decimal places, unit, and percent form match the paper. No rounding, no unit change, and no combined value that creates a number the paper does not state.
3. No citations in the abstract. No bracket markers, no author and year parentheses, no footnote marks, and no reference identifiers. Prior work enters as a plain statement of what is known or missing, with no marker attached.
4. The budget is the venue limit when one was supplied. When none was supplied, 150 to 250 words is guidance only, labeled as a common range to confirm against the target venue limit, never stated as a universal rule.
5. Keywords come from the paper. Each keyword is a term the paper actually uses, spelled as the paper spells it. A term added for reach, with no use in the paper, is removed.
6. Move signals are signals, not proof. The checker keyword checks prompt a reread of the method and results moves. They never certify that a move is present in substance, complete, or correct.
7. Claims keep the strength the paper gives them. Cautious wording in the paper stays cautious in the abstract, sample limits stated in the paper stay stated or stay respected, and no claim appears only in the abstract.
8. Use the checker below for the mechanical checks. Save it as abstract_check.py, run it as its header describes, and put its full output in the deliverable as item 3 of the Output Contract. Report numbers from its output, not from memory of the draft.

### Abstract check (abstract_check.py)

Run: `python3 abstract_check.py --make-fixture fixture` builds the worked fixture in a folder named fixture, holding a paper.txt file and an abstract.txt file. Then run: `python3 abstract_check.py fixture/abstract.txt fixture/paper.txt` to reproduce the output below. Run it on real work with `python3 abstract_check.py ABSTRACT_FILE PAPER_FILE` and add `--budget-min N --budget-max N` when the venue limit differs from the default range.

Expected output for the fixture run:

```text
abstract_file: fixture/abstract.txt
paper_file: fixture/paper.txt
abstract_word_count: 42
budget_min: 150
budget_max: 250
budget_status: below
citations_found: 1
CITATION marker=(Smith, 2020)
numbers_total: 2
numbers_missing_from_paper: 1
NUMBER_MISSING value=87
move_method_signal: missing
move_result_signal: present
verdict: REVIEW
```

The fixture is built to show each checker result once: the fixture abstract is short, at 42 words against the 150 to 250 default budget, so its budget status is below. It holds one citation marker, (Smith, 2020), and two numbers, of which one, 87, does not appear in the fixture paper, while 2020 does appear in the paper. It holds result language, so the result signal is present, and no method term from the check list, so the method signal is missing, which gives a verdict of REVIEW.

abstract_check.py (uses only the Python standard library). Save this code as abstract_check.py:

```python
#!/usr/bin/env python3
"""Check an academic abstract against its paper.

Usage:
  python3 abstract_check.py --make-fixture DIR
  python3 abstract_check.py ABSTRACT_FILE PAPER_FILE [--budget-min N --budget-max N]

The default budget is 150 to 250 words. Pass --budget-min and
--budget-max to use the limit for a specific target venue.

Checks:
  word count against the budget
  citation markers in the abstract
  numbers in the abstract that do not appear in the paper
  move signals for method language and result language

Citation markers checked:
  bracket markers with a digit, such as [1]
  parenthetical markers with a four digit year, such as (Smith, 2020)
  doi markers, such as doi:10.1000/example

Numbers are tokens matching digits with an optional decimal part,
such as 42 or 87.5. Comparison is by exact token text after commas
are removed.

Move signals are simple keyword checks, labeled as signals and
not proof. Method signal terms: method, recruited, assigned,
measured, survey, interview, randomi, participant, sample, trial.
Result signal terms: result, found, showed, scored, improved,
increased, decreased, reduced, fell, difference, percent,
compared, higher, lower. A signal is present when at least one
term appears in the abstract as a substring of the lowercased text.

Output prints the word count and budget status, each citation
marker found, each missing number, both move signals, and a
verdict. Exit code is 0 when both files can be read, 1 when a
file cannot be read, and 2 for bad arguments. Standard library
only.
"""
import os
import re
import sys

NUMBER_RE = re.compile(r"\d+(?:,\d{3})*(?:\.\d+)?")
CITATION_PATTERNS = [
    re.compile(r"\[[^\]]*\d[^\]]*\]"),
    re.compile(r"\([^)]*\b(?:18|19|20)\d{2}[a-z]?\b[^)]*\)"),
    re.compile(r"doi:\S+", re.IGNORECASE),
]
METHOD_TERMS = [
    "method",
    "recruited",
    "assigned",
    "measured",
    "survey",
    "interview",
    "randomi",
    "participant",
    "sample",
    "trial",
]
RESULT_TERMS = [
    "result",
    "found",
    "showed",
    "scored",
    "improved",
    "increased",
    "decreased",
    "reduced",
    "fell",
    "difference",
    "percent",
    "compared",
    "higher",
    "lower",
]


def find_citations(text):
    found = []
    for pattern in CITATION_PATTERNS:
        for match in pattern.finditer(text):
            found.append((match.start(), match.group(0)))
    found.sort(key=lambda item: (item[0], item[1]))
    seen = set()
    ordered = []
    for pos, marker in found:
        key = (pos, marker)
        if key not in seen:
            seen.add(key)
            ordered.append(marker)
    return ordered


def find_numbers(text):
    numbers = []
    seen = set()
    for match in NUMBER_RE.finditer(text):
        token = match.group(0).replace(",", "")
        if token not in seen:
            seen.add(token)
            numbers.append(token)
    return numbers


def check(abstract_path, paper_path, budget_min, budget_max):
    if not os.path.isfile(abstract_path):
        print(f"error: abstract file not found: {abstract_path}")
        return 1
    if not os.path.isfile(paper_path):
        print(f"error: paper file not found: {paper_path}")
        return 1
    with open(abstract_path, "r", encoding="utf-8", errors="replace") as fh:
        abstract = fh.read()
    with open(paper_path, "r", encoding="utf-8", errors="replace") as fh:
        paper = fh.read()
    word_count = len(abstract.split())
    if word_count < budget_min:
        budget_status = "below"
    elif word_count > budget_max:
        budget_status = "above"
    else:
        budget_status = "within"
    citations = find_citations(abstract)
    abstract_numbers = find_numbers(abstract)
    paper_numbers = set(find_numbers(paper))
    missing_numbers = [n for n in abstract_numbers if n not in paper_numbers]
    lower = abstract.lower()
    method_signal = "present" if any(term in lower for term in METHOD_TERMS) else "missing"
    result_signal = "present" if any(term in lower for term in RESULT_TERMS) else "missing"
    print(f"abstract_file: {abstract_path}")
    print(f"paper_file: {paper_path}")
    print(f"abstract_word_count: {word_count}")
    print(f"budget_min: {budget_min}")
    print(f"budget_max: {budget_max}")
    print(f"budget_status: {budget_status}")
    print(f"citations_found: {len(citations)}")
    for marker in citations:
        print(f"CITATION marker={marker}")
    print(f"numbers_total: {len(abstract_numbers)}")
    print(f"numbers_missing_from_paper: {len(missing_numbers)}")
    for number in missing_numbers:
        print(f"NUMBER_MISSING value={number}")
    print(f"move_method_signal: {method_signal}")
    print(f"move_result_signal: {result_signal}")
    ok = (
        budget_status == "within"
        and len(citations) == 0
        and len(missing_numbers) == 0
        and method_signal == "present"
        and result_signal == "present"
    )
    print(f"verdict: {'PASS' if ok else 'REVIEW'}")
    return 0


def make_fixture(base):
    os.makedirs(base, exist_ok=True)
    paper = (
        "Morning light and alertness in office workers\n"
        "Data were collected in 2020 from two sites.\n"
        "Background. Low alertness in the morning is a common problem in office settings.\n"
        "Method. We recruited 120 office workers and assigned them to bright light or dim light for 8 days. Alertness was measured with a validated scale each morning.\n"
        "Results. The bright light group scored 42 points on average compared with 31 points in the dim light group, a difference of 11 points. Response time fell by 15 percent in the bright light group.\n"
        "Conclusion. Morning bright light improved alertness in this sample of office workers.\n"
        "Keywords: alertness, bright light, office workers\n"
    )
    abstract = (
        "Low morning alertness affects office work. This study tested bright light. The bright light group improved alertness by 87 percent and scored higher than controls (Smith, 2020). Morning bright light may help office workers stay alert.\n"
        "Keywords: alertness, bright light, office workers\n"
    )
    paper_path = os.path.join(base, "paper.txt")
    abstract_path = os.path.join(base, "abstract.txt")
    with open(paper_path, "w", encoding="utf-8") as fh:
        fh.write(paper)
    with open(abstract_path, "w", encoding="utf-8") as fh:
        fh.write(abstract)
    print(f"fixture_paper: {paper_path}")
    print(f"fixture_abstract: {abstract_path}")
    return 0


def main():
    args = sys.argv[1:]
    if len(args) == 2 and args[0] == "--make-fixture":
        return make_fixture(args[1])
    budget_min = 150
    budget_max = 250
    positional = []
    i = 0
    while i < len(args):
        if args[i] == "--budget-min" and i + 1 < len(args):
            try:
                budget_min = int(args[i + 1])
            except ValueError:
                print("error: --budget-min needs an integer")
                return 2
            i += 2
        elif args[i] == "--budget-max" and i + 1 < len(args):
            try:
                budget_max = int(args[i + 1])
            except ValueError:
                print("error: --budget-max needs an integer")
                return 2
            i += 2
        else:
            positional.append(args[i])
            i += 1
    if len(positional) != 2:
        print("usage: abstract_check.py ABSTRACT_FILE PAPER_FILE [--budget-min N --budget-max N]")
        print("       abstract_check.py --make-fixture DIR")
        return 2
    return check(positional[0], positional[1], budget_min, budget_max)


if __name__ == "__main__":
    raise SystemExit(main())
```
