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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# deepevents.ai
deepevents.ai main codebase

## Modules

- [`project-repository-version-control`](./project-repository-version-control) - runnable prototype for citable scientific project repositories, version control, reproducibility checks, and export metadata.
60 changes: 60 additions & 0 deletions project-repository-version-control/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Project Repository & Version Control

This module is a self-contained implementation for SCIBASE.AI issue #10. It models the scientific project repository as a citable, versioned, reproducible workspace with manuscript, data, code, notebook, result, protocol, and metadata components.

## What It Covers

- Repository structure for `manuscript/`, `data/`, `code/`, `notebooks/`, `results/`, `protocols/`, and `metadata.json`.
- Hash-based manifest generation for file integrity and reproducible export bundles.
- Commit history, branch timelines, semantic version DOI metadata, forks, attribution, and merge request summaries.
- Markdown/notebook-aware diff summaries for review workflows.
- Computation-aware reproducibility checks for pipeline presence, raw data hashes, expected outputs, metadata schema, and sandbox execution.
- Auto-generated APA, MLA, and BibTeX citations.
- JSON API and browser dashboard for reviewer smoke testing.

## Run Locally

```bash
cd project-repository-version-control
npm test
npm start
```

Then open `http://localhost:4129`.

## API Surface

- `GET /api/dashboard`
- `GET /api/repositories/repo-organoid-response`
- `GET /api/repositories/repo-organoid-response/manifest`
- `GET /api/repositories/repo-organoid-response/merge-request`
- `GET /api/repositories/repo-organoid-response/reproducibility`
- `GET /api/repositories/repo-organoid-response/citation?style=APA|MLA|BibTeX`
- `GET /api/repositories/repo-organoid-response/export`

## Requirement Mapping

- Repository components: represented in `demoRepository.files`.
- File and metadata versioning: implemented by `buildManifest`, hash generation, branches, and commits.
- Collaboration and forking: represented by `forks`, `mergeRequests`, branch timelines, discussion, and reviewer metadata.
- In-browser editors and diffs: implemented as Markdown/notebook-aware diff summaries and dashboard review surfaces.
- Computation-aware reproducibility: implemented by `runReproducibilityCheck`.
- Repository identifiers and citation: implemented by DOI generation and `buildCitation`.
- Programmatic access and export: implemented by the JSON API and `buildExportBundle`.

## Verification

```bash
npm test
node src/server.js
```

Optional smoke checks:

```bash
curl -s http://localhost:4129/api/dashboard
curl -s http://localhost:4129/api/repositories/repo-organoid-response/manifest
curl -s "http://localhost:4129/api/repositories/repo-organoid-response/citation?style=BibTeX"
```

Demo artifacts are committed under `docs/demo/`, including `dashboard.png` and `project-repository-version-control-demo.mp4`.
8 changes: 8 additions & 0 deletions project-repository-version-control/docs/demo-script.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Demo Script

1. Run `npm test` to verify manifest, commit, diff, reproducibility, citation, and export logic.
2. Run `npm start` and open `http://localhost:4129`.
3. Confirm the dashboard shows repository DOI, file count, component list, and integrity hash.
4. Inspect the merge request card for changed files and Markdown/notebook-aware diff types.
5. Confirm the reproducibility checks all pass.
6. Review the generated citation and export bundle metadata.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
14 changes: 14 additions & 0 deletions project-repository-version-control/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@scibase/project-repository-version-control",
"version": "0.1.0",
"private": true,
"description": "Self-contained scientific project repository and version-control prototype for SCIBASE.AI issue #10.",
"type": "module",
"scripts": {
"start": "node src/server.js",
"test": "node --test test/*.test.js"
},
"engines": {
"node": ">=20"
}
}
33 changes: 33 additions & 0 deletions project-repository-version-control/public/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const dashboard = await fetch("/api/dashboard").then((response) => response.json());

document.querySelector("#repoTitle").textContent = dashboard.manifest.title;
document.querySelector("#manifest").innerHTML = [
stat("DOI", dashboard.manifest.doi),
stat("Files", dashboard.manifest.files.length),
stat("Components", Object.keys(dashboard.manifest.components).join(", ")),
stat("Integrity", dashboard.manifest.integrityHash.slice(0, 16))
].join("");

document.querySelector("#mergeRequest").innerHTML = `
<div class="callout">
<strong>${dashboard.mergeRequest.id}</strong>
<span>${dashboard.mergeRequest.status}</span>
</div>
<ul>
${dashboard.mergeRequest.diffs.map((diff) => `<li>${diff.path} · ${diff.type} · ${diff.hunks.length} hunks</li>`).join("")}
</ul>
`;

document.querySelector("#checks").innerHTML = `
<div class="status ${dashboard.reproducibility.status}">${dashboard.reproducibility.status}</div>
<ul>
${dashboard.reproducibility.checks.map((check) => `<li>${check.passed ? "PASS" : "FAIL"} · ${check.name}</li>`).join("")}
</ul>
`;

document.querySelector("#citation").textContent = dashboard.citation.apa;
document.querySelector("#export").textContent = `${dashboard.exportBundle.fileName} · ${dashboard.exportBundle.cliCommand}`;

function stat(label, value) {
return `<div><span>${label}</span><strong>${String(value)}</strong></div>`;
}
41 changes: 41 additions & 0 deletions project-repository-version-control/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SCIBASE Project Repository</title>
<link rel="stylesheet" href="/styles.css" />
</head>
<body>
<main class="shell">
<header>
<p>SCIBASE.AI / issue #10</p>
<h1>Project Repository & Version Control</h1>
</header>
<section class="grid">
<article class="panel hero">
<p class="label">Repository</p>
<h2 id="repoTitle">Loading...</h2>
<div id="manifest" class="stats"></div>
</article>
<article class="panel">
<p class="label">Version Control</p>
<h2>Commit history and merge requests</h2>
<div id="mergeRequest"></div>
</article>
<article class="panel">
<p class="label">Reproducibility</p>
<h2>Sandbox validation</h2>
<div id="checks"></div>
</article>
<article class="panel">
<p class="label">Citation & Export</p>
<h2>Citable version bundle</h2>
<code id="citation"></code>
<p id="export"></p>
</article>
</section>
</main>
<script type="module" src="/app.js"></script>
</body>
</html>
153 changes: 153 additions & 0 deletions project-repository-version-control/public/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
:root {
--ink: #111615;
--muted: #64706d;
--line: #d7ded9;
--paper: #f3f6f1;
--panel: #ffffff;
--green: #17664c;
--blue: #285f8f;
}

* {
box-sizing: border-box;
}

body {
margin: 0;
background: var(--paper);
color: var(--ink);
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.shell {
max-width: 1280px;
margin: 0 auto;
padding: 32px;
}

header {
display: flex;
align-items: end;
justify-content: space-between;
gap: 24px;
margin-bottom: 24px;
}

header p,
.label {
color: var(--muted);
font-size: 12px;
font-weight: 900;
letter-spacing: 0.08em;
text-transform: uppercase;
}

h1,
h2,
p {
margin: 0;
}

h1 {
max-width: 820px;
font-size: clamp(38px, 6vw, 76px);
line-height: 0.95;
letter-spacing: 0;
}

h2 {
margin-top: 8px;
font-size: 24px;
}

.grid {
display: grid;
grid-template-columns: 1.1fr 0.9fr;
gap: 16px;
}

.panel {
min-height: 260px;
border: 1px solid var(--line);
background: var(--panel);
padding: 24px;
}

.hero {
grid-row: span 2;
}

.stats {
display: grid;
gap: 12px;
margin-top: 26px;
}

.stats div,
.callout,
li,
code,
#export,
.status {
border-top: 1px solid var(--line);
padding-top: 12px;
}

.stats span {
display: block;
color: var(--muted);
font-size: 12px;
font-weight: 900;
text-transform: uppercase;
}

.stats strong {
display: block;
margin-top: 5px;
overflow-wrap: anywhere;
}

.callout {
display: flex;
justify-content: space-between;
gap: 14px;
margin-top: 18px;
}

.callout span,
.status {
color: var(--green);
font-weight: 900;
text-transform: uppercase;
}

ul {
margin: 18px 0 0;
padding: 0;
list-style: none;
}

li {
line-height: 1.35;
}

code,
#export {
display: block;
margin-top: 18px;
color: var(--blue);
line-height: 1.5;
white-space: normal;
}

@media (max-width: 820px) {
.shell {
padding: 18px;
}

header,
.grid {
display: grid;
grid-template-columns: 1fr;
}
}
Loading