- register --live adds the Institute's cover edition beside the published
PDF in the same push. A cover it cannot make is reported in the log, the
state and the curator ping, and the page still publishes.
- The cover tool handles papers registered under the Institute prefix as
well as earlier records. The cover names the journal, volume, article
number, dates and licence with the page's own citation and matches the
manuscript's page size, and the tool checks the result before replacing
anything.
- Sponsor logo uploads are held for the curator's approval; --apply reviews
a held upload and publishes it.
- Citation verification treats a reference cited by URL as a web source, not
a registry match. Only an identity-confirmed reference can ground an
integrity finding, and an empty citation-results block tells the panel
that nothing was checked.
- Workers AI runs as an OpenAI-compatible panel provider, metered against its
free daily allocation, with a usage guard per provider. The panel roster
and its fallback routes are updated, and the example config matches the
live roster.
- A replay harness runs real submissions through intake up to the panel and
grades each stage against an answer key.
- Keywords reach the public record through every registry writer.
- Curator notifications go out without link previews, and test fixtures use
Crossref's test prefix.
- Decision letters name the removed references list by its size and name the
earlier submission a revision answers. The HTML part keeps the templates'
line breaks, and revise letters describe what a resubmission's revi…
20 days ago
Author mail: the receipt no longer calls the audit log tamper-evident; the Zenodo-community comments send a disputed point to help@ instead of inviting a cover note or a reply to the thread
No author names or real submission events in code, comments, the panel prompt or test fixtures: synthetic names and a synthetic code package; comments describe a submission by month, not by ID
Before the next submission: a revised version links only under the same verified ORCID; a DOI is dead only when doi.org has no such DOI (an outage or another registration agency is "unchecked", never a finding); the authors' surnames are blinded wherever the panel reads them; the per-reference citation lines sit inside the untrusted submission block and the RQC evidence block is declared untrusted; "unanimous" names the reviewers' shared vote; the code digest fetches at most 60 files in 180 s; a forced re-draft keeps the first decision time and the audit log records a draft, never a send.
Decision letter: the blind-review disclosure lists what was removed, item by item, and says what stayed visible to the panel; a failed preprocessing step is disclosed without naming the tool. Public Review Quality Control shows only the dimensions the audit scored.
New dimension evidence_use (public): the RQC prompt now carries an
EVIDENCE_SUPPLIED block built from the citation verification JSON (the
counts and every DOI MISMATCH / DOI DEAD / UNVERIFIABLE / text-matched
line) and the code package digest (the shipped code's definitions and the
lines defining the paper's constructs), blinded with the panel's
compaction spans. A slot that says "citations verified" against mismatch
or dead lines, or "implements the measure as described" when the digest
shows another definition, scores 1 and trips the flag.
The scale is re-anchored: 5 exemplary, 4 clean, 3 adequate with gaps, 2 a
defect the curator must see, 1 fatal. Before, 83 of the 90 scored slots on
record were 5s and no audit had ever flagged.
Calibrated against earlier review records (written to an audit folder, never
the live record): reviews that had called dead or mismatched references
clean now score low on evidence_use and trip the flag.
Two defects found by the calibration and fixed her…
Review report: a revision names the submission it revises, never the previous decision
Earlier rounds are not published (the curator, 2026-10-01): only the accepted
round's review record is public, and its header must not carry the
earlier decision. The previous decision stays in the curator escalation.
test_consents_at_submission: define rd0 before the no-revision report check (the suite was red at fb51504)
The "revised version" answer now does work: the new paper's state.json
carries revision_of and the previous paper's gains superseded_by /
superseded_at (an audit event "superseded" on the old id, and the
submission_received event carries resubmission_of); the public state
endpoint exposes both ids (never a decision), so the old status page can
say a revised version was submitted; the review report's front matter and
header carry "Revision of: <id> (previous decision: <d>)"; stats.py counts
unique manuscripts (reviews that are not revisions) beside total reviews,
so a paper revised twice is one manuscript, not three.
What it still does not do, on purpose, pending the curator's word: publish
the earlier round's report and findings beside an accepted revision.
Revised version: the previous submission ID travels with a resubmission; the panel stays fresh
Both forms ask "Is this a revised version of a paper ICSAC returned?";
Yes reveals one field, the previous submission ID (the curator's pick,
2026-09-30, after the fuller block with an author note was reverted as
too much). The intake server stores it as `resubmission` {of,
previous_found, previous_decision}: the ID's shape is validated, whether
the previous paper exists and what was decided is looked up for the
curator and never enforced. The worker carries it into review_data for
the curator escalation only ("REVISED VERSION of X (previous decision
Y). Compare against that paper's curator_findings.md"); the panel prompt
never sees it, so every round is a fresh panel as the letter promises.
The revise letters tell the author to answer Yes and give this ID; the
new version gets its own ID; a disputed finding goes to help@ with the
ID and a finding we got wrong is withdrawn.
test_consents_at_submission.py section 4 covers the question, the
lookup, the escalation, the fresh prompt and …
21 days ago
Revise letter: the new version goes through the same form and gets a new ID, nothing else; a disputed finding goes to help@ with the ID, and a finding we got wrong is withdrawn. No cover note in the abstract field (that field is the deposited abstract).
Revert "Revised versions: the previous submission ID and the author's note travel with a resubmission; the revise letter says so and invites disagreement"
A paper ICSAC returned for revision comes back through the regular flow
and gets a new submission ID. Both forms now carry an optional "Revised
version" block: the previous ID and a point-by-point note on what changed
and what the author disputes. The intake server stores it as
`resubmission` (ID shape validated; whether the previous paper exists and
its decision are recorded for the curator, never enforced). The worker
carries it into review_data; the panel reads the note inside the
submission block, blinded like the abstract; the curator escalation names
the previous paper, its decision and the note, and points at that paper's
curator_findings.md.
The revise letters no longer tell the author to put a cover note in the
abstract field (the abstract is deposited on acceptance). They say the new
version gets a new ID, where the note goes, that it is not published, and
that a finding the author thinks mistaken should be disputed in the note
and left unchanged in the paper: the curation t…
Salutation: a name typed all in lower case is capitalised (ada lovelace -> Ada Lovelace); particles stay lower unless they open the name
Both submission forms now carry, before the Turnstile: a required
acknowledgement of how ICSAC reviews and publishes (stored with its
wording version and time as process_ack / process_ack_version /
process_ack_at); a preview of the acceptance email; the five promotion
and print exclusions as optional unticked boxes, stored as
exclusions_at_submission, pre-ticked on the response page and seeded into
the paper's state when the author window opens so a lapsed window still
honours them (the author's response replaces them); and an optional,
unticked newsletter box, separate from the required ones, stored with its
time and wording version.
A post that carries form_version must carry the acknowledgement; older
forms are accepted unchanged. Unknown exclusion ids are refused.
intake/newsletter.py: the list is one append-only JSONL of subscribe and
unsubscribe events under the submissions root (in the nightly backup),
folded to the current list; written only on the production path, never
from…
Citation identity, code package digest, rubric depth, and the revise letter
A citation that carries a DOI is now judged by that DOI: it is resolved on
Crossref, then DataCite, and the record title is compared with the cited
title (authors and year when no title was cited). A DOI that resolves
nowhere is DOI DEAD; one that resolves to another work is DOI MISMATCH;
neither is ever verified, whatever a title or author-year search finds
afterwards. The search only names the probable intended record for the
panel and the letter. An author-year match with a different title is no
longer verified when the citation has a title. The verification report
carries an evidence level per line (confirmed / matched / mismatch /
dead / unverifiable) and no longer calls itself ground truth; the panel
prompt scores identifier disagreement under citation integrity. The
cited title survives verification as cited_title. A confirmed DOI that
CiteStamp does not know is appended to reviews/citestamp_coverage_gaps.jsonl.
code_digest.py fetches the author's declared Zenodo or GitHub arch…
Panel quorum counts two models served by the same HF upstream as two reviewers, not one; OpenRouter reviews get room to finish reasoning before the JSON
A served HF review is labelled hf:<upstream>:<org>/<model>; the duplicate-seat check read the upstream as the model, so every HF-served reviewer was "deepinfra" and a valid second one was discarded. OpenRouter max_tokens 4000 -> 10000: models that reason in content ran out before the JSON on a long paper.
22 days ago
register --live accepts the Institute's own Zenodo community inclusion for the archive copy it publishes; never fatal, reported in the curator ping, retried on a re-run
Publish gate: the /publications registry, public review and push refuse without the curator's approval; register --live carries it, every other path saves the entry as ready to publish and tells the curator once; no author is told a held paper is live
Live registration never records a skipped landing page as pushed: it stops with the resume instruction and a re-run resumes at the page step; register-doi.sh names the website checkout; the code/data suite tells founding papers from intake papers
Zenodo archive copy of an ICSAC-registered work takes the type of its Crossref record: a Persistence article is a journal article in Persistence with its volume, whatever the form's resource type
Crossref journal title DOI: journal_metadata carries doi_data when CROSSREF_JOURNAL_DOI is set, as Crossref requires of a journal without an ISSN; unset leaves the deposit unchanged
Crossref deposit links the author's code and data archive: isSupplementedBy, as a DOI for a doi.org link and a URI otherwise, beside hasPreprint in the relations program; regression suite validates every variant against the 5.4.0 schema
Submit signature v2: the signature covers the verified ORCID, name and test-tier headers as well as the body, so a signed request cannot be replayed under another identity or tier; the body-only form is refused on submit unless the deploy-window switch is on; smoke scripts sign v2; regression suite
Reviewer self-identification screen: model or seat named in panel or RQC prose is rewritten to neutral wording, or the sentence is dropped and the curator is told; quotations from the paper pass; regression suite
accept.md, scope-reject.md, revise-and-resubmit(-comment).md and the
community invitation said human curator(s); the invitation also said
"We are not a journal" and "reviews available on request", and accept.md
offered the report on request although the record publishes it.
intake/scripts/test_audit_20260929.py: 37 offline checks for this audit.
Pipeline guards: no reprocessing of decided papers, decisions only on papers awaiting one, register --live needs a delivered notice, retries on registry outages, atomic state writes, honest attachment lines
- submission_worker refuses a queue trigger for a paper with a decision
on record or in a completed state (ICSAC_REPROCESS=1 overrides); a
Zenodo or arXiv transport failure is retried three times before it can
become an unresolvable verdict and an author email.
- apply_decision refuses revise/scope_reject unless the paper is
awaiting_decision or held by the code-link check (ICSAC_DECISION_FORCE=1
overrides), so no author email is drafted over a review that has not run.
- register --live refuses a paper in completed_email_failed: the author
never received the response link, so the window closed on silence
nobody could break (ICSAC_REGISTER_WITHOUT_NOTICE=1 after telling them
by hand). The author gate is asked once more right before the deposit.
- state.json is written tmp+rename everywhere (the public status endpoint
reads it).
- Decision mail names the PDFs that are attached; the fixed "Two PDFs are
attached" line promised the RQC audit even when it was not produced…
Intake hardening: one value per identity field, bounded lists, a byte ceiling on arXiv downloads, text-only substitutions in mail, sponsor writes need a live subscription
- A multipart body with two orcid (or name, email) fields passed the edge
check on the first value and was stored under the last; both parsers
now refuse a repeated identity field.
- creators and related_identifiers are capped at 50 entries.
- download_arxiv_pdf had no size limit; it now shares the Zenodo ceiling
(INTAKE_MAX_PDF_BYTES, 100 MB by default) and removes a partial file.
- The HTML part of every mail renders a substituted < as text; the
templates carry no raw HTML, so only author-supplied values could have
injected markup.
- A paid checkout session outlives its subscription; sponsor listing
changes now need status active/trialing and a current period.
- httpx is declared (sponsor_logo imports it); wrap-paper-pdf.py takes the
website checkout from ICSAC_WEBSITE_REPO only.
arXiv within its limits: metadata comes from DataCite first (title, authors, abstract, date, licence, and the journal DOI once published), so arXiv's API is not touched; every remaining API call goes through one door (one connection, one request every three seconds for the whole host, Retry-After honoured, a ten-minute cool-off after a refusal or stall so a bad hour cannot stretch a panel run); the citation title search waits its turn or is skipped; the DOI route refuses a preprint already published in a journal, as the upload route does
DOI route: the author chooses the published article's licence (CC BY 4.0, CC BY-SA 4.0 or CC0), validated before anything is written; the worker keeps the choice when it resolves the preprint and records the preprint's own licence beside it (arXiv reports none); the curator summary shows both; a record without a choice behaves as before
Preprints from any server: the upload form takes a preprint DOI, checked against Crossref and DataCite when submitted (a published article, a preprint already published, or a DOI that does not exist is refused; an unreachable registry fails open and the curation team is told), and the Persistence DOI is linked to it; the DOI route sends other servers to the upload form with the DOI; the exclusivity confirmation is stored on both routes (it never was); the acceptance email says it only when it was confirmed
DOI route: an accepted paper submitted by its preprint DOI becomes a Persistence article with its own DOI under the Institute prefix, linked to the preprint by a hasPreprint relation; it gets the author response window, the site hosts the version of record at registration, and the emails name the preprint instead of claiming no other DOI
Stats count every review on record: the published copies of the reviews from before the public flip, the new score-table heading and the old dimension label; a record in both places counts once
The curation team decides and hears appeals: README note to authors, the legacy acceptance comments and the RQC status line; the intake README lists every field the form now collects
Audit 2026-09-28 (evening): a late author response is never overwritten by the window check, an accept waits for a panel report, a review of a paper that studies models passes the redaction gate, a data sentence does not take back a code claim, the stats snapshot never shrinks
A paper that says it has code or data must link it: the submit form asks where, a paper with no link anywhere is held for revise and resubmit before the panel, and the published page shows the author's link
Recording a choice on the response page now requires an ORCID session
(verified by the site's proxy and signed into the body) whose iD matches the
one the paper was submitted with; test-tier records accept any whitelisted
test iD, since they store a tier token. The page view carries the submitter's
iD so the page can enable the buttons for the right person. The acceptance
email says so in one sentence. The panel report and RQC PDFs open every
reviewer block and no longer tell the reader to expand rows.
Panel report and RQC PDFs carry the Institute letterhead, the document kind, the submission id, the review date and page numbers