diff --git a/reporting-guideline-compliance-assistant/README.md b/reporting-guideline-compliance-assistant/README.md
new file mode 100644
index 00000000..16102d20
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/README.md
@@ -0,0 +1,23 @@
+# Reporting Guideline Compliance Assistant
+
+This module is a focused AI peer-review aid for issue #13. It checks synthetic manuscript packets against reporting-guideline readiness rules for CONSORT, PRISMA, STROBE, and cross-guideline submission hygiene, then emits reviewer actions and citation recommendations.
+
+## Three-Step Setup
+
+1. `cd reporting-guideline-compliance-assistant`
+2. `npm test`
+3. `npm run demo`
+
+## What It Produces
+
+- `reports/reporting-guideline-packet.json`: deterministic machine-readable review packet
+- `reports/reviewer-packet.md`: structured reviewer-ready Markdown
+- `reports/summary.svg`: visual readiness summary
+- `reports/demo-script.txt`: short demo walkthrough
+
+## Requirement Mapping
+
+- AI peer review aid: flags missing reporting-guideline details before submission.
+- AI citation tool: recommends the relevant CONSORT, PRISMA, or STROBE citation when a checklist gap is found.
+- Paper summarizer: emits abstract, executive, and layperson summaries of guideline readiness.
+- Safety: uses synthetic data only, no external APIs, no credentials, and no private manuscripts.
diff --git a/reporting-guideline-compliance-assistant/demo.js b/reporting-guideline-compliance-assistant/demo.js
new file mode 100644
index 00000000..3977d69f
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/demo.js
@@ -0,0 +1,36 @@
+import { mkdir, writeFile } from "node:fs/promises"
+import { manuscripts } from "./sample-data.js"
+import {
+ analyzeBatch,
+ renderMarkdownReport,
+ renderSvgSummary,
+} from "./index.js"
+
+const reportDir = new URL("./reports/", import.meta.url)
+await mkdir(reportDir, { recursive: true })
+
+const batch = analyzeBatch(manuscripts)
+const markdown = renderMarkdownReport(batch)
+const svg = renderSvgSummary(batch)
+const script = [
+ "Reporting Guideline Compliance Assistant demo",
+ "",
+ "1. Load three synthetic manuscripts: clinical trial, systematic review, observational cohort.",
+ "2. Match each manuscript to CONSORT, PRISMA, STROBE, and cross-guideline checks.",
+ "3. Emit reviewer actions, readiness scores, and guideline citation recommendations.",
+ "",
+ `Average readiness score: ${batch.averageScore}/100`,
+ `Ready manuscripts: ${batch.readyCount}/${batch.packets.length}`,
+ "",
+ ...batch.packets.map(
+ (packet) =>
+ `${packet.manuscriptId}: ${packet.readiness} (${packet.readinessScore}/100)`
+ ),
+].join("\n")
+
+await writeFile(new URL("reporting-guideline-packet.json", reportDir), `${JSON.stringify(batch, null, 2)}\n`)
+await writeFile(new URL("reviewer-packet.md", reportDir), markdown)
+await writeFile(new URL("summary.svg", reportDir), svg)
+await writeFile(new URL("demo-script.txt", reportDir), `${script}\n`)
+
+console.log(script)
diff --git a/reporting-guideline-compliance-assistant/index.js b/reporting-guideline-compliance-assistant/index.js
new file mode 100644
index 00000000..69257f43
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/index.js
@@ -0,0 +1,266 @@
+import { citationLibrary } from "./sample-data.js"
+
+const RULES = [
+ {
+ id: "consort-allocation",
+ guideline: "CONSORT",
+ appliesTo: ["clinical-trial"],
+ section: "methods",
+ severity: "high",
+ terms: ["allocation", "conceal"],
+ message: "Describe allocation concealment so readers can assess selection-bias risk.",
+ },
+ {
+ id: "consort-flow",
+ guideline: "CONSORT",
+ appliesTo: ["clinical-trial"],
+ section: "results",
+ severity: "medium",
+ terms: ["flow diagram", "participant flow", "screened", "excluded"],
+ message: "Add participant flow counts or a flow diagram.",
+ },
+ {
+ id: "prisma-search",
+ guideline: "PRISMA",
+ appliesTo: ["systematic-review"],
+ section: "methods",
+ severity: "high",
+ terms: ["database", "search", "searched", "query", "date"],
+ message: "Report complete search sources, dates, and query details.",
+ },
+ {
+ id: "prisma-screening",
+ guideline: "PRISMA",
+ appliesTo: ["systematic-review"],
+ section: "results",
+ severity: "high",
+ terms: ["screened", "excluded", "included", "records"],
+ message: "Report screening counts for records identified, excluded, and included.",
+ },
+ {
+ id: "strobe-setting",
+ guideline: "STROBE",
+ appliesTo: ["observational"],
+ section: "methods",
+ severity: "medium",
+ terms: ["setting", "clinic", "hospital", "cohort", "eligibility"],
+ message: "Describe setting, location, eligibility, and relevant dates.",
+ },
+ {
+ id: "strobe-confounders",
+ guideline: "STROBE",
+ appliesTo: ["observational"],
+ section: "methods",
+ severity: "high",
+ terms: ["confound", "adjusted", "covariate", "baseline"],
+ message: "Define confounders and adjustment variables before interpreting associations.",
+ },
+ {
+ id: "registration",
+ guideline: "cross-guideline",
+ appliesTo: ["clinical-trial", "systematic-review"],
+ section: "methods",
+ severity: "high",
+ terms: ["registry", "registered", "nct", "prospero"],
+ message: "Add a registry identifier or explain why registration was not applicable.",
+ },
+ {
+ id: "data-availability",
+ guideline: "cross-guideline",
+ appliesTo: ["clinical-trial", "systematic-review", "observational"],
+ section: "discussion",
+ severity: "medium",
+ terms: ["data availability", "code availability", "repository", "supplement"],
+ message: "Add data and code availability language before submission.",
+ },
+]
+
+const severityWeight = { high: 24, medium: 14, low: 8 }
+
+const normalize = (value = "") => value.toLowerCase().replace(/\s+/g, " ")
+
+const getSection = (manuscript, section) =>
+ normalize(manuscript.sections?.[section] ?? "")
+
+const appliesTo = (rule, manuscript) =>
+ rule.appliesTo.includes(normalize(manuscript.studyDesign))
+
+const termHits = (text, terms) =>
+ terms.filter((term) => text.includes(normalize(term)))
+
+const findCitation = (guideline) =>
+ citationLibrary.find((citation) => citation.guideline === guideline) ??
+ citationLibrary.find((citation) => citation.guideline === "STROBE")
+
+export function formatCitation(citation, style = "APA") {
+ if (style === "Nature") {
+ return `${citation.authors}. ${citation.title}. (${citation.year}).`
+ }
+
+ return `${citation.authors} (${citation.year}). ${citation.title}. ${citation.url}`
+}
+
+export function analyzeReportingGuidelineCompliance(manuscript) {
+ const findings = RULES.filter((rule) => appliesTo(rule, manuscript)).map(
+ (rule) => {
+ const text = getSection(manuscript, rule.section)
+ const hits = termHits(text, rule.terms)
+ const passed = hits.length > 0
+ const citation =
+ rule.guideline === "cross-guideline" ? null : findCitation(rule.guideline)
+
+ return {
+ id: rule.id,
+ guideline: rule.guideline,
+ section: rule.section,
+ severity: rule.severity,
+ status: passed ? "pass" : "fail",
+ matchedTerms: hits,
+ message: rule.message,
+ reviewerAction: passed
+ ? `Keep ${rule.section} language for ${rule.id} explicit.`
+ : rule.message,
+ citationRecommendation: citation
+ ? {
+ key: citation.key,
+ guideline: citation.guideline,
+ apa: formatCitation(citation, "APA"),
+ nature: formatCitation(citation, "Nature"),
+ }
+ : null,
+ }
+ }
+ )
+
+ const failedFindings = findings.filter((finding) => finding.status === "fail")
+ const penalty = failedFindings.reduce(
+ (total, finding) => total + severityWeight[finding.severity],
+ 0
+ )
+ const readinessScore = Math.max(0, 100 - penalty)
+
+ return {
+ manuscriptId: manuscript.id,
+ title: manuscript.title,
+ studyDesign: manuscript.studyDesign,
+ readinessScore,
+ readiness:
+ readinessScore >= 85
+ ? "ready"
+ : readinessScore >= 65
+ ? "needs-minor-revision"
+ : "needs-guideline-rework",
+ summaries: buildSummaries(manuscript, failedFindings, readinessScore),
+ findings,
+ citationRecommendations: dedupeCitations(
+ failedFindings
+ .map((finding) => finding.citationRecommendation)
+ .filter(Boolean)
+ ),
+ }
+}
+
+export function analyzeBatch(manuscripts) {
+ const packets = manuscripts.map(analyzeReportingGuidelineCompliance)
+ const averageScore = Math.round(
+ packets.reduce((total, packet) => total + packet.readinessScore, 0) /
+ packets.length
+ )
+
+ return {
+ generatedAt: new Date(0).toISOString(),
+ averageScore,
+ readyCount: packets.filter((packet) => packet.readiness === "ready").length,
+ packets,
+ }
+}
+
+function buildSummaries(manuscript, failedFindings, readinessScore) {
+ const failures = failedFindings.map((finding) => finding.id).join(", ")
+ return {
+ abstract: `${manuscript.abstract} Reporting-guideline readiness score: ${readinessScore}/100.`,
+ executive:
+ failedFindings.length === 0
+ ? "No blocking reporting-guideline gaps were detected in the synthetic review packet."
+ : `The draft needs targeted reporting updates before submission: ${failures}.`,
+ layperson:
+ failedFindings.length === 0
+ ? "The draft gives readers enough checklist detail to understand how the study was done."
+ : "The draft is missing some checklist details that help readers trust how the study was planned, analyzed, and reported.",
+ }
+}
+
+function dedupeCitations(citations) {
+ return [...new Map(citations.map((citation) => [citation.key, citation])).values()]
+}
+
+export function renderMarkdownReport(batch) {
+ const lines = [
+ "# Reporting Guideline Compliance Packet",
+ "",
+ `Average readiness score: ${batch.averageScore}/100`,
+ `Ready manuscripts: ${batch.readyCount}/${batch.packets.length}`,
+ "",
+ ]
+
+ for (const packet of batch.packets) {
+ lines.push(`## ${packet.title}`)
+ lines.push("")
+ lines.push(`- Study design: ${packet.studyDesign}`)
+ lines.push(`- Readiness: ${packet.readiness}`)
+ lines.push(`- Score: ${packet.readinessScore}/100`)
+ lines.push(`- Executive summary: ${packet.summaries.executive}`)
+ lines.push("")
+ lines.push("### Reviewer Actions")
+
+ for (const finding of packet.findings.filter((item) => item.status === "fail")) {
+ lines.push(
+ `- [${finding.severity}] ${finding.guideline}/${finding.id}: ${finding.reviewerAction}`
+ )
+ }
+
+ if (packet.citationRecommendations.length > 0) {
+ lines.push("")
+ lines.push("### Citation Recommendations")
+ for (const citation of packet.citationRecommendations) {
+ lines.push(`- ${citation.apa}`)
+ }
+ }
+
+ lines.push("")
+ }
+
+ return `${lines.join("\n").trim()}\n`
+}
+
+export function renderSvgSummary(batch) {
+ const bars = batch.packets
+ .map((packet, index) => {
+ const y = 104 + index * 54
+ const width = Math.max(18, Math.round(packet.readinessScore * 4.6))
+ const color =
+ packet.readinessScore >= 85
+ ? "#15803d"
+ : packet.readinessScore >= 65
+ ? "#b45309"
+ : "#b91c1c"
+ return `${escapeXml(packet.manuscriptId)} (${packet.readinessScore})`
+ })
+ .join("")
+
+ return `
+`
+}
+
+function escapeXml(value) {
+ return String(value)
+ .replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+}
diff --git a/reporting-guideline-compliance-assistant/package.json b/reporting-guideline-compliance-assistant/package.json
new file mode 100644
index 00000000..74506009
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "reporting-guideline-compliance-assistant",
+ "version": "1.0.0",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "check": "node --check index.js && node --check sample-data.js && node --check demo.js && node --check test.js",
+ "test": "node --test test.js",
+ "demo": "node demo.js"
+ }
+}
diff --git a/reporting-guideline-compliance-assistant/reports/demo-script.txt b/reporting-guideline-compliance-assistant/reports/demo-script.txt
new file mode 100644
index 00000000..970563f2
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/reports/demo-script.txt
@@ -0,0 +1,12 @@
+Reporting Guideline Compliance Assistant demo
+
+1. Load three synthetic manuscripts: clinical trial, systematic review, observational cohort.
+2. Match each manuscript to CONSORT, PRISMA, STROBE, and cross-guideline checks.
+3. Emit reviewer actions, readiness scores, and guideline citation recommendations.
+
+Average readiness score: 54/100
+Ready manuscripts: 0/3
+
+trial-omega-sleep: needs-guideline-rework (62/100)
+review-cardio-ai: needs-guideline-rework (38/100)
+cohort-lab-glucose: needs-guideline-rework (62/100)
diff --git a/reporting-guideline-compliance-assistant/reports/reporting-guideline-packet.json b/reporting-guideline-compliance-assistant/reports/reporting-guideline-packet.json
new file mode 100644
index 00000000..fd94418d
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/reports/reporting-guideline-packet.json
@@ -0,0 +1,236 @@
+{
+ "generatedAt": "1970-01-01T00:00:00.000Z",
+ "averageScore": 54,
+ "readyCount": 0,
+ "packets": [
+ {
+ "manuscriptId": "trial-omega-sleep",
+ "title": "Omega Sleep Digital Coaching for Insomnia: A Randomized Trial",
+ "studyDesign": "clinical-trial",
+ "readinessScore": 62,
+ "readiness": "needs-guideline-rework",
+ "summaries": {
+ "abstract": "A mobile coaching intervention improved sleep scores in adults with insomnia. The manuscript reports the primary endpoint and adverse event monitoring. Reporting-guideline readiness score: 62/100.",
+ "executive": "The draft needs targeted reporting updates before submission: consort-allocation, data-availability.",
+ "layperson": "The draft is missing some checklist details that help readers trust how the study was planned, analyzed, and reported."
+ },
+ "findings": [
+ {
+ "id": "consort-allocation",
+ "guideline": "CONSORT",
+ "section": "methods",
+ "severity": "high",
+ "status": "fail",
+ "matchedTerms": [],
+ "message": "Describe allocation concealment so readers can assess selection-bias risk.",
+ "reviewerAction": "Describe allocation concealment so readers can assess selection-bias risk.",
+ "citationRecommendation": {
+ "key": "consort-2010",
+ "guideline": "CONSORT",
+ "apa": "Schulz KF, Altman DG, Moher D (2010). CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials. https://www.consort-statement.org/",
+ "nature": "Schulz KF, Altman DG, Moher D. CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials. (2010)."
+ }
+ },
+ {
+ "id": "consort-flow",
+ "guideline": "CONSORT",
+ "section": "results",
+ "severity": "medium",
+ "status": "pass",
+ "matchedTerms": [
+ "flow diagram",
+ "participant flow"
+ ],
+ "message": "Add participant flow counts or a flow diagram.",
+ "reviewerAction": "Keep results language for consort-flow explicit.",
+ "citationRecommendation": {
+ "key": "consort-2010",
+ "guideline": "CONSORT",
+ "apa": "Schulz KF, Altman DG, Moher D (2010). CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials. https://www.consort-statement.org/",
+ "nature": "Schulz KF, Altman DG, Moher D. CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials. (2010)."
+ }
+ },
+ {
+ "id": "registration",
+ "guideline": "cross-guideline",
+ "section": "methods",
+ "severity": "high",
+ "status": "pass",
+ "matchedTerms": [
+ "registry",
+ "nct"
+ ],
+ "message": "Add a registry identifier or explain why registration was not applicable.",
+ "reviewerAction": "Keep methods language for registration explicit.",
+ "citationRecommendation": null
+ },
+ {
+ "id": "data-availability",
+ "guideline": "cross-guideline",
+ "section": "discussion",
+ "severity": "medium",
+ "status": "fail",
+ "matchedTerms": [],
+ "message": "Add data and code availability language before submission.",
+ "reviewerAction": "Add data and code availability language before submission.",
+ "citationRecommendation": null
+ }
+ ],
+ "citationRecommendations": [
+ {
+ "key": "consort-2010",
+ "guideline": "CONSORT",
+ "apa": "Schulz KF, Altman DG, Moher D (2010). CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials. https://www.consort-statement.org/",
+ "nature": "Schulz KF, Altman DG, Moher D. CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials. (2010)."
+ }
+ ]
+ },
+ {
+ "manuscriptId": "review-cardio-ai",
+ "title": "AI Triage for Cardiology Referrals: A Systematic Review",
+ "studyDesign": "systematic-review",
+ "readinessScore": 38,
+ "readiness": "needs-guideline-rework",
+ "summaries": {
+ "abstract": "This review summarizes diagnostic triage models for cardiology referrals and compares reported performance across clinical settings. Reporting-guideline readiness score: 38/100.",
+ "executive": "The draft needs targeted reporting updates before submission: prisma-screening, registration, data-availability.",
+ "layperson": "The draft is missing some checklist details that help readers trust how the study was planned, analyzed, and reported."
+ },
+ "findings": [
+ {
+ "id": "prisma-search",
+ "guideline": "PRISMA",
+ "section": "methods",
+ "severity": "high",
+ "status": "pass",
+ "matchedTerms": [
+ "search",
+ "searched"
+ ],
+ "message": "Report complete search sources, dates, and query details.",
+ "reviewerAction": "Keep methods language for prisma-search explicit.",
+ "citationRecommendation": {
+ "key": "prisma-2020",
+ "guideline": "PRISMA",
+ "apa": "Page MJ, McKenzie JE, Bossuyt PM (2021). PRISMA 2020 statement: an updated guideline for reporting systematic reviews. https://www.prisma-statement.org/",
+ "nature": "Page MJ, McKenzie JE, Bossuyt PM. PRISMA 2020 statement: an updated guideline for reporting systematic reviews. (2021)."
+ }
+ },
+ {
+ "id": "prisma-screening",
+ "guideline": "PRISMA",
+ "section": "results",
+ "severity": "high",
+ "status": "fail",
+ "matchedTerms": [],
+ "message": "Report screening counts for records identified, excluded, and included.",
+ "reviewerAction": "Report screening counts for records identified, excluded, and included.",
+ "citationRecommendation": {
+ "key": "prisma-2020",
+ "guideline": "PRISMA",
+ "apa": "Page MJ, McKenzie JE, Bossuyt PM (2021). PRISMA 2020 statement: an updated guideline for reporting systematic reviews. https://www.prisma-statement.org/",
+ "nature": "Page MJ, McKenzie JE, Bossuyt PM. PRISMA 2020 statement: an updated guideline for reporting systematic reviews. (2021)."
+ }
+ },
+ {
+ "id": "registration",
+ "guideline": "cross-guideline",
+ "section": "methods",
+ "severity": "high",
+ "status": "fail",
+ "matchedTerms": [],
+ "message": "Add a registry identifier or explain why registration was not applicable.",
+ "reviewerAction": "Add a registry identifier or explain why registration was not applicable.",
+ "citationRecommendation": null
+ },
+ {
+ "id": "data-availability",
+ "guideline": "cross-guideline",
+ "section": "discussion",
+ "severity": "medium",
+ "status": "fail",
+ "matchedTerms": [],
+ "message": "Add data and code availability language before submission.",
+ "reviewerAction": "Add data and code availability language before submission.",
+ "citationRecommendation": null
+ }
+ ],
+ "citationRecommendations": [
+ {
+ "key": "prisma-2020",
+ "guideline": "PRISMA",
+ "apa": "Page MJ, McKenzie JE, Bossuyt PM (2021). PRISMA 2020 statement: an updated guideline for reporting systematic reviews. https://www.prisma-statement.org/",
+ "nature": "Page MJ, McKenzie JE, Bossuyt PM. PRISMA 2020 statement: an updated guideline for reporting systematic reviews. (2021)."
+ }
+ ]
+ },
+ {
+ "manuscriptId": "cohort-lab-glucose",
+ "title": "Continuous Glucose Monitoring Alerts in Primary Care: A Cohort Study",
+ "studyDesign": "observational",
+ "readinessScore": 62,
+ "readiness": "needs-guideline-rework",
+ "summaries": {
+ "abstract": "A retrospective cohort study compared alert burden and follow-up testing after continuous glucose monitoring deployment. Reporting-guideline readiness score: 62/100.",
+ "executive": "The draft needs targeted reporting updates before submission: strobe-confounders, data-availability.",
+ "layperson": "The draft is missing some checklist details that help readers trust how the study was planned, analyzed, and reported."
+ },
+ "findings": [
+ {
+ "id": "strobe-setting",
+ "guideline": "STROBE",
+ "section": "methods",
+ "severity": "medium",
+ "status": "pass",
+ "matchedTerms": [
+ "clinic",
+ "eligibility"
+ ],
+ "message": "Describe setting, location, eligibility, and relevant dates.",
+ "reviewerAction": "Keep methods language for strobe-setting explicit.",
+ "citationRecommendation": {
+ "key": "strobe-2007",
+ "guideline": "STROBE",
+ "apa": "von Elm E, Altman DG, Egger M (2007). The STROBE statement: guidelines for reporting observational studies. https://www.strobe-statement.org/",
+ "nature": "von Elm E, Altman DG, Egger M. The STROBE statement: guidelines for reporting observational studies. (2007)."
+ }
+ },
+ {
+ "id": "strobe-confounders",
+ "guideline": "STROBE",
+ "section": "methods",
+ "severity": "high",
+ "status": "fail",
+ "matchedTerms": [],
+ "message": "Define confounders and adjustment variables before interpreting associations.",
+ "reviewerAction": "Define confounders and adjustment variables before interpreting associations.",
+ "citationRecommendation": {
+ "key": "strobe-2007",
+ "guideline": "STROBE",
+ "apa": "von Elm E, Altman DG, Egger M (2007). The STROBE statement: guidelines for reporting observational studies. https://www.strobe-statement.org/",
+ "nature": "von Elm E, Altman DG, Egger M. The STROBE statement: guidelines for reporting observational studies. (2007)."
+ }
+ },
+ {
+ "id": "data-availability",
+ "guideline": "cross-guideline",
+ "section": "discussion",
+ "severity": "medium",
+ "status": "fail",
+ "matchedTerms": [],
+ "message": "Add data and code availability language before submission.",
+ "reviewerAction": "Add data and code availability language before submission.",
+ "citationRecommendation": null
+ }
+ ],
+ "citationRecommendations": [
+ {
+ "key": "strobe-2007",
+ "guideline": "STROBE",
+ "apa": "von Elm E, Altman DG, Egger M (2007). The STROBE statement: guidelines for reporting observational studies. https://www.strobe-statement.org/",
+ "nature": "von Elm E, Altman DG, Egger M. The STROBE statement: guidelines for reporting observational studies. (2007)."
+ }
+ ]
+ }
+ ]
+}
diff --git a/reporting-guideline-compliance-assistant/reports/reviewer-packet.md b/reporting-guideline-compliance-assistant/reports/reviewer-packet.md
new file mode 100644
index 00000000..fd74a982
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/reports/reviewer-packet.md
@@ -0,0 +1,47 @@
+# Reporting Guideline Compliance Packet
+
+Average readiness score: 54/100
+Ready manuscripts: 0/3
+
+## Omega Sleep Digital Coaching for Insomnia: A Randomized Trial
+
+- Study design: clinical-trial
+- Readiness: needs-guideline-rework
+- Score: 62/100
+- Executive summary: The draft needs targeted reporting updates before submission: consort-allocation, data-availability.
+
+### Reviewer Actions
+- [high] CONSORT/consort-allocation: Describe allocation concealment so readers can assess selection-bias risk.
+- [medium] cross-guideline/data-availability: Add data and code availability language before submission.
+
+### Citation Recommendations
+- Schulz KF, Altman DG, Moher D (2010). CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials. https://www.consort-statement.org/
+
+## AI Triage for Cardiology Referrals: A Systematic Review
+
+- Study design: systematic-review
+- Readiness: needs-guideline-rework
+- Score: 38/100
+- Executive summary: The draft needs targeted reporting updates before submission: prisma-screening, registration, data-availability.
+
+### Reviewer Actions
+- [high] PRISMA/prisma-screening: Report screening counts for records identified, excluded, and included.
+- [high] cross-guideline/registration: Add a registry identifier or explain why registration was not applicable.
+- [medium] cross-guideline/data-availability: Add data and code availability language before submission.
+
+### Citation Recommendations
+- Page MJ, McKenzie JE, Bossuyt PM (2021). PRISMA 2020 statement: an updated guideline for reporting systematic reviews. https://www.prisma-statement.org/
+
+## Continuous Glucose Monitoring Alerts in Primary Care: A Cohort Study
+
+- Study design: observational
+- Readiness: needs-guideline-rework
+- Score: 62/100
+- Executive summary: The draft needs targeted reporting updates before submission: strobe-confounders, data-availability.
+
+### Reviewer Actions
+- [high] STROBE/strobe-confounders: Define confounders and adjustment variables before interpreting associations.
+- [medium] cross-guideline/data-availability: Add data and code availability language before submission.
+
+### Citation Recommendations
+- von Elm E, Altman DG, Egger M (2007). The STROBE statement: guidelines for reporting observational studies. https://www.strobe-statement.org/
diff --git a/reporting-guideline-compliance-assistant/reports/summary.svg b/reporting-guideline-compliance-assistant/reports/summary.svg
new file mode 100644
index 00000000..6c1f0b94
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/reports/summary.svg
@@ -0,0 +1,6 @@
+
diff --git a/reporting-guideline-compliance-assistant/sample-data.js b/reporting-guideline-compliance-assistant/sample-data.js
new file mode 100644
index 00000000..cb545635
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/sample-data.js
@@ -0,0 +1,77 @@
+export const citationLibrary = [
+ {
+ key: "consort-2010",
+ guideline: "CONSORT",
+ title: "CONSORT 2010 Statement: updated guidelines for reporting parallel group randomised trials",
+ authors: "Schulz KF, Altman DG, Moher D",
+ year: 2010,
+ url: "https://www.consort-statement.org/",
+ },
+ {
+ key: "prisma-2020",
+ guideline: "PRISMA",
+ title: "PRISMA 2020 statement: an updated guideline for reporting systematic reviews",
+ authors: "Page MJ, McKenzie JE, Bossuyt PM",
+ year: 2021,
+ url: "https://www.prisma-statement.org/",
+ },
+ {
+ key: "strobe-2007",
+ guideline: "STROBE",
+ title: "The STROBE statement: guidelines for reporting observational studies",
+ authors: "von Elm E, Altman DG, Egger M",
+ year: 2007,
+ url: "https://www.strobe-statement.org/",
+ },
+]
+
+export const manuscripts = [
+ {
+ id: "trial-omega-sleep",
+ title: "Omega Sleep Digital Coaching for Insomnia: A Randomized Trial",
+ studyDesign: "clinical-trial",
+ abstract:
+ "A mobile coaching intervention improved sleep scores in adults with insomnia. The manuscript reports the primary endpoint and adverse event monitoring.",
+ sections: {
+ methods:
+ "Adults with insomnia were randomized to digital coaching or usual care. Eligibility criteria and the intervention schedule were recorded. The trial registry identifier was NCT01234567.",
+ results:
+ "The primary endpoint improved after eight weeks. Two adverse events were reported. The manuscript does not include a participant flow diagram.",
+ discussion:
+ "The intervention may help patients with persistent insomnia, although longer follow-up is needed.",
+ },
+ references: ["digital-sleep-2024"],
+ },
+ {
+ id: "review-cardio-ai",
+ title: "AI Triage for Cardiology Referrals: A Systematic Review",
+ studyDesign: "systematic-review",
+ abstract:
+ "This review summarizes diagnostic triage models for cardiology referrals and compares reported performance across clinical settings.",
+ sections: {
+ methods:
+ "We searched MEDLINE and arXiv for diagnostic triage studies published through March 2026. Inclusion criteria required an external validation cohort.",
+ results:
+ "Twenty-six studies met the review criteria. The manuscript lists model families but omits stage-by-stage review flow counts.",
+ discussion:
+ "External validation remains uncommon. Reporting quality was uneven across included studies.",
+ },
+ references: ["cardio-triage-2025"],
+ },
+ {
+ id: "cohort-lab-glucose",
+ title: "Continuous Glucose Monitoring Alerts in Primary Care: A Cohort Study",
+ studyDesign: "observational",
+ abstract:
+ "A retrospective cohort study compared alert burden and follow-up testing after continuous glucose monitoring deployment.",
+ sections: {
+ methods:
+ "Patients were sampled from three primary care clinics. Eligibility required at least one glucose alert during the observation window.",
+ results:
+ "Alert burden was higher for patients with more prior visits. Follow-up testing increased in the intervention clinics.",
+ discussion:
+ "The study may be affected by baseline differences and unmeasured care access factors.",
+ },
+ references: ["cgm-alerts-2024"],
+ },
+]
diff --git a/reporting-guideline-compliance-assistant/test.js b/reporting-guideline-compliance-assistant/test.js
new file mode 100644
index 00000000..6a7c8b3a
--- /dev/null
+++ b/reporting-guideline-compliance-assistant/test.js
@@ -0,0 +1,58 @@
+import test from "node:test"
+import assert from "node:assert/strict"
+import { manuscripts } from "./sample-data.js"
+import {
+ analyzeBatch,
+ analyzeReportingGuidelineCompliance,
+ renderMarkdownReport,
+ renderSvgSummary,
+} from "./index.js"
+
+test("flags missing CONSORT allocation concealment details", () => {
+ const packet = analyzeReportingGuidelineCompliance(manuscripts[0])
+ const allocation = packet.findings.find(
+ (finding) => finding.id === "consort-allocation"
+ )
+
+ assert.equal(allocation.status, "fail")
+ assert.equal(allocation.severity, "high")
+ assert.match(allocation.reviewerAction, /allocation concealment/i)
+})
+
+test("recommends guideline citations for failed checklist items", () => {
+ const packet = analyzeReportingGuidelineCompliance(manuscripts[1])
+
+ assert.equal(packet.citationRecommendations[0].guideline, "PRISMA")
+ assert.match(packet.citationRecommendations[0].apa, /PRISMA 2020/)
+})
+
+test("scores clean checklist evidence higher than missing evidence", () => {
+ const cleanTrial = {
+ ...manuscripts[0],
+ sections: {
+ methods:
+ "Adults were randomized with allocation concealment. The trial was registered as NCT01234567.",
+ results:
+ "A participant flow diagram reports records screened, excluded, randomized, and analyzed.",
+ discussion:
+ "Data availability and code availability statements are included in the supplement.",
+ },
+ }
+
+ const cleanPacket = analyzeReportingGuidelineCompliance(cleanTrial)
+ const originalPacket = analyzeReportingGuidelineCompliance(manuscripts[0])
+
+ assert.ok(cleanPacket.readinessScore > originalPacket.readinessScore)
+ assert.equal(cleanPacket.readiness, "ready")
+})
+
+test("renders reviewer markdown and svg artifacts", () => {
+ const batch = analyzeBatch(manuscripts)
+ const markdown = renderMarkdownReport(batch)
+ const svg = renderSvgSummary(batch)
+
+ assert.match(markdown, /Reporting Guideline Compliance Packet/)
+ assert.match(markdown, /Reviewer Actions/)
+ assert.match(svg, /