**Motivations:** - Implémenter le workflow complet de démonstration Collatz (commandes.md) - Permettre la reprise après interruption au palier D20 **Evolutions:** - Scripts 01-12 et run-full-workflow alignés sur commandes.md sections 1-10 - collatz_recover_noyau.py : recréation de noyau_post_D20 à partir du CSV candidats - Option --resume-from D20 dans collatz_k_pipeline pour reprendre sans recalculer D18-D19-F15 - Détection automatique : si candidats_D20 existe sans noyau_post_D20, récupération puis poursuite - Filtres --cible=critique et --modulo dans collatz_fusion_pipeline - ROOT par défaut = collatz_k_scripts (plus data/source vide) **Pages affectées:** - .gitignore (__pycache__, out/) - applications/collatz/collatz_k_scripts/*.py - applications/collatz/scripts/*.sh - applications/collatz/scripts/README.md
81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
collatz_document_base_states.py
|
|
|
|
If JSON has state info (e.g. per-palier state), document each state.
|
|
Outputs MD describing each state.
|
|
|
|
Usage: python collatz_document_base_states.py --base-projective JSON --output MD
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
def load_json(path: str) -> dict[str, Any]:
|
|
"""Load JSON file."""
|
|
p = Path(path)
|
|
if not p.exists():
|
|
raise FileNotFoundError(f"File not found: {path}")
|
|
return json.loads(p.read_text(encoding="utf-8"))
|
|
|
|
|
|
def is_state_info(obj: Any) -> bool:
|
|
"""Check if object looks like a state (has m, mod, etc.)."""
|
|
if not isinstance(obj, dict):
|
|
return False
|
|
return "m" in obj or "mod" in obj
|
|
|
|
|
|
def document_states(data: dict[str, Any]) -> list[str]:
|
|
"""Extract and document each state from JSON."""
|
|
lines: list[str] = ["# Base states documentation", ""]
|
|
|
|
for key, val in sorted(data.items()):
|
|
if not is_state_info(val):
|
|
continue
|
|
val = val if isinstance(val, dict) else {}
|
|
lines.append(f"## State {key}")
|
|
lines.append("")
|
|
for k, v in sorted(val.items()):
|
|
if isinstance(v, list) and len(v) > 10:
|
|
lines.append(f"- **{k}**: {len(v)} items")
|
|
else:
|
|
lines.append(f"- **{k}**: {v}")
|
|
lines.append("")
|
|
|
|
if len(lines) <= 2:
|
|
lines.append("No state information found in JSON.")
|
|
|
|
return lines
|
|
|
|
|
|
def run(base_path: str, output_path: str) -> None:
|
|
"""Run and write output."""
|
|
try:
|
|
data = load_json(base_path)
|
|
lines = document_states(data)
|
|
except FileNotFoundError as e:
|
|
lines = ["# Base states documentation", "", str(e)]
|
|
except json.JSONDecodeError as e:
|
|
lines = ["# Base states documentation", "", f"Invalid JSON: {e}"]
|
|
|
|
Path(output_path).write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="Document base states from JSON")
|
|
parser.add_argument("--base-projective", required=True, help="Path to base-projective JSON")
|
|
parser.add_argument("--output", required=True, help="Path to output MD file")
|
|
args = parser.parse_args()
|
|
run(args.base_projective, args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|