feat: add per-part CAD model specs

This commit is contained in:
Jerry
2026-07-23 15:12:28 +08:00
parent 304911a69f
commit a2f3ba6a90
35 changed files with 1351 additions and 85 deletions
+14 -5
View File
@@ -263,7 +263,10 @@ def classify_edit_context(
suffix = source.suffix.lower() if source else ""
text = request.lower()
if suffix in {".py", ".scad", ".js", ".mjs"}:
if suffix == ".json" and source and source.name == "model-spec.json":
mode = "model_spec_parameter_edit"
reason = "A per-part model specification exists; update its named JSON parameters or modification features."
elif suffix in {".py", ".scad", ".js", ".mjs"}:
mode = "native_parameter_edit"
reason = "An editable generator exists; update its named parameters or feature source."
elif contains_any(text, MAJOR_EDIT_TERMS):
@@ -304,7 +307,7 @@ def classify_edit_context(
"preservation_contract": [
"Preserve the source coordinate frame unless the request explicitly changes it.",
"Preserve unmodified interfaces, datums, and feature relationships.",
"Prefer the native generator over inferred STEP reconstruction when both exist.",
"Prefer the per-part model-spec.json and native generator over inferred STEP reconstruction when they exist.",
"Use generalized experience only as method guidance, never as replacement source geometry.",
],
}
@@ -480,6 +483,12 @@ def route(args: argparse.Namespace) -> dict[str, object]:
registry = json.loads(REGISTRY_PATH.read_text(encoding="utf-8"))
backend_info = registry["backends"][selected.name]
source_of_truth = backend_info["source_of_truth"]
if (
edit_context
and edit_context.get("modification_mode") == "model_spec_parameter_edit"
):
source_of_truth = "per-part model-spec.json with a backend generator"
gap = selected.score - max((scores[name].score for name in scores if name != selected.name), default=0)
confidence = "high" if gap >= 40 else "medium" if gap >= 15 else "low"
result: dict[str, object] = {
@@ -498,7 +507,7 @@ def route(args: argparse.Namespace) -> dict[str, object]:
"workflow_profiles": profiles,
"downstream_skills": downstream,
"requested_outputs": outputs,
"source_of_truth": backend_info["source_of_truth"],
"source_of_truth": source_of_truth,
"experience_context": experience_context,
"design_plan": {
"plan_kind": "backend_neutral_parametric_design_plan",
@@ -506,7 +515,7 @@ def route(args: argparse.Namespace) -> dict[str, object]:
"part_family": experience_family or "unclassified",
"requested_feature_roles": sorted(set(experience_features)),
"selected_backend": selected.name,
"source_of_truth": backend_info["source_of_truth"],
"source_of_truth": source_of_truth,
"generalized_methods": [
{
key: item[key]
@@ -631,7 +640,7 @@ def build_parser() -> argparse.ArgumentParser:
parser.add_argument(
"--edit-source",
type=Path,
help="Existing generator, STEP/STP, or private case JSON to modify.",
help="Existing model-spec.json, generator, or explicit STEP/STP to modify; private case JSON is forbidden.",
)
parser.add_argument("--assembly", action="store_true", help="The requested result is an assembly.")
parser.add_argument("--browser-controls", action="store_true", help="Interactive browser parameter controls are required.")