Milestone 7: validate before solving
The registration gate catches a manifest that advertises behavior no shared contract can enforce:
from pathlib import Path
import yaml
from helixor_solvers.manifest_gate import validate_manifest
manifest = yaml.safe_load(Path("retail_rota.yaml").read_text())
report = validate_manifest(manifest, source="retail_rota.yaml")
for finding in report.findings:
print(finding.severity, finding.describe())
errors = [f for f in report.findings if f.severity == "error"]
if errors:
raise SystemExit("manifest is not registrable")
The gate and solve boundary should expose at least:
-
unknown contracts and parameters;
-
enabled rules that build no enforcement stream;
-
a missing
decisionblock; -
missing record attributes needed by enabled rules;
-
unsupported problem types;
-
declared rules that could not be evaluated.
Missing input returns HTTP 422 with a typed envelope, for example:
{
"status": "unsupported",
"failure_code": "missing_problem_data",
"problem_type": "retail_rota",
"reason": "input-contract",
"detail": "Retail rostering requires employee and shift records.",
"missing_inputs": ["employees", "shifts"],
"hint": "Provide the missing inputs. The solve path never generates demo data; demo datasets come from the explicit dataset endpoints or seed packs."
}
The UX should preserve failure_code, missing_inputs, detail, hint,
job_id, and the reasoning verdict. Reducing this to “Solve failed” discards
the information the user needs to repair the request.