Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions review-civility-evidence-gate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Peer Review Civility And Evidence Gate

This module is a focused slice for issue #15, Community & User Reputation System. It protects the review and comment layer before content is published to project timelines or allowed to affect researcher reputation.

It is intentionally not another broad reputation ledger. The gate evaluates structured peer reviews and inline comments for:

- harassment or personal attacks
- protected or personal identity disclosures
- anonymous, blind, or double-blind reviewer identity leaks
- low structured scores that lack evidence anchors
- missing inline artifact anchors
- repeated comments that should be collapsed before reputation impact

The output is a deterministic moderation packet with blockers, warnings, redactions, withheld item IDs, and a release recommendation.

## Run

```bash
node review-civility-evidence-gate/test.js
node review-civility-evidence-gate/demo.js
```

The demo writes:

- `reports/civility-evidence-packet.json`
- `reports/civility-evidence-report.md`
- `reports/summary.svg`
- `reports/summary.png`
- `reports/demo.mp4`

## Design Notes

- Dependency-free Node.js implementation for the core logic.
- Synthetic data only. No credentials or external services.
- Evidence anchors support DOI, URLs, figure/table references, dataset IDs, commits, notebook cells, lines, protocols, sections, and artifacts.
- Reputation impact is withheld while blockers are present.
25 changes: 25 additions & 0 deletions review-civility-evidence-gate/acceptance-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Acceptance Notes

## What To Review

- `index.js` implements the peer-review civility and evidence gate.
- `sample-data.js` includes synthetic unsafe and clean packets.
- `test.js` validates blocker, redaction, anonymous leak, clean-pass, and report rendering behavior.
- `demo.js` generates the reviewer packet and visual demo artifact.

## Verification

```bash
node review-civility-evidence-gate/test.js
node review-civility-evidence-gate/demo.js
node --check review-civility-evidence-gate/index.js
node --check review-civility-evidence-gate/sample-data.js
node --check review-civility-evidence-gate/test.js
node --check review-civility-evidence-gate/demo.js
git diff --check
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,duration -of default=noprint_wrappers=1 review-civility-evidence-gate/reports/demo.mp4
```

## Expected Demo Result

The sample packet should return `hold_review_publication` with blockers for harassment, unsupported low-score claims, anonymous reviewer identity leakage, and protected identity disclosure. The clean packet should return `community_ready`.
52 changes: 52 additions & 0 deletions review-civility-evidence-gate/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const { spawnSync } = require("child_process");
const fs = require("fs");
const path = require("path");
const { evaluateReviewCivility, writeReportBundle } = require("./index");
const { samplePacket } = require("./sample-data");

const moduleDir = __dirname;
const reportsDir = path.join(moduleDir, "reports");
const result = evaluateReviewCivility(samplePacket);
const paths = writeReportBundle(result, reportsDir);
const pngPath = path.join(reportsDir, "summary.png");
const mp4Path = path.join(reportsDir, "demo.mp4");

function runCommand(command, args) {
const child = spawnSync(command, args, { encoding: "utf8" });
if (child.status !== 0) {
throw new Error(`${command} failed: ${child.stderr || child.stdout}`);
}
return child;
}

if (fs.existsSync(paths.svgPath)) {
runCommand("rsvg-convert", ["-w", "1280", "-h", "720", paths.svgPath, "-o", pngPath]);
runCommand("ffmpeg", [
"-y",
"-loop",
"1",
"-i",
pngPath,
"-t",
"12",
"-vf",
"format=yuv420p",
"-c:v",
"libx264",
"-movflags",
"+faststart",
mp4Path
]);
}

console.log(
[
`status=${result.status}`,
`blockers=${result.summary.blockers}`,
`warnings=${result.summary.warnings}`,
`redactions=${result.summary.redactions}`,
`report=${paths.markdownPath}`,
`packet=${paths.jsonPath}`,
`demo=${mp4Path}`
].join("\n")
);
Loading