Paper Support#

Source: examples/paper_support.py

Introduction#

Run a tiny offline study, aggregate component-owned contributions with durable run evidence, then explicitly export both the support contract and a compilable paper draft. No paper files are written by run_study or collection alone.

Technical Implementation#

The example passes a versioned JSON-compatible component packet to collect_paper_support. The same packet and artifact root are passed to export_paper_draft, which is called separately with explicit overwrite and completeness requirements. Strict failures expose PaperDraftIncompleteError.

  1from __future__ import annotations
  2
  3from pathlib import Path
  4
  5import design_research_experiments as drex
  6
  7
  8def main() -> None:
  9    """Run the offline example and explicitly export its paper support."""
 10    output_dir = Path("artifacts/example-paper-support")
 11    study = drex.Study(
 12        study_id="example-paper-support",
 13        title="Example Paper Support Study",
 14        description="A deterministic demonstration of evidence-grounded paper support.",
 15        factors=(
 16            drex.Factor(
 17                name="prompt_frame",
 18                description="Prompt framing condition",
 19                kind=drex.FactorKind.MANIPULATED,
 20                levels=(
 21                    drex.Level(name="neutral", value="neutral"),
 22                    drex.Level(name="challenge", value="challenge"),
 23                ),
 24            ),
 25        ),
 26        hypotheses=(
 27            drex.Hypothesis(
 28                hypothesis_id="h1",
 29                label="Prompt framing effect",
 30                statement="Prompt framing changes the primary outcome.",
 31                independent_vars=("prompt_frame",),
 32                dependent_vars=("primary_outcome",),
 33            ),
 34        ),
 35        outcomes=(
 36            drex.OutcomeSpec(
 37                name="primary_outcome",
 38                source_table="runs",
 39                column="primary_outcome",
 40                aggregation="mean",
 41                primary=True,
 42            ),
 43        ),
 44        analysis_plans=(
 45            drex.AnalysisPlan(
 46                analysis_plan_id="ap1",
 47                hypothesis_ids=("h1",),
 48                tests=("difference_in_means",),
 49                outcomes=("primary_outcome",),
 50            ),
 51        ),
 52        output_dir=output_dir,
 53    )
 54
 55    def run_condition(_run_spec: drex.RunSpec, condition: drex.Condition) -> drex.RunOutput:
 56        """Return one deterministic raw response and outcome."""
 57        frame = str(condition.factor_assignments["prompt_frame"])
 58        return drex.RunOutput(
 59            outputs={"response": f"retained response for {frame}"},
 60            metrics={"primary_outcome": float(frame == "challenge")},
 61        )
 62
 63    drex.run_study(
 64        study,
 65        condition_runner=run_condition,
 66        checkpoint=False,
 67        show_progress=False,
 68    )
 69    component_packet = {
 70        "schema_version": "0.1.0",
 71        "source": {
 72            "package": "example-method-library",
 73            "package_version": "1.0.0",
 74            "component_type": "prompt-method",
 75            "component_id": "prompt-framing",
 76        },
 77        "contributions": [
 78            {
 79                "contribution_id": "example:prompt-framing:background",
 80                "section": "background",
 81                "kind": "bullet",
 82                "text": "Prompt framing was treated as an experimental manipulation.",
 83                "evidence_basis": "configured",
 84                "citation_keys": ["example2026"],
 85                "evidence_refs": ["study.yaml#/factors/0"],
 86            },
 87            {
 88                "contribution_id": "example:prompt-framing:result",
 89                "section": "results",
 90                "kind": "paragraph",
 91                "text": "The retained difference-in-means analysis completed.",
 92                "evidence_basis": "analyzed",
 93                "citation_keys": [],
 94                "evidence_refs": ["analysis/example-result.json"],
 95                "metadata": {"hypothesis_ids": ["h1"]},
 96            },
 97        ],
 98        "references": [
 99            {
100                "key": "example2026",
101                "title": "Example curated source",
102                "raw_text": "@misc{example2026, title={Example curated source}}",
103            }
104        ],
105        "reporting_gaps": [],
106    }
107    support = drex.collect_paper_support(study, component_packets=(component_packet,))
108    support_paths = drex.export_paper_support(support, output_dir=output_dir, overwrite=True)
109    try:
110        paths = drex.export_paper_draft(
111            study,
112            component_packets=(component_packet,),
113            overwrite=True,
114            require_complete=True,
115        )
116    except drex.PaperDraftIncompleteError as exc:
117        paths = exc.paths
118    print(f"Draft status: {support.draft_status}")
119    print(f"Run accounting: {dict(support.run_accounting)}")
120    print(f"Paper outline: {support_paths['paper_outline.md']}")
121    print(f"LaTeX draft: {paths['main.tex']}")
122
123
124if __name__ == "__main__":
125    main()

Expected Results#

Run Command

PYTHONPATH=src python examples/paper_support.py

The script records two successful run-evidence directories, writes the support files, and assembles main.tex, Markdown, sections, references, and a draft manifest beneath artifacts/example-paper-support/paper-draft.