Add exact Engine L2 reconciliation transition

This commit is contained in:
Codex
2026-07-23 13:10:11 +03:00
parent ad3760e767
commit 50cba59bde
4 changed files with 1114 additions and 15 deletions
@@ -4,10 +4,12 @@ import importlib.util
import json
import os
from pathlib import Path
import shutil
import subprocess
import tarfile
import tempfile
import unittest
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
@@ -16,6 +18,11 @@ BUILDER_PATH = SCRIPT_DIR / "build-engine-l2-closed-loop-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-l2-closed-loop-20991231-999"
SOURCE_COMMIT = "dda405cff27977622af0c218abb4d4420c408536"
BASELINE_ARTIFACT = (
SCRIPT_DIR.parent
/ "deploy-artifacts"
/ "nodedc-engine-provider-authority-diagnostics-20260723-029.tgz"
)
def load_runner():
@@ -57,6 +64,37 @@ class EngineL2ClosedLoopArtifactTest(unittest.TestCase):
)
return json.loads(completed.stdout)
def load_built_payload(self, root):
built = self.build(root / "artifact")
artifact = Path(built["artifact"])
manifest, entries, payload = RUNNER.load_artifact(
artifact,
root / "loaded",
)
return built, manifest, entries, payload
def materialize_partial_predecessor(self, payload, entries, root):
for relative_path in entries:
source = payload / relative_path
destination = root / relative_path
destination.parent.mkdir(parents=True, exist_ok=True)
if source.is_dir():
shutil.copytree(source, destination)
else:
shutil.copy2(source, destination)
with tarfile.open(BASELINE_ARTIFACT, "r:gz") as archive:
member = archive.extractfile(
"payload/nodedc-source/services/node-intelligence/activation.json"
)
self.assertIsNotNone(member)
(root / RUNNER.ENGINE_L2_CLOSED_LOOP_DESCRIPTOR_REL).write_bytes(
member.read()
)
shutil.copytree(
root / "nodedc-source/dist",
root / "nginx-html",
)
def test_builder_is_commit_bound_and_byte_deterministic(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-l2-closed-loop-") as directory:
root = Path(directory)
@@ -74,6 +112,30 @@ class EngineL2ClosedLoopArtifactTest(unittest.TestCase):
self.assertEqual(first["services"], ["nodedc-backend", "app"])
self.assertEqual(first["mcpVersion"], "0.7.0")
def test_failed_030_identity_is_terminal_and_cannot_be_retried(self):
with self.assertRaisesRegex(
RUNNER.DeployError,
"terminal failed",
):
RUNNER.reject_terminal_engine_l2_failed_artifact(
{
"id": RUNNER.ENGINE_L2_CLOSED_LOOP_FAILED_PATCH_ID,
},
"0" * 64,
)
with self.assertRaisesRegex(
RUNNER.DeployError,
"terminal failed",
):
RUNNER.reject_terminal_engine_l2_failed_artifact(
{"id": "different-successor"},
RUNNER.ENGINE_L2_CLOSED_LOOP_FAILED_ARTIFACT_SHA256,
)
RUNNER.reject_terminal_engine_l2_failed_artifact(
{"id": "engine-l2-closed-loop-20260723-031"},
"1" * 64,
)
def test_artifact_is_a_safe_exact_engine_overlay(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-l2-overlay-") as directory:
root = Path(directory)
@@ -134,6 +196,192 @@ class EngineL2ClosedLoopArtifactTest(unittest.TestCase):
self.assertTrue(all("/logs/" not in path for path in payload_files))
self.assertTrue(all(not path.endswith(".env") for path in payload_files))
def test_preflight_accepts_only_the_exact_failed_030_partial_state(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-l2-preflight-") as directory:
workspace = Path(directory)
_built, _manifest, entries, payload = self.load_built_payload(
workspace / "build"
)
live = workspace / "live"
self.materialize_partial_predecessor(payload, entries, live)
recovery = workspace / RUNNER.ENGINE_L2_CLOSED_LOOP_RECOVERY_BACKUP_ID
backend = {
"mode": "verified-derived-retry",
"container_id": "a" * 64,
}
with (
mock.patch.object(RUNNER, "component_root", return_value=live),
mock.patch.object(
RUNNER,
"validate_engine_l2_closed_loop_recovery_evidence",
return_value=recovery,
),
mock.patch.object(
RUNNER,
"validate_installed_engine_node_intelligence_source",
) as validate_source,
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value=backend,
) as validate_backend,
mock.patch.object(
RUNNER,
"engine_compose_service_container_id_for_gateway",
return_value="b" * 64,
) as app_lookup,
):
result = RUNNER.preflight_engine_l2_closed_loop_predecessor(
payload
)
self.assertEqual(
result["mode"],
"failed-030-partial-source-reconciliation",
)
self.assertEqual(result["backend_container_id"], "a" * 64)
self.assertEqual(result["app_container_id"], "b" * 64)
self.assertEqual(
result["target_gateway_sha256"],
RUNNER.ENGINE_L2_CLOSED_LOOP_TARGET_SHA256[
RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL
],
)
self.assertEqual(
validate_source.call_args.kwargs[
"expected_gateway_sha256"
],
RUNNER.ENGINE_L2_CLOSED_LOOP_PARTIAL_SHA256[
RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL
],
)
self.assertEqual(
validate_backend.call_args.kwargs[
"expected_node_intelligence_gateway_sha256"
],
RUNNER.ENGINE_L2_CLOSED_LOOP_PARTIAL_SHA256[
RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL
],
)
app_lookup.assert_called_once_with(
"app",
RUNNER.ENGINE_L2_CLOSED_LOOP_PARTIAL_SHA256[
RUNNER.ENGINE_NODE_INTELLIGENCE_GATEWAY_REL
],
)
index_path = live / "nodedc-source/dist/index.html"
index_path.write_bytes(index_path.read_bytes() + b"\n")
with (
mock.patch.object(RUNNER, "component_root", return_value=live),
mock.patch.object(
RUNNER,
"validate_engine_l2_closed_loop_recovery_evidence",
return_value=recovery,
),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
) as unreachable_backend,
):
with self.assertRaisesRegex(
RUNNER.DeployError,
"partial predecessor drift",
):
RUNNER.preflight_engine_l2_closed_loop_predecessor(payload)
unreachable_backend.assert_not_called()
def test_reconciliation_rollback_uses_failed_030_backup_and_restores_runtime(self):
entries = RUNNER.ENGINE_L2_CLOSED_LOOP_ARTIFACT_ENTRIES
services = ("nodedc-backend", "app")
with tempfile.TemporaryDirectory(prefix="nodedc-engine-l2-rollback-") as directory:
root = Path(directory)
candidate = root / "candidate-backup"
recovery = root / "recovery-backup"
candidate_entries = [*entries, "nginx-html"]
original_entries = [
rel
for rel in entries
if rel != RUNNER.ENGINE_L2_CLOSED_LOOP_DESCRIPTOR_REL
]
original_entries.append("nginx-html")
def backup_paths(path):
if path.parent == candidate:
return candidate_entries if path.name == "existing-files.txt" else []
if path.parent == recovery:
if path.name == "existing-files.txt":
return [
rel
for rel in original_entries
if rel != "nodedc-source/server/l2/graphRepository.js"
]
return ["nodedc-source/server/l2/graphRepository.js"]
raise AssertionError(path)
with (
mock.patch.object(
RUNNER,
"validate_engine_l2_closed_loop_recovery_evidence",
return_value=recovery,
),
mock.patch.object(
RUNNER,
"read_backup_path_list",
side_effect=backup_paths,
),
mock.patch.object(
RUNNER,
"restore_platform_overlay",
side_effect=(len(candidate_entries), len(original_entries)),
) as restore,
mock.patch.object(
RUNNER,
"validate_engine_l2_closed_loop_stable_source",
) as validate_stable,
mock.patch.object(RUNNER, "run_component_runtime") as run_runtime,
mock.patch.object(RUNNER, "healthcheck_compose_service") as check_service,
mock.patch.object(
RUNNER,
"component_healthchecks",
return_value=(
"http://127.0.0.1:8080/",
"http://127.0.0.1:3001/health",
),
),
mock.patch.object(RUNNER, "healthcheck_url") as check_url,
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = RUNNER.rollback_engine_l2_closed_loop_reconciliation(
root,
candidate,
entries,
"20991231-235959",
True,
services,
)
self.assertTrue(result.startswith("stable-source+runtime-restored:"))
self.assertEqual(
[call.args[1] for call in restore.call_args_list],
[candidate, recovery],
)
validate_stable.assert_called_once_with(root)
run_runtime.assert_called_once_with(
"engine",
tuple(RUNNER.ENGINE_L2_CLOSED_LOOP_STABLE_SHA256),
services,
)
self.assertEqual(
[call.args for call in check_service.call_args_list],
[("engine", "nodedc-backend"), ("engine", "app")],
)
self.assertEqual(check_url.call_count, 2)
if __name__ == "__main__":
unittest.main(verbosity=2)