Block conflicting extension write selectors
This commit is contained in:
@@ -401,7 +401,7 @@ def validate_write_preflight(
|
||||
failures.append({"code": "write_preflight_not_ok", "label": label, "path": str(path), "status": report.get("status")})
|
||||
if report.get("failures"):
|
||||
failures.append({"code": "write_preflight_failures_present", "label": label, "path": str(path), "failures": report.get("failures")})
|
||||
for check in ("method_exposed", "effective_path_preflight", "concrete_saved_state_preflight", "name_first_extension_form_preflight"):
|
||||
for check in ("method_exposed", "effective_path_preflight", "concrete_saved_state_preflight", "name_first_extension_form_preflight", "conflicting_extension_selector_preflight"):
|
||||
if check not in checks:
|
||||
failures.append({"code": "write_preflight_check_missing", "label": label, "check": check, "path": str(path)})
|
||||
expect_check(checks, failures, label, path, "method_exposed", {"status": "ok"}, failure_code="write_preflight_check_field_unexpected")
|
||||
@@ -470,6 +470,31 @@ def validate_write_preflight(
|
||||
"repository_layer_id": repository_layer or None,
|
||||
"support_layer_id": support_layer or None,
|
||||
})
|
||||
conflicting_extension = checks.get("conflicting_extension_selector_preflight") if isinstance(checks.get("conflicting_extension_selector_preflight"), dict) else {}
|
||||
if conflicting_extension.get("status") == "skipped_no_public_extension_form_target":
|
||||
if require_name_first_form:
|
||||
failures.append({
|
||||
"code": "write_preflight_extension_conflict_check_required",
|
||||
"label": label,
|
||||
"path": str(path),
|
||||
})
|
||||
else:
|
||||
expect_check(
|
||||
checks,
|
||||
failures,
|
||||
label,
|
||||
path,
|
||||
"conflicting_extension_selector_preflight",
|
||||
{
|
||||
"schema": "onec_metadata_write_preflight.v1",
|
||||
"status": "blocked",
|
||||
"allowed": False,
|
||||
"resolution_status": "conflict",
|
||||
"error": "extension_selector_conflict",
|
||||
"layer_id": "extension:unresolved",
|
||||
},
|
||||
failure_code="write_preflight_check_field_unexpected",
|
||||
)
|
||||
if require_mcp_initialize:
|
||||
if "mcp.initialize" not in checks:
|
||||
failures.append({"code": "write_preflight_check_missing", "label": label, "check": "mcp.initialize", "path": str(path)})
|
||||
@@ -1633,6 +1658,14 @@ def write_self_test_reports(report_dir: Path, *, base_id: str, composed: bool, s
|
||||
"name_first": True,
|
||||
"extension": "test2",
|
||||
},
|
||||
"conflicting_extension_selector_preflight": {
|
||||
"schema": "onec_metadata_write_preflight.v1",
|
||||
"status": "blocked",
|
||||
"allowed": False,
|
||||
"resolution_status": "conflict",
|
||||
"error": "extension_selector_conflict",
|
||||
"layer_id": "extension:unresolved",
|
||||
},
|
||||
},
|
||||
"failures": [],
|
||||
}
|
||||
|
||||
@@ -207,6 +207,14 @@ def first_public_extension_form_candidate(result: dict[str, Any]) -> dict[str, A
|
||||
return candidate
|
||||
|
||||
|
||||
def different_extension_guid(layer_id: str) -> str | None:
|
||||
if not EXTENSION_GUID_LAYER_RE.fullmatch(str(layer_id or "")):
|
||||
return None
|
||||
guid = str(layer_id).split(":", 1)[1].lower()
|
||||
replacement = "0" if guid[-1] != "0" else "1"
|
||||
return f"{guid[:-1]}{replacement}"
|
||||
|
||||
|
||||
def run_smoke(
|
||||
endpoint_url: str,
|
||||
base_id: str,
|
||||
@@ -312,6 +320,9 @@ def run_smoke(
|
||||
"search_status": forms.get("status"),
|
||||
"forms": int((forms.get("counts") or {}).get("forms") or 0),
|
||||
}
|
||||
checks["conflicting_extension_selector_preflight"] = {
|
||||
"status": "skipped_no_public_extension_form_target",
|
||||
}
|
||||
if require_name_first_extension_form:
|
||||
failures.append("name-first extension form preflight target is required but was not discovered")
|
||||
else:
|
||||
@@ -355,6 +366,49 @@ def run_smoke(
|
||||
require(name_first, "extension form preflight input must remain name-first", failures)
|
||||
require(bool(EXTENSION_GUID_LAYER_RE.fullmatch(repository_layer)), "repository gate must use a resolved extension GUID layer", failures)
|
||||
require(repository_layer == support_layer, "repository and support gates must use the same extension layer", failures)
|
||||
conflicting_guid = different_extension_guid(repository_layer)
|
||||
if not conflicting_guid:
|
||||
checks["conflicting_extension_selector_preflight"] = {
|
||||
"status": "skipped_no_resolved_extension_layer",
|
||||
}
|
||||
else:
|
||||
conflicting = rpc_call(
|
||||
endpoint_url,
|
||||
"metadata.write.preflight",
|
||||
{
|
||||
"base_id": base_id,
|
||||
"extension_guid": conflicting_guid,
|
||||
"target": form_candidate["target"],
|
||||
"edits": [form_candidate["edit"]],
|
||||
"resolve_origin": False,
|
||||
"timeout_seconds": int(timeout),
|
||||
},
|
||||
timeout,
|
||||
transport=transport,
|
||||
session_id=session_id,
|
||||
)
|
||||
layer_resolution = (
|
||||
conflicting.get("development_layer_resolution")
|
||||
if isinstance(conflicting.get("development_layer_resolution"), dict)
|
||||
else {}
|
||||
)
|
||||
layer_diagnostics = (
|
||||
layer_resolution.get("diagnostics")
|
||||
if isinstance(layer_resolution.get("diagnostics"), dict)
|
||||
else {}
|
||||
)
|
||||
checks["conflicting_extension_selector_preflight"] = {
|
||||
"schema": conflicting.get("schema"),
|
||||
"status": conflicting.get("status"),
|
||||
"allowed": conflicting.get("allowed"),
|
||||
"resolution_status": layer_resolution.get("status"),
|
||||
"error": layer_diagnostics.get("error"),
|
||||
"layer_id": layer_resolution.get("layer_id"),
|
||||
}
|
||||
require(conflicting.get("schema") == "onec_metadata_write_preflight.v1", "conflicting extension selector preflight must return expected schema", failures)
|
||||
require(conflicting.get("status") == "blocked" and conflicting.get("allowed") is False, "conflicting extension name/GUID must block preflight", failures)
|
||||
require(layer_resolution.get("status") == "conflict", "conflicting extension selector must report conflict resolution status", failures)
|
||||
require(layer_diagnostics.get("error") == "extension_selector_conflict", "conflicting extension selector must report extension_selector_conflict", failures)
|
||||
|
||||
return {
|
||||
"schema": "onec_write_preflight_smoke.v1",
|
||||
|
||||
@@ -206,7 +206,7 @@ function Assert-WritePreflightReport {
|
||||
if ($report.failures -and $report.failures.Count -gt 0) {
|
||||
throw "$Label report contains failures: $Path"
|
||||
}
|
||||
foreach ($check in @("method_exposed", "effective_path_preflight", "concrete_saved_state_preflight", "name_first_extension_form_preflight")) {
|
||||
foreach ($check in @("method_exposed", "effective_path_preflight", "concrete_saved_state_preflight", "name_first_extension_form_preflight", "conflicting_extension_selector_preflight")) {
|
||||
if ($report.checks.PSObject.Properties.Name -notcontains $check) {
|
||||
throw "$Label report is missing check '$check': $Path"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user