Code / tools/new_map.py

tools/new_map.py 104 lines
#!/usr/bin/env python3
# =============================================================================
#  Project   : modelmap
#  File      : tools/new_map.py
#  Purpose   : Scaffold a compliant atlas entry with provenance + confidence
#  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 atlas entry: atlas/<model_id>/<map_type>/<version>/.

An entry cannot be published without a completed provenance.json and
confidence.md (charter §3). This tool creates both as explicit stubs that
tools/publish.py refuses to export until completed.

Usage:
    python3 tools/new_map.py <model_id> <map_type> [version]
"""

from __future__ import annotations

import datetime
import json
import subprocess
import sys
from pathlib import Path

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


def git_commit() -> str:
    try:
        return subprocess.run(
            ["git", "rev-parse", "HEAD"], cwd=ROOT, capture_output=True, text=True, check=True
        ).stdout.strip()
    except subprocess.CalledProcessError:
        return "unknown"


CONFIDENCE_TEMPLATE = """---
project: modelmap
document: {model_id}/{map_type}/{version} — confidence
author: Simon-Pierre Boucher
contact: contact@spboucher.ai
website: https://modelmap.io
created: {date}
status: draft
---

# Confidence — {model_id} / {map_type} / {version}

```text
Level      : (0 anecdotal | 1 correlational | 2 method-robust | 3 causal)
Seeds      : (n)
Prompt sets: (n)
Methods in agreement : (list)
Causal verification  : (none | patching | ablation | ...)
```

**NOT PUBLISHABLE until this file states an evidence level with its support.**
"""


def main() -> int:
    if len(sys.argv) < 3:
        print(__doc__)
        return 2
    model_id, map_type = sys.argv[1], sys.argv[2]
    version = sys.argv[3] if len(sys.argv) > 3 else "v0"
    date = datetime.datetime.now(tz=datetime.UTC).date().isoformat()
    entry = ROOT / "atlas" / model_id / map_type / version
    if entry.exists():
        print(f"error: {entry.relative_to(ROOT)} already exists")
        return 1
    entry.mkdir(parents=True)
    provenance = {
        "author": "Simon-Pierre Boucher",
        "contact": "contact@spboucher.ai",
        "website": "https://modelmap.io",
        "model_id": model_id,
        "map_type": map_type,
        "version": version,
        "commit": git_commit(),
        "model_hash": "PENDING",
        "config": "PENDING",
        "seed": None,
        "hardware_manifest": "PENDING",
        "created": date,
    }
    (entry / "provenance.json").write_text(json.dumps(provenance, indent=2) + "\n")
    (entry / "confidence.md").write_text(
        CONFIDENCE_TEMPLATE.format(model_id=model_id, map_type=map_type, version=version, date=date)
    )
    print(f"scaffolded atlas/{model_id}/{map_type}/{version}")
    return 0


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