Honesty doctrine. Every candidate anomaly is an artifact until proven otherwise; in-sample results are never findings; past statistical regularity does not imply future returns. This is research on statistical properties of market data — not investment advice, not a trading system.

Code / tools/new_finding.py

tools/new_finding.py 119 lines
#!/usr/bin/env python3
# =============================================================================
#  Project   : anomaly-atlas
#  File      : tools/new_finding.py
#  Purpose   : Scaffold a compliant atlas entry — refuses incomplete provenance
#  Author    : Simon-Pierre Boucher
#  Contact   : contact@spboucher.ai
#  Data src  : hfmarketdata.io (sole data source)
#  Created   : 2026-08-12
#  Modified  : 2026-08-12
#  Platform  : macOS / Apple Silicon (arm64)
#  License   : All rights reserved (research code)
# =============================================================================
"""Create atlas/<anomaly_id>/<version>/ from a completed finding payload.

Refuses to create an entry unless BOTH a complete provenance.json and a
confidence.md are supplied (CLAUDE.md §3, §10). Level 0 findings are refused
outright — in-sample-only output never enters the atlas.

Usage:
    python3 tools/new_finding.py <anomaly_id> <version> \\
        --finding finding.json --provenance provenance.json --confidence confidence.md

Required provenance keys:
    commit, config, data_manifest_hash, hardware_manifest, generated_utc,
    n_hypotheses_tested, correction_method, oos_status
Required confidence.md content: a 'Level: <1|2|3>' line plus front matter.
"""

from __future__ import annotations

import argparse
import json
import re
import shutil
import sys
from pathlib import Path

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

PROVENANCE_KEYS = (
    "commit",
    "config",
    "data_manifest_hash",
    "hardware_manifest",
    "generated_utc",
    "n_hypotheses_tested",
    "correction_method",
    "oos_status",
)
FINDING_ATTRIBUTION = {
    "author": "Simon-Pierre Boucher",
    "contact": "contact@spboucher.ai",
    "data_source": "hfmarketdata.io",
}


def fail(msg: str) -> None:
    sys.exit(f"REFUSED: {msg}")


def validate_provenance(path: Path) -> dict:
    try:
        prov = json.loads(path.read_text())
    except (OSError, json.JSONDecodeError) as exc:
        fail(f"provenance.json unreadable/invalid: {exc}")
    missing = [k for k in PROVENANCE_KEYS if not prov.get(k)]
    if missing:
        fail(f"provenance.json incomplete — missing/empty: {', '.join(missing)}")
    return prov


def validate_confidence(path: Path) -> int:
    try:
        text = path.read_text()
    except OSError as exc:
        fail(f"confidence.md unreadable: {exc}")
    m = re.search(r"^Level:\s*([0-3])\b", text, re.MULTILINE)
    if not m:
        fail("confidence.md must contain a 'Level: <0-3>' line with evidence")
    level = int(m.group(1))
    if level < 1:
        fail("Level 0 (in-sample only) never enters the atlas — scan output only")
    return level


def main() -> None:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("anomaly_id")
    ap.add_argument("version")
    ap.add_argument("--finding", required=True, type=Path)
    ap.add_argument("--provenance", required=True, type=Path)
    ap.add_argument("--confidence", required=True, type=Path)
    args = ap.parse_args()

    prov = validate_provenance(args.provenance)
    level = validate_confidence(args.confidence)
    try:
        finding = json.loads(args.finding.read_text())
    except (OSError, json.JSONDecodeError) as exc:
        fail(f"finding.json unreadable/invalid: {exc}")

    finding.update(FINDING_ATTRIBUTION)
    finding.setdefault("anomaly_id", args.anomaly_id)
    finding["confidence_level"] = level

    dest = REPO_ROOT / "atlas" / args.anomaly_id / args.version
    if dest.exists():
        fail(f"{dest.relative_to(REPO_ROOT)} already exists — bump the version")
    dest.mkdir(parents=True)
    (dest / "finding.json").write_text(json.dumps(finding, indent=2) + "\n")
    (dest / "provenance.json").write_text(json.dumps(prov, indent=2) + "\n")
    shutil.copy(args.confidence, dest / "confidence.md")
    print(f"atlas entry created: {dest.relative_to(REPO_ROOT)} (Level {level})")


if __name__ == "__main__":
    main()