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
1 change: 1 addition & 0 deletions sample-custody-quality-graph-guard/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
reports/frames/
40 changes: 40 additions & 0 deletions sample-custody-quality-graph-guard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Sample Custody Quality Graph Guard

Self-contained reviewer artifact for SCIBASE issue #17, focused on sample custody and cold-chain quality before sample nodes are exposed in scientific knowledge graph entity pages or recommendations.

This slice is intentionally narrow. It does not duplicate broad graph extraction/navigation, geospatial sample provenance, organism/strain boundaries, biological accession crosswalks, measurement harmonization, software dependency provenance, evidence freshness, temporal validity, image metadata provenance, funding provenance, or clinical-trial registry work.

## What It Checks

- Collection provenance has timestamps, site ids, and protocol ids.
- Preservation protocol and preservation timing are present and inside policy windows.
- Chain-of-custody handoffs are complete, signed, and contiguous.
- Cold-chain temperature logs exist and have no policy-breaking excursions.
- Freeze-thaw cycles and integrity scores meet quality thresholds.
- Required sample-to-protocol, sample-to-dataset, and sample-to-assay graph edges are present.
- Unsafe sample graph edges are held with deterministic remediation actions.

## Local Verification

```sh
npm run check
npm test
npm run demo
npm run verify-video
```

`npm run demo` writes reviewer artifacts to `reports/`:

- `clean-audit.json`
- `risky-audit.json`
- `risky-review.md`
- `summary.svg`
- `manifest.json`
- `demo.mp4`

## Requirement Mapping

- Scientific knowledge graph integration: evaluates sample nodes before entity pages and recommendations publish.
- Provenance quality: links custody, preservation, temperature, and assay-quality evidence to graph edge publication.
- Recommendation safety: holds degraded or uncertain sample edges before they can influence discovery paths.
- Reviewer demonstration: synthetic clean/risky packets produce JSON, Markdown, SVG, and MP4 artifacts without credentials or external services.
42 changes: 42 additions & 0 deletions sample-custody-quality-graph-guard/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use strict";

const fs = require("node:fs");
const path = require("node:path");
const {
evaluateSampleCustodyGraph,
renderMarkdownReport,
renderSvgSummary
} = require("./index");
const { cleanPacket, riskyPacket } = require("./sample-data");

const reportsDir = path.join(__dirname, "reports");
fs.mkdirSync(reportsDir, { recursive: true });

const clean = evaluateSampleCustodyGraph(cleanPacket, { now: "2026-06-01T10:45:00.000Z" });
const risky = evaluateSampleCustodyGraph(riskyPacket, { now: "2026-06-01T10:45:00.000Z" });
const manifest = {
module: "sample-custody-quality-graph-guard",
issue: 17,
generatedAt: "2026-06-01T10:45:00.000Z",
scenarios: [
{ name: "clean", status: clean.status, fingerprint: clean.fingerprint, findings: clean.findings.length },
{ name: "risky", status: risky.status, fingerprint: risky.fingerprint, findings: risky.findings.length }
],
artifacts: [
"reports/clean-audit.json",
"reports/risky-audit.json",
"reports/risky-review.md",
"reports/summary.svg",
"reports/demo.mp4"
]
};

fs.writeFileSync(path.join(reportsDir, "clean-audit.json"), `${JSON.stringify(clean, null, 2)}\n`);
fs.writeFileSync(path.join(reportsDir, "risky-audit.json"), `${JSON.stringify(risky, null, 2)}\n`);
fs.writeFileSync(path.join(reportsDir, "risky-review.md"), renderMarkdownReport(risky, riskyPacket));
fs.writeFileSync(path.join(reportsDir, "summary.svg"), renderSvgSummary(risky));
fs.writeFileSync(path.join(reportsDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`);

console.log(`Clean status: ${clean.status} (${clean.fingerprint})`);
console.log(`Risky status: ${risky.status} (${risky.fingerprint})`);
console.log(`Wrote reviewer artifacts to ${reportsDir}`);
Loading