from __future__ import annotations import argparse import json from pathlib import Path from typing import Any def read_json(path: Path) -> dict[str, Any]: if not path.exists(): return {} return json.loads(path.read_text(encoding="utf-8")) def artifact_status(path: Path) -> dict[str, Any]: data = read_json(path) return { "path": str(path), "exists": path.exists(), "schema": data.get("schema"), "status": data.get("status"), "counts": data.get("counts") or {}, } def build_status(root: Path) -> dict[str, Any]: registry = read_json(root / "plugins/1c/metadata/moxel-schema-registry.json") verification = read_json(root / "reports/1c-template-baselines/moxel-schema-registry-verification.json") pipeline = read_json(root / "reports/1c-template-baselines/moxel-discovery-pipeline.json") next_action = read_json(root / "reports/1c-template-baselines/moxel-next-action.json") next_action_check = read_json(root / "reports/1c-template-baselines/moxel-next-action-check.json") registry_counts = registry.get("counts") or {} action = next_action.get("action") if isinstance(next_action.get("action"), dict) else {} blockers = [] if int(registry_counts.get("candidate_read") or 0) > 0: blockers.append("candidate_read rules remain; run the planned named-range/property experiments.") if int(registry_counts.get("write_enabled") or 0) == 0: blockers.append("MOXCEL write is intentionally disabled until disposable-base round-trip evidence exists.") if next_action_check.get("status") not in {"ok", None}: blockers.append("next action check is failing.") if pipeline.get("status") not in {"ok", None}: blockers.append("last MOXCEL discovery pipeline did not finish cleanly.") return { "schema": "codex_1c_moxel_status.v1", "status": "ok" if pipeline.get("status") == "ok" and next_action_check.get("status") == "ok" else "partial", "registry": { "counts": registry_counts, "verified_read_targets": [ rule.get("target") for rule in registry.get("rules") or [] if isinstance(rule, dict) and rule.get("read_status") == "verified_read" ], "candidate_read_targets": [ rule.get("target") for rule in registry.get("rules") or [] if isinstance(rule, dict) and rule.get("read_status") == "candidate_read" ], }, "pipeline": { "status": pipeline.get("status"), "steps": [ {"name": step.get("name"), "status": step.get("status")} for step in pipeline.get("steps") or [] if isinstance(step, dict) ], }, "verification": { "status": verification.get("status"), "counts": verification.get("counts") or {}, }, "next_action": { "status": next_action.get("status"), "id": action.get("id"), "target": action.get("target"), "manual_action": action.get("manual_action"), "command": action.get("capture_command_with_pipeline"), "check_status": next_action_check.get("status"), }, "blockers": blockers, "artifacts": { "registry": artifact_status(root / "plugins/1c/metadata/moxel-schema-registry.json"), "verification": artifact_status(root / "reports/1c-template-baselines/moxel-schema-registry-verification.json"), "pipeline": artifact_status(root / "reports/1c-template-baselines/moxel-discovery-pipeline.json"), "next_action": artifact_status(root / "reports/1c-template-baselines/moxel-next-action.json"), "next_action_check": artifact_status(root / "reports/1c-template-baselines/moxel-next-action-check.json"), }, } def render_markdown(status: dict[str, Any]) -> str: registry = status.get("registry") or {} counts = registry.get("counts") or {} next_action = status.get("next_action") or {} lines = ["# 1C MOXCEL Status", ""] lines.append(f"- Status: `{status.get('status')}`") lines.append(f"- Rules: `{counts.get('rules')}`") lines.append(f"- Verified read: `{counts.get('verified_read')}`") lines.append(f"- Candidate read: `{counts.get('candidate_read')}`") lines.append(f"- Write enabled: `{counts.get('write_enabled')}`") lines.append(f"- Next action: `{next_action.get('id')}`") lines.append("") lines.append("## Next Action") lines.append("") lines.append(str(next_action.get("manual_action") or "")) if next_action.get("command"): lines.append("") lines.append("```powershell") lines.append(str(next_action.get("command"))) lines.append("```") lines.append("") lines.append("## Blockers") lines.append("") for blocker in status.get("blockers") or []: lines.append(f"- {blocker}") if not status.get("blockers"): lines.append("- none") lines.append("") return "\n".join(lines) def resolve_output_path(root: Path, value: str) -> Path: path = Path(value) return path if path.is_absolute() else root / path def main() -> int: parser = argparse.ArgumentParser(description="Summarize the 1C MOXCEL discovery/registry status.") parser.add_argument("--root", type=Path, default=Path(__file__).resolve().parents[1]) parser.add_argument("--output-json", default="reports/1c-template-baselines/moxel-status.json") parser.add_argument("--output-markdown", default="reports/1c-template-baselines/moxel-status.md") args = parser.parse_args() root = args.root.resolve() status = build_status(root) json_path = resolve_output_path(root, args.output_json) md_path = resolve_output_path(root, args.output_markdown) json_path.parent.mkdir(parents=True, exist_ok=True) md_path.parent.mkdir(parents=True, exist_ok=True) json_path.write_text(json.dumps(status, ensure_ascii=False, indent=2), encoding="utf-8") md_path.write_text(render_markdown(status), encoding="utf-8") print(json.dumps({"status": status["status"], "json": str(json_path), "markdown": str(md_path)}, ensure_ascii=False, indent=2)) return 0 if status["status"] in {"ok", "partial"} else 1 if __name__ == "__main__": raise SystemExit(main())