Code / tools/new_experiment.py

tools/new_experiment.py 81 lines
#!/usr/bin/env python3
# =============================================================================
#  Project   : modelmap
#  File      : tools/new_experiment.py
#  Purpose   : Scaffold a charter-compliant experiment directory (§10 block)
#  Author    : Simon-Pierre Boucher
#  Contact   : contact@spboucher.ai
#  Website   : https://modelmap.io
#  Created   : 2026-08-12
#  Modified  : 2026-08-12
#  Platform  : macOS / Apple Silicon (arm64)
#  License   : All rights reserved (research code)
# =============================================================================
"""Scaffold an experiment directory with the seven-field scientific block.

Usage:
    python3 tools/new_experiment.py experiments/micro/expX_name "one-line purpose"
"""

from __future__ import annotations

import datetime
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent

FRONT = """---
project: modelmap
document: {doc}
author: Simon-Pierre Boucher
contact: contact@spboucher.ai
website: https://modelmap.io
created: {date}
status: draft
---
"""

BLOCK = """```text
Hypothesis              : (to be registered before the first run)
Falsification criterion : (explicit kill-number, registered in advance)
Method                  : (including controls)
Baseline / null         : (shuffled labels / random directions / random init)
Result                  : (pending)
Interpretation          : (pending — with explicit confidence level)
Next experiment         : (pending)
```
"""


def main() -> int:
    if len(sys.argv) < 3:
        print(__doc__)
        return 2
    rel, purpose = sys.argv[1], sys.argv[2]
    date = datetime.datetime.now(tz=datetime.UTC).date().isoformat()
    exp = ROOT / rel
    name = exp.name
    if exp.exists():
        print(f"error: {rel} already exists")
        return 1
    (exp / "implementation").mkdir(parents=True)
    (exp / "results").mkdir()
    (exp / "README.md").write_text(
        FRONT.format(doc=name, date=date) + f"\n# {name}\n\n{purpose}\n"
    )
    (exp / "hypothesis.md").write_text(
        FRONT.format(doc=f"{name} — hypothesis", date=date)
        + f"\n# Hypothesis — {name}\n\n> {purpose}\n\n" + BLOCK
    )
    (exp / "analysis.md").write_text(
        FRONT.format(doc=f"{name} — analysis", date=date)
        + f"\n# Analysis — {name}\n\n*(pending — written only after results exist)*\n"
    )
    print(f"scaffolded {rel}")
    return 0


if __name__ == "__main__":
    sys.exit(main())