Verified Paper Bundle#

Source: examples/verified_paper_bundle.py

Introduction#

Package a completed study handoff for collaborator inspection, manual reanalysis, and continued paper editing without promising automatic replay or environment recreation.

Technical Implementation#

  1. Write a tiny canonical study fixture and one retained run record.

  2. Persist one structured analysis result and a complete paper-draft tree.

  3. Explicitly select one supporting-data table while leaving an attachment out.

  4. Create the deterministic ZIP and verify every member hash without extraction.

 1from __future__ import annotations
 2
 3import json
 4from pathlib import Path
 5from tempfile import TemporaryDirectory
 6
 7import design_research_analysis as dran
 8
 9
10def _write_text(path: Path, content: str) -> None:
11    """Write one fixture file after creating its parent directory."""
12    path.parent.mkdir(parents=True, exist_ok=True)
13    path.write_text(content, encoding="utf-8")
14
15
16def _write_study_fixture(root: Path) -> None:
17    """Write the minimum verified study, evidence, analysis, and draft tree."""
18    _write_text(
19        root / "study.yaml",
20        "schema_version: 0.2.0\nstudy_id: bundle-example\n"
21        "title: Bundle example\ndescription: Deterministic fixture\n",
22    )
23    _write_text(
24        root / "manifest.json",
25        json.dumps({"schema_version": "0.2.0", "study_id": "bundle-example"}),
26    )
27    for filename in ("conditions.csv", "runs.csv", "events.csv", "evaluations.csv"):
28        _write_text(root / filename, "id\n1\n")
29    _write_text(root / "hypotheses.json", "[]\n")
30    _write_text(root / "analysis_plan.json", "[]\n")
31
32    evidence_ref = "artifacts/runs/run-1/run.json"
33    _write_text(
34        root / evidence_ref,
35        json.dumps({"schema_version": "0.1.0", "run_id": "run-1", "status": "success"}),
36    )
37    _write_text(root / "artifacts/runs/run-1/observations.jsonl", '{"event": "observed"}\n')
38    _write_text(root / "artifacts/runs/run-1/attachments/private.txt", "not selected\n")
39
40    table_ref = "artifacts/analysis/tables/result.tex"
41    _write_text(root / table_ref, "\\begin{tabular}{lr}A & 1\\\\\\end{tabular}\n")
42    (root / "artifacts/analysis/figures").mkdir(parents=True)
43    result = dran.build_analysis_result(
44        {"estimate": 1.0},
45        analysis_id="bundle-example-analysis",
46        method_id="analysis.example",
47        candidate_run_ids=("run-1",),
48        included_run_ids=("run-1",),
49        tables=(table_ref,),
50        evidence_refs=(evidence_ref,),
51    )
52    dran.write_analysis_result(result, output_dir=root)
53
54    _write_text(root / "paper-draft/main.tex", "\\documentclass{article}\n")
55    _write_text(root / "paper-draft/paper_draft.md", "# Paper draft\n")
56    _write_text(root / "paper-draft/references.bib", "")
57    _write_text(root / "paper-draft/README.md", "Author review required.\n")
58    _write_text(
59        root / "paper-draft/paper_draft_manifest.json",
60        json.dumps({"document_status": "paper-draft", "study_id": "bundle-example"}),
61    )
62    for section in ("introduction", "background", "methods", "results", "discussion"):
63        _write_text(
64            root / "paper-draft/sections" / f"{section}.tex",
65            f"\\section{{{section.title()}}}\n",
66        )
67    (root / "paper-draft/tables").mkdir()
68    (root / "paper-draft/figures").mkdir()
69    _write_text(
70        root / "artifacts/analysis/supporting-data/selected.csv",
71        "run_id,value\nrun-1,1\n",
72    )
73
74
75def main() -> None:
76    """Create and verify the example bundle in a temporary directory."""
77    with TemporaryDirectory() as temporary_dir:
78        root = Path(temporary_dir) / "study-output"
79        _write_study_fixture(root)
80        bundle = dran.create_research_bundle(
81            root,
82            supporting_data=("artifacts/analysis/supporting-data/selected.csv",),
83        )
84        verification = dran.verify_research_bundle(bundle)
85        assert verification["bundle_schema_version"] == dran.BUNDLE_SCHEMA_VERSION
86        print(f"Bundle: {bundle.name}")
87        print(f"Verified: {verification['valid']}")
88        print(f"Members: {verification['file_count']}")
89
90
91if __name__ == "__main__":
92    main()

Expected Results#

Run Command

PYTHONPATH=src python examples/verified_paper_bundle.py

Prints a successful verification summary for study-paper-draft.zip. The archive contains canonical artifacts, run and analysis records, the paper draft, sanitized environment metadata, and the explicitly selected support file; the unselected attachment is absent.

References#

  • docs/research_bundle.rst