feat(devkit): add resumable workspace automation and UI review tooling
Verified with the coordinated workspace changes by devkit full run 2026-09-08T225814-186389-0000-3e3ed7cd (all seven phases passed). This shared UI pass does not mark the individual module reviews complete.
This commit is contained in:
Executable
+244
@@ -0,0 +1,244 @@
|
||||
"""Independently verified check results; never an artifact/build-output cache."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import deepcopy
|
||||
import threading
|
||||
import re
|
||||
|
||||
from .common import digest, now
|
||||
from .inputs import InputSnapshotter, FINGERPRINT_VERSION
|
||||
|
||||
CHECKPOINT_VERSION = 1
|
||||
|
||||
|
||||
def validate_checkpoint_receipt(receipt):
|
||||
"""New checkpoints are explicit; legacy status alone never certifies a phase."""
|
||||
version = receipt.get("fingerprint_version")
|
||||
if version is None:
|
||||
return
|
||||
if version != FINGERPRINT_VERSION:
|
||||
raise ValueError("Unsupported check fingerprint version")
|
||||
for stage in receipt["stages"]:
|
||||
verified = stage.get("checkpoint_verified")
|
||||
if type(verified) is not bool:
|
||||
raise ValueError("Stage checkpoint verification must be boolean")
|
||||
if stage["status"] == "passed" and not verified:
|
||||
raise ValueError(
|
||||
"Passing stage requires an independently verified checkpoint"
|
||||
)
|
||||
if not verified:
|
||||
continue
|
||||
if (
|
||||
stage["status"] != "passed"
|
||||
or stage.get("checkpoint_version") != CHECKPOINT_VERSION
|
||||
):
|
||||
raise ValueError("Invalid verified checkpoint state or version")
|
||||
for field in (
|
||||
"cache_key",
|
||||
"input_fingerprint",
|
||||
"stage_plan_fingerprint",
|
||||
"log_sha256",
|
||||
):
|
||||
if not isinstance(stage.get(field), str) or not re.fullmatch(
|
||||
r"[a-f0-9]{64}", stage[field]
|
||||
):
|
||||
raise ValueError(
|
||||
"Verified checkpoint requires bounded content identities"
|
||||
)
|
||||
if (
|
||||
not isinstance(stage.get("checkpoint_at"), str)
|
||||
or not stage["checkpoint_at"]
|
||||
):
|
||||
raise ValueError("Verified checkpoint requires its recording time")
|
||||
scope = stage.get("input_scope")
|
||||
if (
|
||||
not isinstance(scope, dict)
|
||||
or scope.get("version") != 1
|
||||
or scope.get("kind") not in {"workspace", "repositories"}
|
||||
or type(scope.get("declared")) is not bool
|
||||
):
|
||||
raise ValueError("Verified checkpoint requires a versioned input scope")
|
||||
names = scope.get("repos")
|
||||
if (
|
||||
not isinstance(names, list)
|
||||
or not 1 <= len(names) <= 256
|
||||
or any(not isinstance(name, str) for name in names)
|
||||
or len(set(names)) != len(names)
|
||||
):
|
||||
raise ValueError(
|
||||
"Verified checkpoint requires bounded repository identities"
|
||||
)
|
||||
|
||||
|
||||
class Checkpoints:
|
||||
def __init__(self, project, workspace, plan, environment_probe, cancelled):
|
||||
self.scanner = InputSnapshotter(project, workspace_root=workspace)
|
||||
self.plan = {stage["id"]: stage for stage in plan}
|
||||
self.environment_probe = environment_probe
|
||||
self.cancelled = cancelled
|
||||
self.lock = threading.RLock()
|
||||
self.initial = None
|
||||
self.environment = None
|
||||
|
||||
def source(self, stages=None):
|
||||
with self.lock:
|
||||
return self.scanner.snapshot(
|
||||
list(self.plan.values()) if stages is None else stages
|
||||
)
|
||||
|
||||
def probe_environment(self):
|
||||
value = self.environment_probe()
|
||||
self.check_cancelled()
|
||||
return value
|
||||
|
||||
def check_cancelled(self):
|
||||
if self.cancelled.is_set():
|
||||
raise InterruptedError("Check cancelled during input verification")
|
||||
|
||||
def initialize(self):
|
||||
self.initial = self.source()
|
||||
self.check_cancelled()
|
||||
self.environment = self.probe_environment()
|
||||
return self.initial, self.environment
|
||||
|
||||
def closure(self, stage):
|
||||
selected = {}
|
||||
|
||||
def include(item):
|
||||
if item["id"] in selected:
|
||||
return
|
||||
selected[item["id"]] = item
|
||||
for identity in item["deps"]:
|
||||
include(self.plan[identity])
|
||||
|
||||
include(self.plan[stage["id"]])
|
||||
return [selected[key] for key in sorted(selected)]
|
||||
|
||||
def identity(self, stage):
|
||||
with self.lock:
|
||||
closure = self.closure(stage)
|
||||
snapshot = self.source(closure)
|
||||
self.check_cancelled()
|
||||
environment = self.probe_environment()
|
||||
own = snapshot["stages"][stage["id"]]
|
||||
key = digest(
|
||||
{
|
||||
"checkpoint_version": CHECKPOINT_VERSION,
|
||||
"inputs": {
|
||||
identity: value["fingerprint"]
|
||||
for identity, value in snapshot["stages"].items()
|
||||
},
|
||||
"environment": environment,
|
||||
}
|
||||
)
|
||||
return {
|
||||
"checkpoint_version": CHECKPOINT_VERSION,
|
||||
"cache_key": key,
|
||||
"input_fingerprint": own["fingerprint"],
|
||||
"input_scope": own["scope"],
|
||||
"stage_plan_fingerprint": own["plan_fingerprint"],
|
||||
"stage_environment_fingerprint": environment,
|
||||
"dependency_input_fingerprints": {
|
||||
item["id"]: snapshot["stages"][item["id"]]["fingerprint"]
|
||||
for item in closure
|
||||
if item["id"] != stage["id"]
|
||||
},
|
||||
}
|
||||
|
||||
def prepare(self, stage, prior, allow_reuse, verify_log):
|
||||
before = self.identity(stage)
|
||||
reason = "No previous verified checkpoint"
|
||||
if stage.get("reuse", "verified") == "never":
|
||||
reason = (
|
||||
"This stage explicitly disables reuse (outputs/setup must be recreated)"
|
||||
)
|
||||
elif not allow_reuse:
|
||||
reason = "A data dependency ran again; its consumers must run again"
|
||||
elif (
|
||||
prior
|
||||
and prior.get("status") == "passed"
|
||||
and prior.get("checkpoint_verified") is True
|
||||
and prior.get("checkpoint_version") == CHECKPOINT_VERSION
|
||||
):
|
||||
if prior.get("cache_key") == before["cache_key"]:
|
||||
# Receipt command text is never executed. Only the freshly planned
|
||||
# stage runs; a cached log must independently match its content hash.
|
||||
verify_log(prior)
|
||||
result = {
|
||||
**before,
|
||||
**{
|
||||
key: deepcopy(prior[key])
|
||||
for key in (
|
||||
"status",
|
||||
"exit_code",
|
||||
"duration_seconds",
|
||||
"log_path",
|
||||
"log_sha256",
|
||||
"output_truncated",
|
||||
"omitted_output_bytes",
|
||||
"checkpoint_at",
|
||||
)
|
||||
if key in prior
|
||||
},
|
||||
}
|
||||
result.update(
|
||||
checkpoint_verified=True,
|
||||
reuse_reason="Verified checkpoint matches current inputs, command, dependencies and environment",
|
||||
)
|
||||
return before, result
|
||||
reason = (
|
||||
"Declared inputs, command, dependency inputs or environment changed"
|
||||
)
|
||||
before["reuse_reason"] = reason
|
||||
return before, None
|
||||
|
||||
def finish(self, stage, before, result):
|
||||
result = {**result, **before, "checkpoint_verified": False}
|
||||
if result["status"] != "passed" or result.get("exit_code") != 0:
|
||||
return result
|
||||
after = self.identity(stage)
|
||||
if before["cache_key"] != after["cache_key"]:
|
||||
result.update(
|
||||
status="stale",
|
||||
error="Stage inputs or environment changed during execution; no reusable checkpoint was recorded",
|
||||
)
|
||||
else:
|
||||
result.update(checkpoint_verified=True, checkpoint_at=now())
|
||||
return result
|
||||
|
||||
def finalize(self, stages):
|
||||
final = self.source()
|
||||
self.check_cancelled()
|
||||
environment = self.probe_environment()
|
||||
valid = (
|
||||
final["observed_source_fingerprint"]
|
||||
== self.initial["observed_source_fingerprint"]
|
||||
and environment == self.environment
|
||||
)
|
||||
for stage in stages:
|
||||
if stage["status"] != "passed":
|
||||
valid = valid and stage["status"] != "stale"
|
||||
continue
|
||||
closure = self.closure(self.plan[stage["id"]])
|
||||
key = digest(
|
||||
{
|
||||
"checkpoint_version": CHECKPOINT_VERSION,
|
||||
"inputs": {
|
||||
item["id"]: final["stages"][item["id"]]["fingerprint"]
|
||||
for item in closure
|
||||
},
|
||||
"environment": environment,
|
||||
}
|
||||
)
|
||||
if (
|
||||
stage.get("checkpoint_verified") is not True
|
||||
or stage.get("cache_key") != key
|
||||
):
|
||||
stage.update(
|
||||
status="stale",
|
||||
checkpoint_verified=False,
|
||||
error="Final inputs no longer match this checkpoint",
|
||||
)
|
||||
valid = False
|
||||
return valid, final, environment
|
||||
Reference in New Issue
Block a user