From 846188d346dfa36d0be3257d5e9a518f335d210f Mon Sep 17 00:00:00 2001
From: shaiananvari8 <228813044+shaiananvari8@users.noreply.github.com>
Date: Wed, 27 May 2026 23:45:48 -0500
Subject: [PATCH] Add Bayesian prior sensitivity assistant
---
.../README.md | 35 +++
.../acceptance-notes.md | 19 ++
bayesian-prior-sensitivity-assistant/demo.js | 84 +++++++
bayesian-prior-sensitivity-assistant/index.js | 229 ++++++++++++++++++
.../make-demo-video.js | 163 +++++++++++++
.../package.json | 13 +
.../bayesian-prior-sensitivity-packet.json | 138 +++++++++++
.../bayesian-prior-sensitivity-report.md | 35 +++
.../reports/demo.avi | Bin 0 -> 2765416 bytes
.../reports/summary.svg | 20 ++
.../requirements-map.md | 13 +
.../sample-data.js | 143 +++++++++++
bayesian-prior-sensitivity-assistant/test.js | 61 +++++
13 files changed, 953 insertions(+)
create mode 100644 bayesian-prior-sensitivity-assistant/README.md
create mode 100644 bayesian-prior-sensitivity-assistant/acceptance-notes.md
create mode 100644 bayesian-prior-sensitivity-assistant/demo.js
create mode 100644 bayesian-prior-sensitivity-assistant/index.js
create mode 100644 bayesian-prior-sensitivity-assistant/make-demo-video.js
create mode 100644 bayesian-prior-sensitivity-assistant/package.json
create mode 100644 bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-packet.json
create mode 100644 bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-report.md
create mode 100644 bayesian-prior-sensitivity-assistant/reports/demo.avi
create mode 100644 bayesian-prior-sensitivity-assistant/reports/summary.svg
create mode 100644 bayesian-prior-sensitivity-assistant/requirements-map.md
create mode 100644 bayesian-prior-sensitivity-assistant/sample-data.js
create mode 100644 bayesian-prior-sensitivity-assistant/test.js
diff --git a/bayesian-prior-sensitivity-assistant/README.md b/bayesian-prior-sensitivity-assistant/README.md
new file mode 100644
index 00000000..d3c9c4af
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/README.md
@@ -0,0 +1,35 @@
+# Bayesian Prior Sensitivity Assistant
+
+Synthetic, dependency-free auto peer-review assistant for SCIBASE issue #16, AI-Powered Research Assistant Suite.
+
+This module evaluates Bayesian analysis review packets for prior-sensitivity and posterior-robustness risks before an AI assistant promotes manuscript feedback to authors or reviewers.
+
+## What It Checks
+
+- priors used without manuscript disclosure
+- informative priors without domain justification
+- posterior direction flips under alternate priors
+- large posterior shifts under prior sensitivity runs
+- convergence failures, divergent transitions, and low effective sample size
+- missing or weak prior predictive checks
+- strong manuscript claims that are not robust across priors
+
+## Run
+
+```bash
+npm run check
+npm test
+npm run demo
+npm run demo:video
+```
+
+The demo writes reviewer artifacts under `reports/`:
+
+- `bayesian-prior-sensitivity-packet.json`
+- `bayesian-prior-sensitivity-report.md`
+- `summary.svg`
+- `demo.avi`
+
+## Safety
+
+All records are synthetic. The module does not read local files outside this folder, call external services, execute notebooks, or process real manuscripts.
diff --git a/bayesian-prior-sensitivity-assistant/acceptance-notes.md b/bayesian-prior-sensitivity-assistant/acceptance-notes.md
new file mode 100644
index 00000000..b8554317
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/acceptance-notes.md
@@ -0,0 +1,19 @@
+# Acceptance Notes
+
+Reviewer acceptance checklist:
+
+- The high-risk clinical Bayesian model is held for major revision.
+- The borderline materials model is marked for minor revision.
+- The ready ecology model passes without findings.
+- Strong claims that are not prior-robust are blocked.
+- Audit digests are deterministic across repeated runs.
+- Demo artifacts are generated locally from synthetic data only.
+
+Validation commands:
+
+```bash
+npm run check
+npm test
+npm run demo
+npm run demo:video
+```
diff --git a/bayesian-prior-sensitivity-assistant/demo.js b/bayesian-prior-sensitivity-assistant/demo.js
new file mode 100644
index 00000000..bc065bb1
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/demo.js
@@ -0,0 +1,84 @@
+"use strict";
+
+const fs = require("fs");
+const path = require("path");
+const { assessBayesianPriorSensitivity } = require("./index");
+const { mixedBayesianReviewPacket, readyBayesianReviewPacket } = require("./sample-data");
+
+const reportsDir = path.join(__dirname, "reports");
+fs.mkdirSync(reportsDir, { recursive: true });
+
+const packet = {
+ mixed: assessBayesianPriorSensitivity(mixedBayesianReviewPacket),
+ ready: assessBayesianPriorSensitivity(readyBayesianReviewPacket)
+};
+
+fs.writeFileSync(path.join(reportsDir, "bayesian-prior-sensitivity-packet.json"), `${JSON.stringify(packet, null, 2)}\n`);
+fs.writeFileSync(path.join(reportsDir, "bayesian-prior-sensitivity-report.md"), renderMarkdown(packet));
+fs.writeFileSync(path.join(reportsDir, "summary.svg"), renderSvg(packet));
+
+console.log(`Wrote ${path.relative(process.cwd(), reportsDir)}`);
+console.log(`Mixed packet status: ${packet.mixed.status}`);
+console.log(`Audit digest: ${packet.mixed.auditDigest}`);
+
+function renderMarkdown(packet) {
+ const lines = [
+ "# Bayesian Prior Sensitivity Assistant Report",
+ "",
+ "Synthetic auto peer-review packet for SCIBASE issue #16.",
+ "",
+ "## Summary",
+ "",
+ "| Packet | Status | Major | Minor | Ready | Digest |",
+ "| --- | --- | ---: | ---: | ---: | --- |",
+ `| mixed | ${packet.mixed.status} | ${packet.mixed.summary.major} | ${packet.mixed.summary.minor} | ${packet.mixed.summary.ready} | ${packet.mixed.auditDigest.slice(0, 12)} |`,
+ `| ready | ${packet.ready.status} | ${packet.ready.summary.major} | ${packet.ready.summary.minor} | ${packet.ready.summary.ready} | ${packet.ready.auditDigest.slice(0, 12)} |`,
+ "",
+ "## Analysis Decisions",
+ ""
+ ];
+
+ for (const analysis of packet.mixed.analyses) {
+ lines.push(`### ${analysis.analysisId}: ${analysis.decision}`);
+ for (const blocker of analysis.blockers) {
+ lines.push(`- blocker ${blocker.code}: ${blocker.message}`);
+ }
+ for (const warning of analysis.warnings) {
+ lines.push(`- warning ${warning.code}: ${warning.message}`);
+ }
+ lines.push("");
+ }
+
+ lines.push("## Non-Overlap Notes", "");
+ lines.push(
+ "This module focuses specifically on Bayesian prior sensitivity, convergence diagnostics, prior predictive checks, and posterior claim calibration. It does not implement a broad assistant suite, multiple-comparison correction, generic statistical consistency checks, study power feasibility, uncertainty tone review, prompt safety, literature freshness, image integrity, external validity, or protocol trace workflows."
+ );
+
+ return `${lines.join("\n")}\n`;
+}
+
+function renderSvg(packet) {
+ const mixed = packet.mixed.summary;
+ return `
+
+`;
+}
+
+function bar(x, y, label, count, color) {
+ const width = Math.max(24, count * 120);
+ return [
+ ` ${label}`,
+ ` `,
+ ` `,
+ ` ${count} analysis item(s)`
+ ].join("\n");
+}
diff --git a/bayesian-prior-sensitivity-assistant/index.js b/bayesian-prior-sensitivity-assistant/index.js
new file mode 100644
index 00000000..00e38d15
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/index.js
@@ -0,0 +1,229 @@
+"use strict";
+
+const crypto = require("crypto");
+
+const DEFAULT_POLICY = {
+ maxRhat: 1.01,
+ severeRhat: 1.05,
+ minEffectiveSampleSize: 400,
+ severeEffectiveSampleSize: 150,
+ maxPosteriorShift: 0.2,
+ minPriorPredictiveCoverage: 0.7,
+ strongClaimProbability: 0.95
+};
+
+function assessBayesianPriorSensitivity(packet, policy = {}) {
+ const settings = { ...DEFAULT_POLICY, ...policy };
+ const generatedAt = new Date(packet.generatedAt || "2026-05-28T00:00:00Z");
+ const analyses = (packet.analyses || []).map((analysis) => evaluateAnalysis(analysis, settings));
+ const summary = summarize(analyses);
+ const payload = {
+ generatedAt: generatedAt.toISOString(),
+ manuscriptId: packet.manuscriptId || "synthetic-bayesian-manuscript",
+ status: summary.status,
+ summary,
+ analyses
+ };
+
+ return {
+ ...payload,
+ auditDigest: digest(payload)
+ };
+}
+
+function evaluateAnalysis(analysis, settings) {
+ const blockers = [];
+ const warnings = [];
+ const actions = [];
+
+ checkPriorDisclosure(analysis, blockers, warnings, actions);
+ checkPriorSensitivity(analysis, settings, blockers, warnings, actions);
+ checkDiagnostics(analysis, settings, blockers, warnings, actions);
+ checkPriorPredictive(analysis, settings, blockers, warnings, actions);
+ checkClaims(analysis, settings, blockers, warnings, actions);
+
+ const decision = blockers.length > 0
+ ? "major_revision_prior_robustness"
+ : warnings.length > 0
+ ? "minor_revision_prior_robustness"
+ : "ready_for_peer_review";
+
+ return {
+ analysisId: analysis.id,
+ domain: analysis.domain,
+ decision,
+ blockers,
+ warnings,
+ actions: [...new Set(actions)]
+ };
+}
+
+function checkPriorDisclosure(analysis, blockers, warnings, actions) {
+ const undisclosed = analysis.priors.filter((prior) => !prior.reported);
+ const unjustifiedInformative = analysis.priors.filter((prior) => prior.reported && prior.strength === "informative" && !prior.justification);
+
+ if (undisclosed.length > 0) {
+ blockers.push({
+ code: "prior_not_reported",
+ message: `${undisclosed.length} model prior(s) are used without manuscript disclosure.`
+ });
+ actions.push("Disclose all model priors with parameter values and rationale.");
+ }
+
+ if (unjustifiedInformative.length > 0) {
+ warnings.push({
+ code: "informative_prior_not_justified",
+ message: `${unjustifiedInformative.length} informative prior(s) lack domain justification.`
+ });
+ actions.push("Add domain rationale or sensitivity analysis for informative priors.");
+ }
+}
+
+function checkPriorSensitivity(analysis, settings, blockers, warnings, actions) {
+ for (const run of analysis.sensitivityRuns) {
+ const baseline = run.baselineEstimate;
+ const alternate = run.alternateEstimate;
+ const shift = Math.abs(alternate - baseline);
+ const directionFlips = Math.sign(baseline) !== 0 && Math.sign(alternate) !== 0 && Math.sign(baseline) !== Math.sign(alternate);
+
+ if (directionFlips) {
+ blockers.push({
+ code: "posterior_direction_flips_under_prior",
+ message: `${run.name} changes effect direction from ${round(baseline)} to ${round(alternate)}.`
+ });
+ actions.push("Mark the manuscript claim as prior-sensitive and add a robustness table.");
+ } else if (shift > settings.maxPosteriorShift) {
+ warnings.push({
+ code: "large_posterior_shift_under_prior",
+ message: `${run.name} shifts posterior estimate by ${round(shift)}.`
+ });
+ actions.push("Report alternate-prior posterior estimates beside the primary model.");
+ }
+ }
+}
+
+function checkDiagnostics(analysis, settings, blockers, warnings, actions) {
+ const diagnostics = analysis.diagnostics;
+
+ if (diagnostics.divergentTransitions > 0) {
+ blockers.push({
+ code: "divergent_transitions_present",
+ message: `${diagnostics.divergentTransitions} divergent transition(s) were reported.`
+ });
+ actions.push("Resolve sampler divergences before accepting posterior claims.");
+ }
+
+ if (diagnostics.maxRhat > settings.severeRhat) {
+ blockers.push({
+ code: "severe_rhat_convergence_failure",
+ message: `Maximum R-hat is ${round(diagnostics.maxRhat)}.`
+ });
+ actions.push("Rerun or reparameterize the model until convergence diagnostics pass.");
+ } else if (diagnostics.maxRhat > settings.maxRhat) {
+ warnings.push({
+ code: "rhat_above_review_threshold",
+ message: `Maximum R-hat is ${round(diagnostics.maxRhat)}.`
+ });
+ actions.push("Include convergence diagnostics and rerun chains if needed.");
+ }
+
+ if (diagnostics.minEffectiveSampleSize < settings.severeEffectiveSampleSize) {
+ blockers.push({
+ code: "severe_effective_sample_size_shortfall",
+ message: `Minimum effective sample size is ${diagnostics.minEffectiveSampleSize}.`
+ });
+ actions.push("Increase sampling effort or simplify the model before review.");
+ } else if (diagnostics.minEffectiveSampleSize < settings.minEffectiveSampleSize) {
+ warnings.push({
+ code: "low_effective_sample_size",
+ message: `Minimum effective sample size is ${diagnostics.minEffectiveSampleSize}.`
+ });
+ actions.push("Report effective sample sizes and rerun where posterior tails are unstable.");
+ }
+}
+
+function checkPriorPredictive(analysis, settings, blockers, warnings, actions) {
+ const check = analysis.priorPredictiveCheck;
+
+ if (!check.reported) {
+ blockers.push({
+ code: "prior_predictive_check_missing",
+ message: "No prior predictive check is reported for the Bayesian model."
+ });
+ actions.push("Add a prior predictive check before claims are promoted to peer-review text.");
+ return;
+ }
+
+ if (check.coverage < settings.minPriorPredictiveCoverage) {
+ warnings.push({
+ code: "weak_prior_predictive_coverage",
+ message: `Prior predictive coverage is ${Math.round(check.coverage * 100)}%.`
+ });
+ actions.push("Revise priors or explain why prior predictive coverage is low.");
+ }
+}
+
+function checkClaims(analysis, settings, blockers, warnings, actions) {
+ for (const claim of analysis.claims) {
+ const strongLanguage = ["proves", "conclusive", "definitive"].includes(claim.strength);
+
+ if (strongLanguage && !claim.robustAcrossPriors) {
+ blockers.push({
+ code: "strong_claim_not_prior_robust",
+ message: `${claim.id} uses strong language without prior-robust support.`
+ });
+ actions.push("Downgrade claim language or add prior-robust evidence.");
+ } else if (strongLanguage && claim.posteriorProbability < settings.strongClaimProbability) {
+ warnings.push({
+ code: "claim_probability_below_strong_language",
+ message: `${claim.id} has posterior probability ${round(claim.posteriorProbability)} with strong wording.`
+ });
+ actions.push("Calibrate the manuscript claim to the posterior probability.");
+ }
+ }
+}
+
+function summarize(analyses) {
+ const major = analyses.filter((analysis) => analysis.decision === "major_revision_prior_robustness").length;
+ const minor = analyses.filter((analysis) => analysis.decision === "minor_revision_prior_robustness").length;
+ const ready = analyses.filter((analysis) => analysis.decision === "ready_for_peer_review").length;
+ const blockerCount = analyses.reduce((sum, analysis) => sum + analysis.blockers.length, 0);
+ const warningCount = analyses.reduce((sum, analysis) => sum + analysis.warnings.length, 0);
+ const status = major > 0 ? "hold_peer_review_claims" : minor > 0 ? "revise_before_review" : "ready";
+
+ return {
+ status,
+ analysisCount: analyses.length,
+ major,
+ minor,
+ ready,
+ blockerCount,
+ warningCount
+ };
+}
+
+function digest(value) {
+ return crypto.createHash("sha256").update(stableStringify(value)).digest("hex");
+}
+
+function stableStringify(value) {
+ if (Array.isArray(value)) {
+ return `[${value.map(stableStringify).join(",")}]`;
+ }
+ if (value && typeof value === "object") {
+ return `{${Object.keys(value)
+ .sort()
+ .map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`)
+ .join(",")}}`;
+ }
+ return JSON.stringify(value);
+}
+
+function round(value) {
+ return Math.round(value * 100) / 100;
+}
+
+module.exports = {
+ assessBayesianPriorSensitivity,
+ DEFAULT_POLICY
+};
diff --git a/bayesian-prior-sensitivity-assistant/make-demo-video.js b/bayesian-prior-sensitivity-assistant/make-demo-video.js
new file mode 100644
index 00000000..9ead76c3
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/make-demo-video.js
@@ -0,0 +1,163 @@
+"use strict";
+
+const fs = require("fs");
+const path = require("path");
+
+const width = 320;
+const height = 180;
+const fps = 2;
+const frameCount = 16;
+const rowSize = Math.ceil((width * 3) / 4) * 4;
+const frameSize = rowSize * height;
+const reportsDir = path.join(__dirname, "reports");
+const outputPath = path.join(reportsDir, "demo.avi");
+
+fs.mkdirSync(reportsDir, { recursive: true });
+
+const frames = [];
+for (let i = 0; i < frameCount; i += 1) {
+ frames.push(makeFrame(i));
+}
+
+const chunks = [];
+const indexes = [];
+let offset = 4;
+for (const frame of frames) {
+ const chunk = riffChunk("00db", frame);
+ chunks.push(chunk);
+ indexes.push(indexEntry("00db", 0x10, offset, frame.length));
+ offset += chunk.length;
+}
+
+const hdrl = listChunk("hdrl", [
+ riffChunk("avih", aviHeader()),
+ listChunk("strl", [
+ riffChunk("strh", streamHeader()),
+ riffChunk("strf", bitmapInfoHeader())
+ ])
+]);
+const movi = listChunk("movi", chunks);
+const idx1 = riffChunk("idx1", Buffer.concat(indexes));
+const riff = riffChunk("RIFF", Buffer.concat([Buffer.from("AVI "), hdrl, movi, idx1]));
+
+fs.writeFileSync(outputPath, riff);
+console.log(`Wrote ${path.relative(process.cwd(), outputPath)} (${riff.length} bytes)`);
+
+function makeFrame(frameIndex) {
+ const frame = Buffer.alloc(frameSize, 0xff);
+ const progress = (frameIndex + 1) / frameCount;
+ fillRect(frame, 0, 0, width, height, [247, 247, 251]);
+ fillRect(frame, 18, 18, 284, 144, [255, 255, 255]);
+ strokeRect(frame, 18, 18, 284, 144, [210, 216, 226]);
+ fillRect(frame, 38, 50, 240, 18, [232, 237, 244]);
+ fillRect(frame, 38, 50, Math.round(240 * progress), 18, [185, 28, 28]);
+ fillRect(frame, 38, 90, 240, 18, [232, 237, 244]);
+ fillRect(frame, 38, 90, Math.round(120 * progress), 18, [183, 121, 31]);
+ fillRect(frame, 38, 130, 240, 18, [232, 237, 244]);
+ fillRect(frame, 38, 130, Math.round(120 * progress), 18, [21, 128, 61]);
+ drawTicks(frame, 38, 76, frameIndex);
+ return frame;
+}
+
+function drawTicks(frame, x, y, frameIndex) {
+ const count = Math.min(5, Math.floor(frameIndex / 3) + 1);
+ for (let i = 0; i < count; i += 1) {
+ fillRect(frame, x + i * 18, y, 10, 10, [42, 72, 88]);
+ }
+}
+
+function fillRect(frame, x, y, w, h, rgb) {
+ for (let py = y; py < y + h; py += 1) {
+ if (py < 0 || py >= height) continue;
+ for (let px = x; px < x + w; px += 1) {
+ if (px < 0 || px >= width) continue;
+ setPixel(frame, px, py, rgb);
+ }
+ }
+}
+
+function strokeRect(frame, x, y, w, h, rgb) {
+ fillRect(frame, x, y, w, 1, rgb);
+ fillRect(frame, x, y + h - 1, w, 1, rgb);
+ fillRect(frame, x, y, 1, h, rgb);
+ fillRect(frame, x + w - 1, y, 1, h, rgb);
+}
+
+function setPixel(frame, x, y, rgb) {
+ const bottomUpY = height - y - 1;
+ const index = bottomUpY * rowSize + x * 3;
+ frame[index] = rgb[2];
+ frame[index + 1] = rgb[1];
+ frame[index + 2] = rgb[0];
+}
+
+function aviHeader() {
+ const buffer = Buffer.alloc(56);
+ buffer.writeUInt32LE(Math.round(1000000 / fps), 0);
+ buffer.writeUInt32LE(frameSize * fps, 4);
+ buffer.writeUInt32LE(0, 8);
+ buffer.writeUInt32LE(0x10, 12);
+ buffer.writeUInt32LE(frameCount, 16);
+ buffer.writeUInt32LE(0, 20);
+ buffer.writeUInt32LE(1, 24);
+ buffer.writeUInt32LE(frameSize, 28);
+ buffer.writeUInt32LE(width, 32);
+ buffer.writeUInt32LE(height, 36);
+ return buffer;
+}
+
+function streamHeader() {
+ const buffer = Buffer.alloc(56);
+ buffer.write("vids", 0, 4, "ascii");
+ buffer.write("DIB ", 4, 4, "ascii");
+ buffer.writeUInt32LE(0, 8);
+ buffer.writeUInt32LE(0, 12);
+ buffer.writeUInt32LE(0, 16);
+ buffer.writeUInt32LE(1, 20);
+ buffer.writeUInt32LE(fps, 24);
+ buffer.writeUInt32LE(0, 28);
+ buffer.writeUInt32LE(frameCount, 32);
+ buffer.writeUInt32LE(frameSize, 36);
+ buffer.writeInt32LE(-1, 40);
+ buffer.writeUInt32LE(0, 44);
+ buffer.writeInt16LE(0, 48);
+ buffer.writeInt16LE(0, 50);
+ buffer.writeInt16LE(width, 52);
+ buffer.writeInt16LE(height, 54);
+ return buffer;
+}
+
+function bitmapInfoHeader() {
+ const buffer = Buffer.alloc(40);
+ buffer.writeUInt32LE(40, 0);
+ buffer.writeInt32LE(width, 4);
+ buffer.writeInt32LE(height, 8);
+ buffer.writeUInt16LE(1, 12);
+ buffer.writeUInt16LE(24, 14);
+ buffer.writeUInt32LE(0, 16);
+ buffer.writeUInt32LE(frameSize, 20);
+ return buffer;
+}
+
+function indexEntry(id, flags, chunkOffset, size) {
+ const buffer = Buffer.alloc(16);
+ buffer.write(id, 0, 4, "ascii");
+ buffer.writeUInt32LE(flags, 4);
+ buffer.writeUInt32LE(chunkOffset, 8);
+ buffer.writeUInt32LE(size, 12);
+ return buffer;
+}
+
+function riffChunk(id, payload) {
+ const size = payload.length;
+ const pad = size % 2 === 1 ? 1 : 0;
+ const buffer = Buffer.alloc(8 + size + pad);
+ buffer.write(id, 0, 4, "ascii");
+ buffer.writeUInt32LE(size, 4);
+ payload.copy(buffer, 8);
+ return buffer;
+}
+
+function listChunk(type, chunks) {
+ return riffChunk("LIST", Buffer.concat([Buffer.from(type, "ascii"), ...chunks]));
+}
diff --git a/bayesian-prior-sensitivity-assistant/package.json b/bayesian-prior-sensitivity-assistant/package.json
new file mode 100644
index 00000000..45e6a26a
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "bayesian-prior-sensitivity-assistant",
+ "version": "1.0.0",
+ "description": "Synthetic Bayesian prior sensitivity review assistant for SCIBASE issue 16.",
+ "main": "index.js",
+ "scripts": {
+ "check": "node --check index.js && node --check sample-data.js && node --check test.js && node --check demo.js && node --check make-demo-video.js",
+ "test": "node test.js",
+ "demo": "node demo.js",
+ "demo:video": "node make-demo-video.js"
+ },
+ "license": "MIT"
+}
diff --git a/bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-packet.json b/bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-packet.json
new file mode 100644
index 00000000..94709540
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-packet.json
@@ -0,0 +1,138 @@
+{
+ "mixed": {
+ "generatedAt": "2026-05-28T07:30:00.000Z",
+ "manuscriptId": "synthetic-bayesian-review",
+ "status": "hold_peer_review_claims",
+ "summary": {
+ "status": "hold_peer_review_claims",
+ "analysisCount": 3,
+ "major": 1,
+ "minor": 1,
+ "ready": 1,
+ "blockerCount": 7,
+ "warningCount": 6
+ },
+ "analyses": [
+ {
+ "analysisId": "clinical-survival-model",
+ "domain": "clinical trials",
+ "decision": "major_revision_prior_robustness",
+ "blockers": [
+ {
+ "code": "prior_not_reported",
+ "message": "1 model prior(s) are used without manuscript disclosure."
+ },
+ {
+ "code": "posterior_direction_flips_under_prior",
+ "message": "skeptical treatment prior changes effect direction from 0.31 to -0.08."
+ },
+ {
+ "code": "divergent_transitions_present",
+ "message": "14 divergent transition(s) were reported."
+ },
+ {
+ "code": "severe_rhat_convergence_failure",
+ "message": "Maximum R-hat is 1.08."
+ },
+ {
+ "code": "severe_effective_sample_size_shortfall",
+ "message": "Minimum effective sample size is 112."
+ },
+ {
+ "code": "prior_predictive_check_missing",
+ "message": "No prior predictive check is reported for the Bayesian model."
+ },
+ {
+ "code": "strong_claim_not_prior_robust",
+ "message": "claim-treatment-definitive uses strong language without prior-robust support."
+ }
+ ],
+ "warnings": [
+ {
+ "code": "informative_prior_not_justified",
+ "message": "1 informative prior(s) lack domain justification."
+ },
+ {
+ "code": "large_posterior_shift_under_prior",
+ "message": "wider frailty prior shifts posterior estimate by 0.27."
+ }
+ ],
+ "actions": [
+ "Disclose all model priors with parameter values and rationale.",
+ "Add domain rationale or sensitivity analysis for informative priors.",
+ "Mark the manuscript claim as prior-sensitive and add a robustness table.",
+ "Report alternate-prior posterior estimates beside the primary model.",
+ "Resolve sampler divergences before accepting posterior claims.",
+ "Rerun or reparameterize the model until convergence diagnostics pass.",
+ "Increase sampling effort or simplify the model before review.",
+ "Add a prior predictive check before claims are promoted to peer-review text.",
+ "Downgrade claim language or add prior-robust evidence."
+ ]
+ },
+ {
+ "analysisId": "materials-yield-model",
+ "domain": "materials science",
+ "decision": "minor_revision_prior_robustness",
+ "blockers": [],
+ "warnings": [
+ {
+ "code": "informative_prior_not_justified",
+ "message": "1 informative prior(s) lack domain justification."
+ },
+ {
+ "code": "rhat_above_review_threshold",
+ "message": "Maximum R-hat is 1.02."
+ },
+ {
+ "code": "low_effective_sample_size",
+ "message": "Minimum effective sample size is 260."
+ },
+ {
+ "code": "weak_prior_predictive_coverage",
+ "message": "Prior predictive coverage is 58%."
+ }
+ ],
+ "actions": [
+ "Add domain rationale or sensitivity analysis for informative priors.",
+ "Include convergence diagnostics and rerun chains if needed.",
+ "Report effective sample sizes and rerun where posterior tails are unstable.",
+ "Revise priors or explain why prior predictive coverage is low."
+ ]
+ },
+ {
+ "analysisId": "ecology-occupancy-model",
+ "domain": "ecology",
+ "decision": "ready_for_peer_review",
+ "blockers": [],
+ "warnings": [],
+ "actions": []
+ }
+ ],
+ "auditDigest": "0f1f6b29a79b38614e0b5c509f8479266adf55dd81661884b67153e2eb5f9757"
+ },
+ "ready": {
+ "generatedAt": "2026-05-28T07:30:00.000Z",
+ "manuscriptId": "synthetic-ready-bayesian-review",
+ "status": "ready",
+ "summary": {
+ "status": "ready",
+ "analysisCount": 1,
+ "major": 0,
+ "minor": 0,
+ "ready": 1,
+ "blockerCount": 0,
+ "warningCount": 0
+ },
+ "analyses": [
+ {
+ "analysisId": "ecology-occupancy-model",
+ "domain": "ecology",
+ "decision": "ready_for_peer_review",
+ "blockers": [],
+ "warnings": [],
+ "actions": []
+ }
+ ],
+ "auditDigest": "43a9b74dc9b5b4ed480e414f2f5d7b6a7e9d8dae4df9b00cfddabb354aeea190"
+ }
+}
diff --git a/bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-report.md b/bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-report.md
new file mode 100644
index 00000000..89cf4706
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/reports/bayesian-prior-sensitivity-report.md
@@ -0,0 +1,35 @@
+# Bayesian Prior Sensitivity Assistant Report
+
+Synthetic auto peer-review packet for SCIBASE issue #16.
+
+## Summary
+
+| Packet | Status | Major | Minor | Ready | Digest |
+| --- | --- | ---: | ---: | ---: | --- |
+| mixed | hold_peer_review_claims | 1 | 1 | 1 | 0f1f6b29a79b |
+| ready | ready | 0 | 0 | 1 | 43a9b74dc9b5 |
+
+## Analysis Decisions
+
+### clinical-survival-model: major_revision_prior_robustness
+- blocker prior_not_reported: 1 model prior(s) are used without manuscript disclosure.
+- blocker posterior_direction_flips_under_prior: skeptical treatment prior changes effect direction from 0.31 to -0.08.
+- blocker divergent_transitions_present: 14 divergent transition(s) were reported.
+- blocker severe_rhat_convergence_failure: Maximum R-hat is 1.08.
+- blocker severe_effective_sample_size_shortfall: Minimum effective sample size is 112.
+- blocker prior_predictive_check_missing: No prior predictive check is reported for the Bayesian model.
+- blocker strong_claim_not_prior_robust: claim-treatment-definitive uses strong language without prior-robust support.
+- warning informative_prior_not_justified: 1 informative prior(s) lack domain justification.
+- warning large_posterior_shift_under_prior: wider frailty prior shifts posterior estimate by 0.27.
+
+### materials-yield-model: minor_revision_prior_robustness
+- warning informative_prior_not_justified: 1 informative prior(s) lack domain justification.
+- warning rhat_above_review_threshold: Maximum R-hat is 1.02.
+- warning low_effective_sample_size: Minimum effective sample size is 260.
+- warning weak_prior_predictive_coverage: Prior predictive coverage is 58%.
+
+### ecology-occupancy-model: ready_for_peer_review
+
+## Non-Overlap Notes
+
+This module focuses specifically on Bayesian prior sensitivity, convergence diagnostics, prior predictive checks, and posterior claim calibration. It does not implement a broad assistant suite, multiple-comparison correction, generic statistical consistency checks, study power feasibility, uncertainty tone review, prompt safety, literature freshness, image integrity, external validity, or protocol trace workflows.
diff --git a/bayesian-prior-sensitivity-assistant/reports/demo.avi b/bayesian-prior-sensitivity-assistant/reports/demo.avi
new file mode 100644
index 0000000000000000000000000000000000000000..cc3de3b756aa88929cb4448718f4a036f8afac49
GIT binary patch
literal 2765416
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
literal 0
HcmV?d00001
diff --git a/bayesian-prior-sensitivity-assistant/reports/summary.svg b/bayesian-prior-sensitivity-assistant/reports/summary.svg
new file mode 100644
index 00000000..b9c0ce1f
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/reports/summary.svg
@@ -0,0 +1,20 @@
+
+
diff --git a/bayesian-prior-sensitivity-assistant/requirements-map.md b/bayesian-prior-sensitivity-assistant/requirements-map.md
new file mode 100644
index 00000000..460e8720
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/requirements-map.md
@@ -0,0 +1,13 @@
+# Requirements Map
+
+| Issue #16 requirement | Coverage |
+| --- | --- |
+| Auto peer review reports | Emits structured reviewer findings, severity, remediation actions, and deterministic audit digests. |
+| Statistical or methodological red flags | Flags prior sensitivity, convergence, divergent transitions, low effective sample size, and weak prior predictive coverage. |
+| Claims vs. evidence alignment | Checks whether strong manuscript claims remain robust under alternate priors and posterior probabilities. |
+| Adaptive templates per domain | Includes synthetic clinical, materials science, and ecology review packets with domain labels. |
+| Reproducibility confidence support | Records deterministic outcomes and diagnostics that can feed reproducibility review workflows. |
+
+## Non-Overlap
+
+This is not a broad AI assistant suite, multiple-comparison control tool, generic statistical consistency checker, study power feasibility assistant, uncertainty tone reviewer, prompt safety guard, literature freshness checker, image integrity tool, external-validity reviewer, or protocol trace workflow. It focuses narrowly on Bayesian prior sensitivity and posterior robustness.
diff --git a/bayesian-prior-sensitivity-assistant/sample-data.js b/bayesian-prior-sensitivity-assistant/sample-data.js
new file mode 100644
index 00000000..51eaa528
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/sample-data.js
@@ -0,0 +1,143 @@
+"use strict";
+
+const mixedBayesianReviewPacket = {
+ generatedAt: "2026-05-28T07:30:00Z",
+ manuscriptId: "synthetic-bayesian-review",
+ analyses: [
+ {
+ id: "clinical-survival-model",
+ domain: "clinical trials",
+ priors: [
+ {
+ name: "treatment_log_hazard_ratio",
+ reported: true,
+ strength: "informative",
+ justification: false
+ },
+ {
+ name: "baseline_hazard_spline",
+ reported: false,
+ strength: "weakly-informative",
+ justification: false
+ }
+ ],
+ sensitivityRuns: [
+ {
+ name: "skeptical treatment prior",
+ baselineEstimate: 0.31,
+ alternateEstimate: -0.08
+ },
+ {
+ name: "wider frailty prior",
+ baselineEstimate: 0.31,
+ alternateEstimate: 0.04
+ }
+ ],
+ diagnostics: {
+ maxRhat: 1.08,
+ minEffectiveSampleSize: 112,
+ divergentTransitions: 14
+ },
+ priorPredictiveCheck: {
+ reported: false,
+ coverage: 0
+ },
+ claims: [
+ {
+ id: "claim-treatment-definitive",
+ posteriorProbability: 0.91,
+ strength: "definitive",
+ robustAcrossPriors: false
+ }
+ ]
+ },
+ {
+ id: "materials-yield-model",
+ domain: "materials science",
+ priors: [
+ {
+ name: "thermal_gradient_effect",
+ reported: true,
+ strength: "informative",
+ justification: false
+ }
+ ],
+ sensitivityRuns: [
+ {
+ name: "neutral process prior",
+ baselineEstimate: 0.44,
+ alternateEstimate: 0.29
+ }
+ ],
+ diagnostics: {
+ maxRhat: 1.02,
+ minEffectiveSampleSize: 260,
+ divergentTransitions: 0
+ },
+ priorPredictiveCheck: {
+ reported: true,
+ coverage: 0.58
+ },
+ claims: [
+ {
+ id: "claim-yield-improves",
+ posteriorProbability: 0.94,
+ strength: "likely",
+ robustAcrossPriors: true
+ }
+ ]
+ },
+ {
+ id: "ecology-occupancy-model",
+ domain: "ecology",
+ priors: [
+ {
+ name: "occupancy_intercept",
+ reported: true,
+ strength: "weakly-informative",
+ justification: true
+ }
+ ],
+ sensitivityRuns: [
+ {
+ name: "wide occupancy prior",
+ baselineEstimate: 0.22,
+ alternateEstimate: 0.18
+ },
+ {
+ name: "skeptical occupancy prior",
+ baselineEstimate: 0.22,
+ alternateEstimate: 0.2
+ }
+ ],
+ diagnostics: {
+ maxRhat: 1,
+ minEffectiveSampleSize: 920,
+ divergentTransitions: 0
+ },
+ priorPredictiveCheck: {
+ reported: true,
+ coverage: 0.82
+ },
+ claims: [
+ {
+ id: "claim-habitat-associated",
+ posteriorProbability: 0.96,
+ strength: "likely",
+ robustAcrossPriors: true
+ }
+ ]
+ }
+ ]
+};
+
+const readyBayesianReviewPacket = {
+ generatedAt: "2026-05-28T07:30:00Z",
+ manuscriptId: "synthetic-ready-bayesian-review",
+ analyses: [mixedBayesianReviewPacket.analyses[2]]
+};
+
+module.exports = {
+ mixedBayesianReviewPacket,
+ readyBayesianReviewPacket
+};
diff --git a/bayesian-prior-sensitivity-assistant/test.js b/bayesian-prior-sensitivity-assistant/test.js
new file mode 100644
index 00000000..1da0814b
--- /dev/null
+++ b/bayesian-prior-sensitivity-assistant/test.js
@@ -0,0 +1,61 @@
+"use strict";
+
+const assert = require("assert");
+const { assessBayesianPriorSensitivity } = require("./index");
+const { mixedBayesianReviewPacket, readyBayesianReviewPacket } = require("./sample-data");
+
+function testHighRiskBayesianAnalysisIsHeld() {
+ const result = assessBayesianPriorSensitivity(mixedBayesianReviewPacket);
+ const clinical = result.analyses.find((analysis) => analysis.analysisId === "clinical-survival-model");
+ const codes = clinical.blockers.map((blocker) => blocker.code);
+
+ assert.strictEqual(result.status, "hold_peer_review_claims");
+ assert.strictEqual(clinical.decision, "major_revision_prior_robustness");
+ assert(codes.includes("prior_not_reported"));
+ assert(codes.includes("posterior_direction_flips_under_prior"));
+ assert(codes.includes("divergent_transitions_present"));
+ assert(codes.includes("severe_rhat_convergence_failure"));
+ assert(codes.includes("severe_effective_sample_size_shortfall"));
+ assert(codes.includes("prior_predictive_check_missing"));
+ assert(codes.includes("strong_claim_not_prior_robust"));
+}
+
+function testModerateBayesianAnalysisNeedsMinorRevision() {
+ const result = assessBayesianPriorSensitivity(mixedBayesianReviewPacket);
+ const materials = result.analyses.find((analysis) => analysis.analysisId === "materials-yield-model");
+ const codes = materials.warnings.map((warning) => warning.code);
+
+ assert.strictEqual(materials.decision, "minor_revision_prior_robustness");
+ assert(codes.includes("informative_prior_not_justified"));
+ assert(codes.includes("rhat_above_review_threshold"));
+ assert(codes.includes("low_effective_sample_size"));
+ assert(codes.includes("weak_prior_predictive_coverage"));
+}
+
+function testReadyBayesianAnalysisPasses() {
+ const result = assessBayesianPriorSensitivity(readyBayesianReviewPacket);
+ const ready = result.analyses[0];
+
+ assert.strictEqual(result.status, "ready");
+ assert.strictEqual(ready.decision, "ready_for_peer_review");
+ assert.strictEqual(ready.blockers.length, 0);
+ assert.strictEqual(ready.warnings.length, 0);
+}
+
+function testDigestIsDeterministic() {
+ const first = assessBayesianPriorSensitivity(mixedBayesianReviewPacket);
+ const second = assessBayesianPriorSensitivity(mixedBayesianReviewPacket);
+
+ assert.match(first.auditDigest, /^[a-f0-9]{64}$/);
+ assert.strictEqual(first.auditDigest, second.auditDigest);
+}
+
+function run() {
+ testHighRiskBayesianAnalysisIsHeld();
+ testModerateBayesianAnalysisNeedsMinorRevision();
+ testReadyBayesianAnalysisPasses();
+ testDigestIsDeterministic();
+ console.log("4 tests passed");
+}
+
+run();