Automatically resume empty saved source reviews

This commit is contained in:
Wyndham ARR committed 2026-10-09 00:12:06 +08:00
1 parent cd362b3b81
commit 976a4fa7b2
11 files changed
+585 -29

No files matched your search

+51 -24
View File
@@ -31,6 +31,7 @@ VERSION = "arr-source-field-review/v1"
REANALYSIS_POLICY = "oracle-optional-association/v1"
REANALYSIS_VERSION = "arr-source-reanalysis/v1"
STATUS_POLICY = "arr-exclude-cancelled/v1"
EMPTY_REVIEW_ACTOR = "system:arr-empty-source-review"
LIMIT = 100 * 1024 * 1024
OPTIONAL = frozenset({"BLOCK_CODE", "RES_COMMENT", "PRODUCTS", "ROOM_CATEGORY_LABEL"})
LABELS = {
@@ -381,9 +382,11 @@ class DataFieldReviews:
require(fingerprint(actual) == fingerprint(meta), "data_review_prepare_conflict")
review = self._public(directory, actual, original, state)
# A complete ordinary source needs no human step or derived source.
# A reanalysis remains an explicit review until finalized, even if
# its validated source interpretation resolves every listed gap.
return review if review["total_count"] or "source_reanalysis" in state or "reservation_status_evidence" in state else None
# Validated overlays still need a frozen derived source. The
# executor may finish a genuinely empty review under a system actor.
return review if (review["total_count"] or state["decisions"] or state["status"] == "finalized"
or "source_reanalysis" in state or "reservation_status_evidence" in state
or (directory / "finalize-intent.json").exists()) else None
def get(self, request_id):
directory = self._directory(request_id)
@@ -583,33 +586,57 @@ class DataFieldReviews:
return json_bytes(data), binding
def finalize(self, request_id, revision, actor):
directory = self._directory(request_id)
with self._lock(directory):
meta, original, state = self._read(directory)
return self._finalize_locked(directory, meta, original, state, revision, actor)
def recover_ready(self, request_id):
"""Freeze validated zero-item saved reviews, or replay a verified prior freeze.
This internal recovery operation has no HTTP route. A completed manual
list is deliberately not empty: its explicit human confirmation remains
required. Read/derive/guard/freeze share the same revision lock.
"""
directory = self._directory(request_id)
with self._lock(directory):
meta, original, state = self._read(directory)
if state["status"] == "finalized":
self._verify_frozen(directory, meta, original, state)
return self._public(directory, meta, original, state)
self._revision(state, revision)
actor = self._actor(actor)
if self._issues(directory, self._derive(directory, original, state)):
raise _error("INCOMPLETE", "请先完善并确认所有异常字段", 409)
intent = directory / "finalize-intent.json"
prior_sha256 = fingerprint(state)
if intent.exists():
frozen = strict_json(protected_read(intent, LIMIT))
require(frozen["prior_sha256"] == prior_sha256, "data_review_finalize_context_changed")
state = frozen["state"]
else:
state["revision"] += 1
state["status"] = "finalized"
state["events"].append({"revision": state["revision"], "action": "finalize", "actor": actor,
"at": datetime.now(timezone.utc).isoformat()})
atomic_json(intent, {"prior_sha256": prior_sha256, "state": state}, replace=False)
payload, binding = self._frozen(directory, meta, original, state)
_write_once(directory / "reviewed-source.json", payload)
state["derived_sha256"], state["binding_manifest_sha256"] = _hash(payload), binding
self._publish(directory, state)
return True
if original.get("status") not in {"collected", "collected_with_gaps"}:
return False
review = self._public(directory, meta, original, state)
if review["total_count"] != 0 or review["pending_count"] != 0 or not review["can_finalize"]:
return False
self._finalize_locked(directory, meta, original, state, state["revision"], EMPTY_REVIEW_ACTOR)
return True
def _finalize_locked(self, directory, meta, original, state, revision, actor):
if state["status"] == "finalized":
self._verify_frozen(directory, meta, original, state)
return self._public(directory, meta, original, state)
self._revision(state, revision)
actor = self._actor(actor)
if self._issues(directory, self._derive(directory, original, state)):
raise _error("INCOMPLETE", "请先完善并确认所有异常字段", 409)
intent = directory / "finalize-intent.json"
prior_sha256 = fingerprint(state)
if intent.exists():
frozen = strict_json(protected_read(intent, LIMIT))
require(frozen["prior_sha256"] == prior_sha256, "data_review_finalize_context_changed")
state = frozen["state"]
else:
state["revision"] += 1
state["status"] = "finalized"
state["events"].append({"revision": state["revision"], "action": "finalize", "actor": actor,
"at": datetime.now(timezone.utc).isoformat()})
atomic_json(intent, {"prior_sha256": prior_sha256, "state": state}, replace=False)
payload, binding = self._frozen(directory, meta, original, state)
_write_once(directory / "reviewed-source.json", payload)
state["derived_sha256"], state["binding_manifest_sha256"] = _hash(payload), binding
self._publish(directory, state)
return self._public(directory, meta, original, state)
def _verify_frozen(self, directory, meta, original, state):
payload, binding = self._frozen(directory, meta, original, state)