Skip to content
Back to skills

Ingest Decision Letter

ASecurity

Ingest a journal decision letter and reviewer comments into a structured remark ledger, archive the sources, and run a coverage check that maps every remark to a ticket. Turns Revise-and-Resubmit intake into one deterministic pass instead of a manual re-count.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
toolsgoshell

Security analysis

A100/100

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

Scanned October 19, 2026

npx -y skills add MinhHaDuong/ImperialDragonHarness --skill ingest-decision-letter --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ingest Decision Letter?

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

Security grade badge for Ingest Decision Letter
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/minhhaduong-ingest-decision-letter/badge)](https://www.skillsdirectory.com/skills/minhhaduong-ingest-decision-letter)

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: ingest-decision-letter
description: "Ingest a journal decision letter and reviewer comments into a structured remark ledger, archive the sources, and run a coverage check that maps every remark to a ticket. Turns Revise-and-Resubmit intake into one deterministic pass instead of a manual re-count."
user-invocable: true
disable-model-invocation: false
argument-hint: "<decision-letter> <reviewer-comments>... [--release-dir <paper-repo>/release/<date>]"
---

# Ingest decision letter $ARGUMENTS

For helper commands, set `IDH_ROOT="$(cd -P "$(dirname "<loaded-SKILL.md>")/../.." && pwd -P)"` in the same shell call. Replace `<loaded-SKILL.md>` with the absolute path the runtime supplied for this skill. This follows a projected skill symlink to the canonical checkout; do not derive the helper root from the project cwd.

Take a journal's **Revise-and-Resubmit** decision letter plus each reviewer's
comments, archive them where they will not be lost, parse them into a structured
**remark ledger**, and produce a **coverage check** that maps every remark to the
ticket(s) addressing it — flagging uncovered remarks and orphan tickets. This is
the *inverse* of `external-peer-review` / `review-pr-prose`: those review **our**
manuscript; this ingests **the journal's** review of it.

The bundled helper is `"$IDH_ROOT/skills/ingest-decision-letter/ingest_letter.py"`.
It is pure I/O — it never calls a model. You (the model) read the extracted text
and assign categories and ticket mappings; the script does the deterministic,
re-runnable work: extract, archive, segment, dedupe, coverage.

## Sources

Accept the letter and comments as **file paths** — a text file or a PDF (the
helper extracts PDF text via `pdftotext`). The comments may also arrive as an
**email thread**: if the project exposes a mail-reading capability, fetch the
thread and save its text to a file first, then proceed exactly as for a text
file. Do not build the intake around any one mail tool — the archived text file
is the interface.

Once located, **archive first** (next step): the 2026-06-18 intake wasted a whole
search re-hunting comments that had already been filed. The archive is the
single source of truth; never send the author back to a mailbox to re-find them.

## Steps

1. **Locate the sources.** Resolve each path argument. If a source is missing and
   it lived in an email thread, fetch the thread with whatever mail capability the
   project offers and write it to a text file. If you cannot find a source, stop
   and ask the author for the path — do not guess.

2. **Archive to `release/<date>/`.** Paper repos keep an immutable, append-only
   `release/<date description>/` per submission; editorial replies file into the
   release subdir they answer, as tracked text. Copy the sources there:
   ```
   "$IDH_ROOT/skills/ingest-decision-letter/ingest_letter.py" archive \
       decision.pdf reviewer1.txt reviewer2.txt \
       --into <paper-repo>/release/<date>/
   ```
   PDFs are copied verbatim and a `.txt` sidecar of their text is written beside
   them, so the archive stays greppable. A `manifest.json` records what landed.
   Commit the archived text in the paper repo (it is durable tracked state).

3. **Segment each reviewer into a candidate ledger.** Run `segment` once per
   reviewer — it splits the comments into candidate remarks with **stable ids**
   (`R1-01`, `R1-02`, …) and source line locations. Re-running on the same input
   yields the same ids, so the ledger is a stable anchor.
   ```
   "$IDH_ROOT/skills/ingest-decision-letter/ingest_letter.py" segment \
       reviewer1.txt --reviewer R1 >  ledger.jsonl
   "$IDH_ROOT/skills/ingest-decision-letter/ingest_letter.py" segment \
       reviewer2.txt --reviewer R2 >> ledger.jsonl
   ```
   The segmenter is a deterministic first pass (it splits on enumeration markers,
   or on paragraphs when the reviewer did not number anything). **Then read the
   extracted text yourself** and refine each record: set `category` (framing /
   method / data / literature / typo / …), fix any remark the segmenter split or
   merged wrongly, and keep the `text` verbatim. This is the one judgment step;
   everything around it is mechanical.

4. **Dedupe atomic-vs-remark.** A reviewer's numbered points often restate one
   underlying remark (the 2026-06-18 letter reconciled 60 atomic comments down to
   56 remarks). `dedupe` folds duplicates and any record you tagged with
   `atomic_of` into its parent, so the distinct-remark count is deterministic:
   ```
   "$IDH_ROOT/skills/ingest-decision-letter/ingest_letter.py" dedupe \
       ledger.jsonl > ledger.dedup.jsonl
   ```
   Distinct remarks are the records whose `atomic_of` is null; folded atomics
   inherit their parent's coverage.

5. **Create tickets, then map remarks to them.** Group the distinct remarks into
   thematic tickets (one theme per ticket). Record the mapping **in the ledger**:
   set each remark's `tickets` field to the list of ticket ids that address it.
   Leave it `[]` for anything not yet ticketed — the coverage check will catch it.

6. **Coverage check — one deterministic pass.** Cross-check the ledger against the
   tickets that exist for this round:
   ```
   "$IDH_ROOT/skills/ingest-decision-letter/ingest_letter.py" coverage \
       ledger.dedup.jsonl --tickets-dir tickets/
   ```
   The report lists, and the command exits non-zero on, any of:
   - **uncovered_remarks** — a remark no ticket addresses.
   - **orphan_tickets** — a ticket in the universe that addresses no remark.
   - **unknown_ticket_refs** — a ticket a remark points at that does not exist.

   Iterate — add tickets, fix mappings — until the report is clean. That clean
   pass replaces the two-or-three manual re-counts the old intake needed.

## Ledger schema

One JSON object per line (JSONL):

| Field | Meaning |
|-------|---------|
| `id` | stable `<reviewer>-<NN>`, document order |
| `reviewer` | reviewer label, e.g. `R1` |
| `category` | you assign: framing / method / data / literature / typo / … |
| `text` | verbatim remark text |
| `source` | `<file>:<line>` where the remark starts |
| `tickets` | list of ticket ids addressing this remark (`[]` = uncovered) |
| `atomic_of` | parent remark id when this folds into another (`null` = distinct) |

## Notes

- **Pure I/O helper.** The script never calls a model; the one judgment step
  (categories, mapping, fixing a mis-split remark) is yours.
- **Tool-agnostic.** The email-thread path is a capability, not a fixed tool —
  the archived text file is the interface, so any mail reader works.
- **Stable ids** make the ledger a durable anchor: re-segmenting the same source
  does not renumber remarks, so ticket references stay valid.
- Companion skill `track-changes-pdf` (tracker 0265) closes the loop by rendering
  a revision-marked PDF grouped by ticket; it lands separately.

Files in this skill

  • SKILL.md6.8 KB
  • ingest_letter.py16.7 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.