From f52348783150741e79812026d96a6164eef32716 Mon Sep 17 00:00:00 2001 From: evilfps <208441420+evilfps@users.noreply.github.com> Date: Sat, 16 May 2026 21:48:28 +0530 Subject: [PATCH 1/2] Add ethics data availability checker --- README.md | 2 + ethics-data-availability-checker/README.md | 38 ++ .../data/sample-ethics-input.json | 84 ++++ .../docs/demo.gif | Bin 0 -> 36962 bytes .../docs/demo.svg | 27 ++ .../docs/demo.webm | Bin 0 -> 49831 bytes .../docs/requirement-map.md | 17 + ethics-data-availability-checker/package.json | 17 + .../scripts/demo.js | 11 + .../src/ethics-data-availability-checker.js | 454 ++++++++++++++++++ .../ethics-data-availability-checker.test.js | 144 ++++++ 11 files changed, 794 insertions(+) create mode 100644 ethics-data-availability-checker/README.md create mode 100644 ethics-data-availability-checker/data/sample-ethics-input.json create mode 100644 ethics-data-availability-checker/docs/demo.gif create mode 100644 ethics-data-availability-checker/docs/demo.svg create mode 100644 ethics-data-availability-checker/docs/demo.webm create mode 100644 ethics-data-availability-checker/docs/requirement-map.md create mode 100644 ethics-data-availability-checker/package.json create mode 100644 ethics-data-availability-checker/scripts/demo.js create mode 100644 ethics-data-availability-checker/src/ethics-data-availability-checker.js create mode 100644 ethics-data-availability-checker/test/ethics-data-availability-checker.test.js diff --git a/README.md b/README.md index d338cf6..fd47d94 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # deepevents.ai deepevents.ai main codebase + +- `ethics-data-availability-checker/` adds ethics, consent, data availability, and reproducibility readiness checks for research review packets. diff --git a/ethics-data-availability-checker/README.md b/ethics-data-availability-checker/README.md new file mode 100644 index 0000000..aa30041 --- /dev/null +++ b/ethics-data-availability-checker/README.md @@ -0,0 +1,38 @@ +# Ethics Data Availability Checker + +This module adds a focused research assistant review slice for ethics and data availability readiness. + +It covers: + +- human-subjects approval, consent scope, vulnerable group, and cross-border data checks +- data availability statements, repository access, embargo, license, and controlled-access handling +- code availability, pinned commit, environment, and reproduction command checks +- claim-to-artifact coverage for manuscript claims that need data or approval evidence +- reviewer actions, release readiness status, signed audit events, and deterministic digests + +The implementation is dependency-free and uses synthetic sample data only. + +## Run + +```bash +npm run check +npm test +npm run demo +``` + +## Demo Assets + +- `docs/demo.svg` +- `docs/demo.webm` + +## API + +```js +import { + evaluateEthicsDataAvailability, + renderEthicsDataAvailabilityReport +} from "./src/ethics-data-availability-checker.js"; + +const result = evaluateEthicsDataAvailability(input); +console.log(renderEthicsDataAvailabilityReport(result)); +``` diff --git a/ethics-data-availability-checker/data/sample-ethics-input.json b/ethics-data-availability-checker/data/sample-ethics-input.json new file mode 100644 index 0000000..5cfa3ca --- /dev/null +++ b/ethics-data-availability-checker/data/sample-ethics-input.json @@ -0,0 +1,84 @@ +{ + "project": { + "id": "proj-neuro-immune-042", + "title": "Neuroimmune Marker Study", + "stage": "pre_submission" + }, + "generatedAt": "2026-05-16T16:00:00.000Z", + "signingKey": "sample-review-key", + "ethics": { + "humanSubjects": true, + "approval": { + "status": "approved", + "protocolId": "IRB-2026-1442", + "expiresAt": "2026-05-30" + }, + "consent": { + "status": "complete", + "scope": "internal_only" + }, + "vulnerablePopulation": true, + "safeguards": [ + "deidentified_exports", + "guardian_consent" + ], + "crossBorderTransfer": true, + "transferBasis": "institutional_dpa" + }, + "dataAvailability": { + "statement": "Participant-level data is available through controlled access after review by the study data access committee.", + "repository": { + "url": "https://data.example.org/studies/neuroimmune-042", + "visibility": "controlled" + }, + "accession": "SCIBASE-NEURO-042", + "sensitiveData": true, + "accessCommittee": "Northbridge Data Access Board", + "license": "CC-BY-NC-4.0", + "embargoUntil": "2026-08-01", + "embargoReason": "journal review embargo" + }, + "codeAvailability": { + "repository": { + "url": "https://git.example.org/neuroimmune/analysis", + "commit": "2f1c8a9d7b11" + }, + "environment": "Dockerfile.sha256:64c983", + "reproductionCommand": "npm run reproduce" + }, + "artifacts": [ + { + "id": "artifact-cytokine-table", + "type": "dataset", + "checksum": "sha256:af31", + "linkedInManuscript": true + }, + { + "id": "artifact-figure-2", + "type": "figure", + "checksum": "sha256:ba84", + "linkedInManuscript": true + } + ], + "claims": [ + { + "id": "claim-primary-marker", + "text": "Marker CX-17 is associated with relapse risk.", + "requiresData": true, + "requiresEthics": true, + "evidenceArtifactIds": [ + "artifact-cytokine-table", + "artifact-figure-2" + ] + }, + { + "id": "claim-secondary-model", + "text": "The secondary model is ready for external validation.", + "requiresData": true, + "requiresEthics": false, + "evidenceArtifactIds": [ + "artifact-missing-model" + ] + } + ] +} diff --git a/ethics-data-availability-checker/docs/demo.gif b/ethics-data-availability-checker/docs/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..85d9261fd0a854aec3ee502e40b101b4aa86bf69 GIT binary patch literal 36962 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 literal 0 HcmV?d00001 diff --git a/ethics-data-availability-checker/docs/demo.svg b/ethics-data-availability-checker/docs/demo.svg new file mode 100644 index 0000000..47499e7 --- /dev/null +++ b/ethics-data-availability-checker/docs/demo.svg @@ -0,0 +1,27 @@ + + Ethics data availability checker demo + Static dashboard preview for reviewer readiness checks. + + + Ethics + Data Availability + Neuroimmune Marker Study + + Status + blocked + + Ready + 2 checks + + Review + 1 check + + Blocked + 1 claim + + Reviewer actions + + claim_artifact_not_found: attach the missing model artifact + + approval_expiring: confirm renewal timing before publication + Manifest digest and signed audit events are produced by the demo run. + diff --git a/ethics-data-availability-checker/docs/demo.webm b/ethics-data-availability-checker/docs/demo.webm new file mode 100644 index 0000000000000000000000000000000000000000..2e010a65d7723ad18b0cabac37b5f0ebf10e766b GIT binary patch literal 49831 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 `${JSON.stringify(key)}:${stableStringify(value[key])}`) + .join(",")}}`; + } + return JSON.stringify(value); +} + +export function digest(value) { + return createHash("sha256").update(stableStringify(value)).digest("hex"); +} + +function signEvent(event, signingKey) { + return createHmac("sha256", signingKey).update(stableStringify(event)).digest("hex"); +} + +function parseDateLike(value) { + if (!value) { + return null; + } + const text = String(value); + const hasTimezone = /(?:Z|[+-]\d{2}:?\d{2})$/i.test(text); + const date = /^\d{4}-\d{2}-\d{2}$/.test(text) + ? new Date(`${text}T00:00:00Z`) + : new Date(hasTimezone ? text : `${text}Z`); + return Number.isNaN(date.getTime()) ? null : date; +} + +function daysUntil(dateString, generatedAt) { + const target = parseDateLike(dateString); + if (!target) { + return null; + } + const generated = new Date(generatedAt); + return Math.ceil((target.getTime() - generated.getTime()) / 86_400_000); +} + +function addFinding(findings, code, severity, message, owner, action) { + findings.push({ + code, + severity, + weight: SEVERITY_WEIGHT[severity], + message, + owner, + action + }); +} + +function worstStatus(items) { + return items.reduce((status, item) => { + if (STATUS_RANK[item.status] > STATUS_RANK[status]) { + return item.status; + } + return status; + }, "ready"); +} + +function buildEthicsCheck(input) { + const ethics = input.ethics || {}; + const findings = []; + const approval = ethics.approval || {}; + const consent = ethics.consent || {}; + + if (ethics.humanSubjects && approval.status !== "approved") { + addFinding( + findings, + "approval_missing", + "high", + "Human-subjects work needs approved review before release.", + "ethics_board", + "Attach the approval record or hold submission." + ); + } + + const expiryDays = daysUntil(approval.expiresAt, input.generatedAt); + if (approval.status === "approved" && approval.expiresAt && expiryDays === null) { + addFinding( + findings, + "approval_expiry_invalid", + "medium", + "Approval expiry date cannot be parsed.", + "ethics_board", + "Replace the expiry value with an ISO date or timestamp." + ); + } else if (approval.status === "approved" && expiryDays !== null && expiryDays < 0) { + addFinding( + findings, + "approval_expired", + "high", + `Approval expired ${Math.abs(expiryDays)} days ago.`, + "ethics_board", + "Renew the approval before release." + ); + } else if (approval.status === "approved" && expiryDays !== null && expiryDays <= 30) { + addFinding( + findings, + "approval_expiring", + "medium", + `Approval expires in ${expiryDays} days.`, + "ethics_board", + "Confirm renewal timing before publication." + ); + } + + if (ethics.humanSubjects && consent.status !== "complete") { + addFinding( + findings, + "consent_incomplete", + "high", + "Consent coverage is incomplete for participant data.", + "study_team", + "Resolve consent gaps or remove affected records." + ); + } + + if (consent.scope === "internal_only" && input.dataAvailability?.repository?.visibility === "public") { + addFinding( + findings, + "consent_scope_conflict", + "high", + "Consent scope does not allow public data release.", + "data_steward", + "Use controlled access or update the data package." + ); + } + + if (ethics.vulnerablePopulation && !ethics.safeguards?.length) { + addFinding( + findings, + "vulnerable_group_safeguards_missing", + "medium", + "Vulnerable group safeguards are not documented.", + "study_team", + "Add safeguard notes for reviewer signoff." + ); + } + + if (ethics.crossBorderTransfer && !ethics.transferBasis) { + addFinding( + findings, + "transfer_basis_missing", + "medium", + "Cross-border participant data transfer needs a legal basis.", + "data_steward", + "Record the transfer basis or restrict export." + ); + } + + return { + id: "ethics", + status: findings.some((finding) => finding.severity === "high") ? "blocked" : findings.length ? "review" : "ready", + findings + }; +} + +function buildDataCheck(input) { + const data = input.dataAvailability || {}; + const repository = data.repository || {}; + const findings = []; + + if (!data.statement || data.statement.trim().length < 30) { + addFinding( + findings, + "statement_too_short", + "medium", + "Data availability statement is missing or too short.", + "corresponding_author", + "Add repository, accession, restrictions, and reuse terms." + ); + } + + if (data.sensitiveData && repository.visibility === "public") { + addFinding( + findings, + "sensitive_data_public", + "high", + "Sensitive data is marked for public release.", + "data_steward", + "Move the data to controlled access or publish a redacted package." + ); + } + + if (data.sensitiveData && !data.accessCommittee) { + addFinding( + findings, + "access_committee_missing", + "medium", + "Controlled data needs an access committee or approval path.", + "data_steward", + "Name the access committee and request process." + ); + } + + if (!repository.url && !data.accession) { + addFinding( + findings, + "repository_missing", + "medium", + "No repository URL or accession is recorded.", + "data_steward", + "Add a persistent repository location." + ); + } + + if (!data.license) { + addFinding( + findings, + "license_missing", + "low", + "Reuse license is not listed.", + "data_steward", + "Add license terms for data reuse." + ); + } + + if (data.embargoUntil && !data.embargoReason) { + addFinding( + findings, + "embargo_reason_missing", + "medium", + "Embargo date is set without a reviewer-facing reason.", + "corresponding_author", + "Explain the embargo and release trigger." + ); + } + + return { + id: "data", + status: findings.some((finding) => finding.severity === "high") ? "blocked" : findings.length ? "review" : "ready", + findings + }; +} + +function buildCodeCheck(input) { + const code = input.codeAvailability || {}; + const findings = []; + + if (!code.repository?.url) { + addFinding( + findings, + "code_repository_missing", + "medium", + "Code repository is missing.", + "corresponding_author", + "Add a repository link or explain why code cannot be shared." + ); + } + + if (code.repository?.url && !code.repository.commit) { + addFinding( + findings, + "commit_missing", + "medium", + "Code repository is not pinned to a commit.", + "corresponding_author", + "Add an immutable commit or release tag." + ); + } + + if (!code.environment) { + addFinding( + findings, + "environment_missing", + "medium", + "Runtime environment is not described.", + "reproducibility_reviewer", + "Add Dockerfile, lockfile, or environment file details." + ); + } + + if (!code.reproductionCommand) { + addFinding( + findings, + "reproduction_command_missing", + "low", + "Reproduction command is not recorded.", + "reproducibility_reviewer", + "Add the command used to rebuild the reported outputs." + ); + } + + return { + id: "code", + status: findings.some((finding) => finding.severity === "high") ? "blocked" : findings.length ? "review" : "ready", + findings + }; +} + +function buildClaimChecks(input) { + const artifactIds = new Set((input.artifacts || []).map((artifact) => artifact.id)); + return (input.claims || []).map((claim) => { + const findings = []; + const linkedArtifacts = claim.evidenceArtifactIds || []; + + if (claim.requiresData && linkedArtifacts.length === 0) { + addFinding( + findings, + "claim_data_evidence_missing", + "high", + `Claim ${claim.id} needs linked data evidence.`, + "corresponding_author", + "Link a dataset, figure source, or analysis output." + ); + } + + const missingArtifacts = linkedArtifacts.filter((artifactId) => !artifactIds.has(artifactId)); + if (missingArtifacts.length) { + addFinding( + findings, + "claim_artifact_not_found", + "high", + `Claim ${claim.id} references missing artifacts: ${missingArtifacts.join(", ")}.`, + "corresponding_author", + "Attach the missing artifacts or update the evidence links." + ); + } + + if (claim.requiresEthics && !input.ethics?.approval?.protocolId) { + addFinding( + findings, + "claim_ethics_protocol_missing", + "high", + `Claim ${claim.id} needs an ethics protocol reference.`, + "ethics_board", + "Add the protocol id that covers this claim." + ); + } + + return { + id: claim.id, + status: findings.some((finding) => finding.severity === "high") ? "blocked" : findings.length ? "review" : "ready", + findings + }; + }); +} + +function buildReviewerActions(checks) { + return checks + .flatMap((check) => check.findings.map((finding) => ({ + checkId: check.id, + code: finding.code, + severity: finding.severity, + owner: finding.owner, + action: finding.action + }))) + .sort((a, b) => SEVERITY_WEIGHT[b.severity] - SEVERITY_WEIGHT[a.severity] || a.code.localeCompare(b.code)); +} + +function buildAuditEvents(result, input) { + const baseEvents = [ + { + type: "ethics_data_readiness_evaluated", + projectId: input.project?.id, + status: result.status, + riskScore: result.riskScore, + at: input.generatedAt + }, + { + type: "reviewer_actions_created", + projectId: input.project?.id, + actionCount: result.reviewerActions.length, + at: input.generatedAt + } + ]; + + return baseEvents.map((event) => ({ + ...event, + signature: signEvent(event, input.signingKey) + })); +} + +export function evaluateEthicsDataAvailability(input) { + if (!input?.generatedAt || Number.isNaN(new Date(input.generatedAt).getTime())) { + throw new Error("A valid generatedAt timestamp is required."); + } + if (!input.signingKey || input.signingKey.length < 8) { + throw new Error("A signingKey of at least 8 characters is required."); + } + + const primaryChecks = [buildEthicsCheck(input), buildDataCheck(input), buildCodeCheck(input)]; + const claimChecks = buildClaimChecks(input); + const checks = [...primaryChecks, ...claimChecks]; + const status = worstStatus(checks); + const reviewerActions = buildReviewerActions(checks); + const riskScore = Math.min( + 100, + checks.flatMap((check) => check.findings).reduce((total, finding) => total + finding.weight, 0) + ); + + const result = { + projectId: input.project?.id, + projectTitle: input.project?.title, + generatedAt: input.generatedAt, + status, + riskScore, + dashboard: { + ready: checks.filter((check) => check.status === "ready").length, + review: checks.filter((check) => check.status === "review").length, + blocked: checks.filter((check) => check.status === "blocked").length, + reviewerActions: reviewerActions.length + }, + checks, + reviewerActions + }; + + result.manifestDigest = digest({ + projectId: result.projectId, + generatedAt: result.generatedAt, + checks: result.checks, + reviewerActions: result.reviewerActions + }); + result.auditEvents = buildAuditEvents(result, input); + return result; +} + +export function renderEthicsDataAvailabilityReport(result) { + const lines = [ + "Ethics + Data Availability", + `${result.projectTitle || result.projectId}: ${result.status} (${result.riskScore}/100)`, + `Checks ready/review/blocked: ${result.dashboard.ready}/${result.dashboard.review}/${result.dashboard.blocked}`, + `Manifest: ${result.manifestDigest.slice(0, 16)}`, + "", + "Reviewer actions:" + ]; + + for (const action of result.reviewerActions.slice(0, 8)) { + lines.push(`- ${action.severity} ${action.code}: ${action.action}`); + } + + if (result.reviewerActions.length === 0) { + lines.push("- none"); + } + + return lines.join("\n"); +} diff --git a/ethics-data-availability-checker/test/ethics-data-availability-checker.test.js b/ethics-data-availability-checker/test/ethics-data-availability-checker.test.js new file mode 100644 index 0000000..453e2ac --- /dev/null +++ b/ethics-data-availability-checker/test/ethics-data-availability-checker.test.js @@ -0,0 +1,144 @@ +import assert from "node:assert/strict"; +import { readFile } from "node:fs/promises"; +import test from "node:test"; +import { + digest, + evaluateEthicsDataAvailability, + renderEthicsDataAvailabilityReport +} from "../src/ethics-data-availability-checker.js"; + +async function loadSample() { + const samplePath = new URL("../data/sample-ethics-input.json", import.meta.url); + return JSON.parse(await readFile(samplePath, "utf8")); +} + +test("blocks missing claim artifacts while keeping controlled data in review", async () => { + const result = evaluateEthicsDataAvailability(await loadSample()); + const checks = new Map(result.checks.map((check) => [check.id, check])); + + assert.equal(result.status, "blocked"); + assert.equal(checks.get("ethics").status, "review"); + assert.equal(checks.get("data").status, "ready"); + assert.equal(checks.get("code").status, "ready"); + assert.equal(checks.get("claim-secondary-model").status, "blocked"); + assert.ok(result.reviewerActions.some((action) => action.code === "claim_artifact_not_found")); +}); + +test("flags public sensitive data and consent scope conflicts", async () => { + const input = await loadSample(); + input.dataAvailability.repository.visibility = "public"; + const result = evaluateEthicsDataAvailability(input); + const codes = result.reviewerActions.map((action) => action.code); + + assert.equal(result.status, "blocked"); + assert.ok(codes.includes("sensitive_data_public")); + assert.ok(codes.includes("consent_scope_conflict")); +}); + +test("handles full timestamp approval expiry values", async () => { + const input = await loadSample(); + input.ethics.approval.expiresAt = "2026-05-15T12:00:00.000Z"; + const result = evaluateEthicsDataAvailability(input); + const codes = result.reviewerActions.map((action) => action.code); + + assert.equal(result.status, "blocked"); + assert.ok(codes.includes("approval_expired")); +}); + +test("treats timezone-less approval timestamps as UTC", async () => { + const input = await loadSample(); + input.ethics.approval.expiresAt = "2026-05-15T12:00:00.000"; + const result = evaluateEthicsDataAvailability(input); + + assert.ok(result.reviewerActions.some((action) => action.code === "approval_expired")); +}); + +test("flags approval, consent, repository, license, and code gaps", async () => { + const input = await loadSample(); + input.ethics.approval = { status: "pending", expiresAt: "bad-date" }; + input.ethics.consent = { status: "partial", scope: "internal_only" }; + input.ethics.safeguards = []; + input.ethics.transferBasis = ""; + input.dataAvailability.statement = "TBD"; + input.dataAvailability.repository = {}; + input.dataAvailability.accession = ""; + input.dataAvailability.accessCommittee = ""; + input.dataAvailability.license = ""; + input.dataAvailability.embargoReason = ""; + input.codeAvailability = { + repository: { url: "https://git.example.org/neuroimmune/analysis" } + }; + input.claims.push({ + id: "claim-unlinked", + text: "Unlinked claim needs checks.", + requiresData: true, + requiresEthics: true, + evidenceArtifactIds: [] + }); + + const result = evaluateEthicsDataAvailability(input); + const codes = result.reviewerActions.map((action) => action.code); + + assert.ok(codes.includes("approval_missing")); + assert.ok(codes.includes("consent_incomplete")); + assert.ok(codes.includes("vulnerable_group_safeguards_missing")); + assert.ok(codes.includes("transfer_basis_missing")); + assert.ok(codes.includes("statement_too_short")); + assert.ok(codes.includes("repository_missing")); + assert.ok(codes.includes("access_committee_missing")); + assert.ok(codes.includes("license_missing")); + assert.ok(codes.includes("embargo_reason_missing")); + assert.ok(codes.includes("commit_missing")); + assert.ok(codes.includes("environment_missing")); + assert.ok(codes.includes("reproduction_command_missing")); + assert.ok(codes.includes("claim_data_evidence_missing")); + assert.ok(codes.includes("claim_ethics_protocol_missing")); +}); + +test("flags unparseable approval expiry values", async () => { + const input = await loadSample(); + input.ethics.approval.expiresAt = "not-a-date"; + input.claims[1].evidenceArtifactIds = ["artifact-cytokine-table"]; + const result = evaluateEthicsDataAvailability(input); + + assert.equal(result.status, "review"); + assert.ok(result.reviewerActions.some((action) => action.code === "approval_expiry_invalid")); +}); + +test("allows a clean ready packet", async () => { + const input = await loadSample(); + input.ethics.approval.expiresAt = "2027-05-30"; + input.claims[1].evidenceArtifactIds = ["artifact-cytokine-table"]; + const result = evaluateEthicsDataAvailability(input); + + assert.equal(result.status, "ready"); + assert.equal(result.riskScore, 0); + assert.equal(result.dashboard.blocked, 0); + assert.equal(result.reviewerActions.length, 0); +}); + +test("requires generatedAt and signing key", async () => { + const input = await loadSample(); + + assert.throws(() => evaluateEthicsDataAvailability({ ...input, generatedAt: "not-a-date" }), /generatedAt/); + assert.throws(() => evaluateEthicsDataAvailability({ ...input, signingKey: "short" }), /signingKey/); +}); + +test("produces deterministic digests and signatures", async () => { + const input = await loadSample(); + const first = evaluateEthicsDataAvailability(input); + const second = evaluateEthicsDataAvailability(input); + + assert.equal(first.manifestDigest, second.manifestDigest); + assert.ok(first.auditEvents.every((event) => /^[a-f0-9]{64}$/.test(event.signature))); + assert.equal(digest({ b: [2, 3], a: 1 }), digest({ a: 1, b: [2, 3] })); +}); + +test("renders a reviewer friendly report", async () => { + const result = evaluateEthicsDataAvailability(await loadSample()); + const report = renderEthicsDataAvailabilityReport(result); + + assert.match(report, /Ethics \+ Data Availability/); + assert.match(report, /claim_artifact_not_found/); + assert.match(report, new RegExp(result.manifestDigest.slice(0, 12))); +}); From eeda7213e06b9b437c70b79bc4332c1bae83e670 Mon Sep 17 00:00:00 2001 From: evilfps <208441420+evilfps@users.noreply.github.com> Date: Sat, 16 May 2026 21:54:31 +0530 Subject: [PATCH 2/2] Clarify demo video asset --- ethics-data-availability-checker/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethics-data-availability-checker/README.md b/ethics-data-availability-checker/README.md index aa30041..1c0f4b5 100644 --- a/ethics-data-availability-checker/README.md +++ b/ethics-data-availability-checker/README.md @@ -23,7 +23,8 @@ npm run demo ## Demo Assets - `docs/demo.svg` -- `docs/demo.webm` +- short demo video: `docs/demo.webm` +- `docs/demo.gif` ## API