#!/usr/bin/env python3 """Generate an implementation-stage adapter map for one module+tier batch.""" from __future__ import annotations import argparse import hashlib import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] ADAPTERS = { "Assembly": ("assembly.worker.ts", "assembly.pythonFamily", "src/WebAssembly/FreeCADCoreProbe/AssemblyRuntimeProbe.cpp"), "BIM": ("bim.worker.ts", "bim.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/BimRuntimeProbe.cpp"), "CAM": ("cam.worker.ts", "cam.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/CAMRuntimeProbe.cpp"), "Draft": ("draft.worker.ts", "draft.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/DraftRuntimeProbe.cpp"), "Fem": ("fem.worker.ts", "fem.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/FemGenericFamilyProbe.cpp"), "Import": ("import.worker.ts", "import.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/ImportRuntimeProbe.cpp"), "Material": ("material.worker.ts", "material.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MaterialKernelProbe.cpp"), "Measure": ("measure.worker.ts", "measure.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MeasureRuntimeProbe.cpp"), "Mesh": ("mesh.worker.ts", "mesh.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MeshRuntimeProbe.cpp"), "MeshPart": ("meshpart.worker.ts", "meshpart.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/MeshPartRuntimeProbe.cpp"), "Part": ("part.worker.ts", "part.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PartBoxProbe.cpp"), "PartDesign": ("partdesign-python.worker.ts", "partdesign.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PartDesignRuntimeProbe.cpp"), "Plot": ("plot-python.worker.ts", "plot.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PlotRuntimeProbe.cpp"), "Points": ("points.worker.ts", "points.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/PointsRuntimeProbe.cpp"), "ReverseEngineering": ("reverseengineering-python.worker.ts", "reverseengineering.pythonFamilyBatch", "src/Mod/ReverseEngineering/InitGui.py"), "Robot": ("robot-python.worker.ts", "robot.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/RobotRuntimeProbeFixed.cpp"), "Sandbox": ("sandbox-python.worker.ts", "sandbox.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SandboxRuntimeProbe.cpp"), "Show": ("show-python.worker.ts", "show.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/ShowRuntimeProbe.cpp"), "Sketcher": ("sketcher-python.worker.ts", "sketcher.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SketcherProbe.cpp"), "Spreadsheet": ("spreadsheet-python.worker.ts", "spreadsheet.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SpreadsheetRuntimeProbe.cpp"), "Surface": ("surface-python.worker.ts", "surface.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/SurfaceFamilyProbe.cpp"), "TechDraw": ("techdraw-python.worker.ts", "techdraw.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/TechDrawRuntimeProbe.cpp"), "TemplatePyMod": ("templatepymod-python.worker.ts", "templatepymod.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/TemplatePyModRuntimeProbe.cpp"), "OpenSCAD": ("openscad.worker.ts", "openscad.pythonFamilyBatch", "src/WebAssembly/FreeCADCoreProbe/OpenSCADRuntimeProbe.cpp"), } parser = argparse.ArgumentParser() parser.add_argument("module") parser.add_argument("tier") parser.add_argument("--output") args = parser.parse_args() if args.module not in ADAPTERS: raise SystemExit(f"no adapter mapping for {args.module}") manifest_path = ROOT / "docs/p6/python-api-manifest.json" rows = json.loads(manifest_path.read_text(encoding="utf-8"))["records"] selected = [row for row in rows if row["module"] == args.module and row["tier"] == args.tier] worker, command, native_source = ADAPTERS[args.module] records = [{"apiId": row["id"], "name": row["name"], "kind": row["kind"], "family": row["family"], "sourcePath": row.get("evidence", {}).get("path"), "route": command, "adapterStatus": "module_adapter_ready_pending_method", "disposition": row["disposition"]} for row in selected] output = { "schema": "freecad-web-python-family-adapter-manifest/v1", "taskId": f"FW-P6-FPA-IMPL-{args.module.upper()}-{args.tier.upper().replace('-', '_')}", "source": {"manifest": "docs/p6/python-api-manifest.json", "manifestSha256": hashlib.sha256(manifest_path.read_bytes()).hexdigest()}, "module": args.module, "tier": args.tier, "count": len(records), "route": {"worker": worker, "command": command, "nativeSource": native_source}, "records": records, "boundaries": ["module adapter readiness is not method-level parameter/return evidence", "original disposition is preserved until the matching coverage gate"], } short_tier = {"tier-1-readonly": "tier1", "tier-2-pure": "tier2", "tier-3-stateful": "tier3"}.get(args.tier, args.tier.replace("-", "")) out = ROOT / (args.output or f"docs/p6/{args.module.lower()}-{short_tier}-adapter-manifest.json") out.write_text(json.dumps(output, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") print(json.dumps({"output": str(out.relative_to(ROOT)), "module": args.module, "tier": args.tier, "count": len(records), "sha256": hashlib.sha256(out.read_bytes()).hexdigest()}, ensure_ascii=False))