优化流程
This commit is contained in:
@@ -109,8 +109,8 @@ class ActionCommandHandler:
|
||||
for event in self.repository.ledger_events(task_id)[-16:]:
|
||||
if event.get("event") in {
|
||||
"candidate_rejected", "candidate_build_failed", "candidate_recovery_failed",
|
||||
"candidate_recovered_rejected", "final_review_repair",
|
||||
}:
|
||||
"candidate_recovered_rejected", "candidate_operation_skipped", "final_review_repair",
|
||||
} or (event.get("event") == "accepted" and event.get("repair_required")):
|
||||
sequence = event.get("sequence")
|
||||
if isinstance(sequence, int):
|
||||
refs.append(f"evidence_ledger_{sequence}")
|
||||
@@ -134,8 +134,10 @@ class ActionCommandHandler:
|
||||
"candidate_build_failed",
|
||||
"candidate_recovery_failed",
|
||||
"candidate_recovered_rejected",
|
||||
"candidate_operation_skipped",
|
||||
"runtime_precondition_rejected",
|
||||
"final_review_repair",
|
||||
"accepted",
|
||||
}
|
||||
diagnostics: list[dict[str, Any]] = []
|
||||
for event in reversed(self.repository.ledger_events(task_id)):
|
||||
@@ -153,6 +155,20 @@ class ActionCommandHandler:
|
||||
message = event.get("message")
|
||||
if isinstance(message, str) and message:
|
||||
item["message"] = message[:500]
|
||||
for field in ("issues", "failed_checklist_items"):
|
||||
values = event.get(field)
|
||||
if isinstance(values, list):
|
||||
item[field] = [str(value)[:500] for value in values[:8] if isinstance(value, str)]
|
||||
failures = event.get("operation_failures")
|
||||
if isinstance(failures, list):
|
||||
item["operation_failures"] = [
|
||||
{key: str(value)[:500] for key, value in failure.items() if key in {"feature_id", "message"}}
|
||||
for failure in failures[:8]
|
||||
if isinstance(failure, dict)
|
||||
]
|
||||
fragment_hash = event.get("fragment_hash")
|
||||
if isinstance(fragment_hash, str) and fragment_hash:
|
||||
item["fragment_hash"] = fragment_hash
|
||||
stage_id = event.get("stage_id")
|
||||
candidate = None
|
||||
if isinstance(stage_id, str) and stage_id:
|
||||
@@ -263,7 +279,11 @@ class ActionCommandHandler:
|
||||
state = state or self.repository.get_state(task_id)
|
||||
if state is None or state.phase != TaskPhase.AWAITING_ACTION or state.pending_action is not None:
|
||||
return False
|
||||
return any(
|
||||
has_earlier_checkpoint = any(
|
||||
revision != state.active_revision
|
||||
for revision in self.checkpoint_tokens(task_id, state).values()
|
||||
)
|
||||
return has_earlier_checkpoint and any(
|
||||
event.get("event") == "geometry_conclusion"
|
||||
and event.get("decision") == "rollback"
|
||||
and event.get("working_head") == state.working_head
|
||||
@@ -390,6 +410,7 @@ class ActionCommandHandler:
|
||||
fragment,
|
||||
selector_tokens=allowed_selector_tokens,
|
||||
reference_tokens=list(references),
|
||||
root_xy_datum=not bool(state.active_revision),
|
||||
)
|
||||
if errors:
|
||||
return Rejected(WorkflowError(ErrorCode.AUTHOR_FORMAT_INVALID, "CDSL fragment violates the active operation schema.", field_errors=tuple(errors)))
|
||||
@@ -452,8 +473,48 @@ class ActionCommandHandler:
|
||||
if not self.repository.compare_and_swap(building, events=[{"event": "candidate_building", "candidate_id": candidate_id, "stage_id": stage.stage_id, "action_id": action.action_id, "fragment_hash": audit["fragment_hash"]}]):
|
||||
return Rejected(self._stale())
|
||||
try:
|
||||
rebuilt = self.runtime.rebuild(cdsl, stage.output_dir, task_id, candidate_id)
|
||||
claim_results = self._evaluate_claims(task_id, rebuilt)
|
||||
rebuilt, operation_failures = self.runtime.rebuild_best_effort(cdsl, stage.output_dir, task_id, candidate_id)
|
||||
attempted_feature_ids = {str(value) for value in audit.get("assigned_feature_ids") or () if isinstance(value, str)}
|
||||
executed_feature_ids = {str(value) for value in rebuilt.get("executed_feature_ids") or () if isinstance(value, str)}
|
||||
if attempted_feature_ids and not attempted_feature_ids.intersection(executed_feature_ids):
|
||||
next_state = transition(building, "candidate_rejected", candidate_id="", candidate_stage_id="", repair_required=True, error=ErrorCode.CANDIDATE_BUILD_FAILED)
|
||||
result = {"candidate_id": candidate_id, "status": "skipped", "code": ErrorCode.CANDIDATE_BUILD_FAILED.value, "operation_failures": operation_failures}
|
||||
if not self._commit_invocation(next_state, [{
|
||||
"event": "candidate_operation_skipped",
|
||||
"candidate_id": candidate_id,
|
||||
"stage_id": stage.stage_id,
|
||||
"action_id": action.action_id,
|
||||
"working_head": action.working_head,
|
||||
"checkpoint_revision": state.active_revision,
|
||||
"atomic_id": action.atomic_id,
|
||||
"fragment_hash": fragment_hash,
|
||||
"operation_failures": operation_failures,
|
||||
"message": "The submitted feature did not execute; earlier executable features were retained.",
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Rejected(WorkflowError(
|
||||
ErrorCode.CANDIDATE_BUILD_FAILED,
|
||||
"The submitted feature could not execute; the previous executable checkpoint was retained.",
|
||||
details={"operation_failures": operation_failures},
|
||||
))
|
||||
try:
|
||||
claim_results = self._evaluate_claims(task_id, rebuilt)
|
||||
except Exception as error:
|
||||
failed_state = transition(building, "failed", error=ErrorCode.REQUIREMENTS_SPEC_INVALID)
|
||||
result = {"candidate_id": candidate_id, "status": "failed", "code": ErrorCode.REQUIREMENTS_SPEC_INVALID.value}
|
||||
if not self._commit_invocation(failed_state, [{
|
||||
"event": "requirements_contract_execution_failed",
|
||||
"candidate_id": candidate_id,
|
||||
"stage_id": stage.stage_id,
|
||||
"action_id": action.action_id,
|
||||
"message": str(error)[:1000],
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Rejected(WorkflowError(
|
||||
ErrorCode.REQUIREMENTS_SPEC_INVALID,
|
||||
"The frozen requirements contract could not be evaluated; no CAD repair was attempted.",
|
||||
details={"diagnostic": str(error)[:1000]},
|
||||
))
|
||||
operation_results = self._operation_candidate_results(
|
||||
action,
|
||||
contract,
|
||||
@@ -466,47 +527,11 @@ class ActionCommandHandler:
|
||||
*self._candidate_blockers(task_id, action.requirement_ids, claim_results),
|
||||
*[item for item in operation_results if item.get("status") != "pass"],
|
||||
]
|
||||
candidate = {"schema_version": "cad.v3.candidate.v1", "candidate_id": candidate_id, "stage_id": stage.stage_id, "action_id": action.action_id, "working_head": action.working_head, "actual_atomic_id": action.atomic_id, "fragment_hash": audit["fragment_hash"], "selector_snapshot_id": audit["selector_snapshot_id"], "claim_results": claim_results, "operation_verifier_results": operation_results, "blockers": blockers, "health": rebuilt["health"], "render_manifest": rebuilt.get("render_manifest") or {}, "paths": rebuilt["paths"]}
|
||||
candidate = {"schema_version": "cad.v3.candidate.v1", "candidate_id": candidate_id, "stage_id": stage.stage_id, "action_id": action.action_id, "working_head": action.working_head, "actual_atomic_id": action.atomic_id, "fragment_hash": audit["fragment_hash"], "selector_snapshot_id": audit["selector_snapshot_id"], "claim_results": claim_results, "operation_verifier_results": operation_results, "blockers": blockers, "operation_failures": operation_failures, "executed_feature_ids": rebuilt.get("executed_feature_ids") or [], "health": rebuilt["health"], "render_manifest": rebuilt.get("render_manifest") or {}, "paths": rebuilt["paths"]}
|
||||
self.artifacts.write_stage_json(task_id, stage.stage_id, "candidate.json", candidate)
|
||||
if blockers:
|
||||
failure_class_fingerprint = self._failure_class_fingerprint(
|
||||
state.active_revision, action.atomic_id, ErrorCode.CLAIM_VERIFICATION_FAILED,
|
||||
)
|
||||
prior_failures = self._failure_class_events(task_id, failure_class_fingerprint)
|
||||
if len(prior_failures) >= 2:
|
||||
failed_state = transition(building, "failed", error=ErrorCode.NO_PROGRESS_LIMIT)
|
||||
result = {"candidate_id": candidate_id, "status": "failed", "code": ErrorCode.NO_PROGRESS_LIMIT.value}
|
||||
if not self._commit_invocation(failed_state, [{
|
||||
"event": "no_progress_limit", "candidate_id": candidate_id, "stage_id": stage.stage_id,
|
||||
"action_id": action.action_id, "checkpoint_revision": state.active_revision,
|
||||
"atomic_id": action.atomic_id, "normalized_error_code": ErrorCode.CLAIM_VERIFICATION_FAILED.value,
|
||||
"failure_class_fingerprint": failure_class_fingerprint,
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Rejected(WorkflowError(ErrorCode.NO_PROGRESS_LIMIT, "The same deterministic candidate failure made no progress after three attempts."))
|
||||
failed_state = transition(building, "candidate_rejected", candidate_id="", candidate_stage_id="", repair_required=True, error=ErrorCode.CLAIM_VERIFICATION_FAILED)
|
||||
result = {"candidate_id": candidate_id, "status": "rejected", "code": ErrorCode.CLAIM_VERIFICATION_FAILED.value, "claim_results": claim_results}
|
||||
if not self._commit_invocation(failed_state, [{
|
||||
"event": "candidate_rejected",
|
||||
"candidate_id": candidate_id,
|
||||
"stage_id": stage.stage_id,
|
||||
"action_id": action.action_id,
|
||||
"working_head": action.working_head,
|
||||
"checkpoint_revision": state.active_revision,
|
||||
"atomic_id": action.atomic_id,
|
||||
"fragment_hash": fragment_hash,
|
||||
"normalized_error_code": ErrorCode.CLAIM_VERIFICATION_FAILED.value,
|
||||
"failure_exact_fingerprint": exact_fingerprint,
|
||||
"failure_class_fingerprint": failure_class_fingerprint,
|
||||
"attempt": len(prior_failures) + 1,
|
||||
"reason": "deterministic_claim_failed",
|
||||
"claim_results": claim_results,
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Rejected(WorkflowError(ErrorCode.CLAIM_VERIFICATION_FAILED, "Candidate violates a deterministic claim required by this action or a global invariant.", details={"claim_results": blockers}))
|
||||
review = transition(building, "candidate_built", candidate_id=candidate_id, candidate_stage_id=stage.stage_id)
|
||||
result = {"candidate_id": candidate_id, "stage_id": stage.stage_id, "status": "awaiting_review", "claim_results": claim_results}
|
||||
if not self._commit_invocation(review, [{"event": "candidate_built", "candidate_id": candidate_id, "action_id": action.action_id, "claim_results": claim_results}], invocation, result):
|
||||
result = {"candidate_id": candidate_id, "stage_id": stage.stage_id, "status": "awaiting_review", "claim_results": claim_results, "operation_failures": operation_failures}
|
||||
if not self._commit_invocation(review, [{"event": "candidate_built", "candidate_id": candidate_id, "action_id": action.action_id, "claim_results": claim_results, "operation_failures": operation_failures}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Accepted(result)
|
||||
except OSError as error:
|
||||
@@ -592,7 +617,9 @@ class ActionCommandHandler:
|
||||
selectors = self.runtime.selector_tokens(self.artifacts.read_topology(task_id, state.active_revision))
|
||||
references = self.runtime.reference_tokens(base)
|
||||
cdsl, _audit = self.runtime.materialize_fragment(base, fragment, contract, selectors, references, require_through=self._action_requires_through(task_id, action.requirement_ids))
|
||||
rebuilt = self.runtime.rebuild(cdsl, self.artifacts.stage_output_dir(task_id, state.candidate_stage_id), task_id, state.candidate_id)
|
||||
rebuilt, operation_failures = self.runtime.rebuild_best_effort(cdsl, self.artifacts.stage_output_dir(task_id, state.candidate_stage_id), task_id, state.candidate_id)
|
||||
if "operation_failures" not in locals():
|
||||
operation_failures = []
|
||||
claim_results = self._evaluate_claims(task_id, rebuilt)
|
||||
audit = source.get("fragment_audit") if isinstance(source.get("fragment_audit"), dict) else {}
|
||||
contract = self.runtime.operation_contract(action.atomic_id)
|
||||
@@ -611,6 +638,7 @@ class ActionCommandHandler:
|
||||
"fragment_hash": audit.get("fragment_hash") or canonical_hash(source.get("fragment") or {}),
|
||||
"selector_snapshot_id": audit.get("selector_snapshot_id") or "", "claim_results": claim_results,
|
||||
"operation_verifier_results": operation_results,
|
||||
"operation_failures": operation_failures,
|
||||
"blockers": [
|
||||
*self._candidate_blockers(task_id, action.requirement_ids, claim_results),
|
||||
*[item for item in operation_results if item.get("status") != "pass"],
|
||||
@@ -699,51 +727,9 @@ class ActionCommandHandler:
|
||||
event="candidate_review_storage_failure",
|
||||
message=str(error),
|
||||
)
|
||||
if review.verdict != "accept" or deterministic_fail:
|
||||
if published_revision:
|
||||
return Rejected(WorkflowError(ErrorCode.STORAGE_FAILURE, "A published candidate cannot be rejected during recovery.", retryable=True))
|
||||
failure_class_fingerprint = self._failure_class_fingerprint(
|
||||
state.active_revision, action.atomic_id, ErrorCode.CANDIDATE_REVIEW_REJECTED,
|
||||
)
|
||||
reviewed_fragment_hash = str(candidate.get("fragment_hash") or "")
|
||||
failure_exact_fingerprint = canonical_hash({
|
||||
"active_revision": state.active_revision,
|
||||
"atomic_id": action.atomic_id,
|
||||
"fragment_hash": reviewed_fragment_hash,
|
||||
}) if reviewed_fragment_hash else ""
|
||||
prior_failures = self._failure_class_events(task_id, failure_class_fingerprint)
|
||||
if len(prior_failures) >= 2:
|
||||
next_state = transition(state, "failed", error=ErrorCode.NO_PROGRESS_LIMIT)
|
||||
result = {"candidate_id": state.candidate_id, "status": "failed", "code": ErrorCode.NO_PROGRESS_LIMIT.value}
|
||||
if not self._commit_invocation(next_state, [{
|
||||
"event": "no_progress_limit", "candidate_id": state.candidate_id,
|
||||
"stage_id": state.candidate_stage_id, "action_id": action.action_id,
|
||||
"checkpoint_revision": state.active_revision, "atomic_id": action.atomic_id,
|
||||
"normalized_error_code": ErrorCode.CANDIDATE_REVIEW_REJECTED.value,
|
||||
"failure_class_fingerprint": failure_class_fingerprint,
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Rejected(WorkflowError(ErrorCode.NO_PROGRESS_LIMIT, "The same candidate-review failure made no progress after three attempts."))
|
||||
next_state = transition(state, "candidate_rejected", error=ErrorCode.CANDIDATE_REVIEW_REJECTED, repair_required=True)
|
||||
result = {"candidate_id": state.candidate_id, "status": "rejected"}
|
||||
if not self._commit_invocation(next_state, [{
|
||||
"event": "candidate_rejected",
|
||||
"candidate_id": state.candidate_id,
|
||||
"stage_id": state.candidate_stage_id,
|
||||
"action_id": action.action_id,
|
||||
"working_head": action.working_head,
|
||||
"review_path": "candidate-review.json",
|
||||
"deterministic_fail": deterministic_fail,
|
||||
"checkpoint_revision": state.active_revision,
|
||||
"atomic_id": action.atomic_id,
|
||||
"fragment_hash": reviewed_fragment_hash,
|
||||
"failure_exact_fingerprint": failure_exact_fingerprint,
|
||||
"normalized_error_code": ErrorCode.CANDIDATE_REVIEW_REJECTED.value,
|
||||
"failure_class_fingerprint": failure_class_fingerprint,
|
||||
"attempt": len(prior_failures) + 1,
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Accepted(result)
|
||||
operation_failures = candidate.get("operation_failures") if isinstance(candidate.get("operation_failures"), list) else []
|
||||
candidate_blockers = candidate.get("blockers") if isinstance(candidate.get("blockers"), list) else []
|
||||
needs_repair = review.verdict != "accept" or bool(deterministic_fail) or bool(operation_failures) or bool(candidate_blockers)
|
||||
revision_id = self._next_revision(task_id)
|
||||
if published_revision and published_revision != revision_id:
|
||||
return Rejected(WorkflowError(ErrorCode.STORAGE_FAILURE, "Published candidate revision does not match the current checkpoint lineage.", retryable=True))
|
||||
@@ -755,9 +741,9 @@ class ActionCommandHandler:
|
||||
event="candidate_publish_storage_failure",
|
||||
message=str(error),
|
||||
)
|
||||
next_state = transition(state, "candidate_accepted", active_revision=revision_id, repair_required=False)
|
||||
event = {"event": "accepted", "action_id": action.action_id, "working_head_before": action.working_head, "parent_revision": state.active_revision, "revision_id": revision_id, "actual_atomic_id": action.atomic_id, "fragment_hash": candidate.get("fragment_hash"), "selector_snapshot_id": candidate.get("selector_snapshot_id"), "candidate_id": state.candidate_id, "review_path": f"revisions/{revision_id}/candidate-review.json", "coverage": actual}
|
||||
result = {"candidate_id": state.candidate_id, "revision_id": revision_id, "paths": paths, "status": "accepted"}
|
||||
next_state = transition(state, "candidate_accepted", active_revision=revision_id, repair_required=needs_repair, error=ErrorCode.CLAIM_VERIFICATION_FAILED if needs_repair else None)
|
||||
event = {"event": "accepted", "action_id": action.action_id, "working_head_before": action.working_head, "parent_revision": state.active_revision, "revision_id": revision_id, "actual_atomic_id": action.atomic_id, "fragment_hash": candidate.get("fragment_hash"), "selector_snapshot_id": candidate.get("selector_snapshot_id"), "candidate_id": state.candidate_id, "review_path": f"revisions/{revision_id}/candidate-review.json", "coverage": actual, "issues": list(review.issues), "operation_failures": operation_failures, "repair_required": needs_repair}
|
||||
result = {"candidate_id": state.candidate_id, "revision_id": revision_id, "paths": paths, "status": "accepted_with_issues" if needs_repair else "accepted"}
|
||||
if not self._commit_invocation(next_state, [event], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Accepted(result)
|
||||
@@ -833,21 +819,6 @@ class ActionCommandHandler:
|
||||
invocation = self.repository.begin_invocation(task_id, f"{task_id}_recover_build_{secrets.token_hex(8)}", key) if key else None
|
||||
if invocation is not None and invocation.status == "finished" and invocation.result is not None:
|
||||
return Accepted(invocation.result)
|
||||
if blockers:
|
||||
failed = transition(state, "candidate_rejected", candidate_id="", candidate_stage_id="", repair_required=True, error=ErrorCode.CLAIM_VERIFICATION_FAILED)
|
||||
result = {"candidate_id": state.candidate_id, "status": "rejected", "code": ErrorCode.CLAIM_VERIFICATION_FAILED.value, "claim_results": claim_results}
|
||||
event = {
|
||||
"event": "candidate_recovered_rejected",
|
||||
"candidate_id": state.candidate_id,
|
||||
"stage_id": state.candidate_stage_id,
|
||||
"action_id": action.action_id,
|
||||
"working_head": action.working_head,
|
||||
"claim_results": claim_results,
|
||||
}
|
||||
committed = self._commit_invocation(failed, [event], invocation, result) if invocation is not None else self.repository.compare_and_swap(failed, events=[event])
|
||||
if not committed:
|
||||
return Rejected(self._stale())
|
||||
return Accepted(result)
|
||||
review = transition(state, "candidate_built", candidate_id=state.candidate_id, candidate_stage_id=state.candidate_stage_id)
|
||||
result = {"candidate_id": state.candidate_id, "stage_id": state.candidate_stage_id, "status": "awaiting_review", "claim_results": claim_results}
|
||||
committed = self._commit_invocation(review, [{"event": "candidate_recovered", "candidate_id": state.candidate_id, "action_id": action.action_id, "claim_results": claim_results}], invocation, result) if invocation is not None else self.repository.compare_and_swap(review, events=[{"event": "candidate_recovered", "candidate_id": state.candidate_id, "action_id": action.action_id, "claim_results": claim_results}])
|
||||
@@ -855,6 +826,43 @@ class ActionCommandHandler:
|
||||
return Rejected(self._stale())
|
||||
return Accepted(result)
|
||||
|
||||
def finalize_best_effort(self, task_id: str, *, reason: ErrorCode, invocation_id: str) -> Accepted | Rejected:
|
||||
"""Publish the last executable checkpoint when further repair is bounded.
|
||||
|
||||
This is deliberately separate from strict final validation. It does
|
||||
not claim that unmet acceptance targets passed; it makes the usable
|
||||
model and its measured gaps durable instead of converting a planning
|
||||
dead-end into a failed task with no deliverable.
|
||||
"""
|
||||
state = self.repository.get_state(task_id)
|
||||
if state is None or not state.active_revision:
|
||||
return Rejected(WorkflowError(ErrorCode.AUTHOR_DECISION_REJECTED, "Best-effort completion requires an executable checkpoint."))
|
||||
if state.phase == TaskPhase.COMPLETED:
|
||||
return Accepted({"status": "completed", "revision_id": state.active_revision})
|
||||
key = self._key(task_id, "best_effort_complete", state.active_revision, {"reason": reason.value})
|
||||
invocation = self.repository.begin_invocation(task_id, invocation_id, key)
|
||||
if invocation.status == "finished" and invocation.result is not None:
|
||||
return Accepted(invocation.result)
|
||||
claim_results = self._evaluate_claims(task_id, self._facts(task_id, state.active_revision))
|
||||
issues = [
|
||||
f"{item.get('claim_kind')}: {item.get('status')}"
|
||||
for item in claim_results
|
||||
if item.get("status") != "pass"
|
||||
]
|
||||
next_state = transition(state, "best_effort_completed", error=ErrorCode.BEST_EFFORT_COMPLETED, repair_required=False)
|
||||
result = {"status": "completed_with_warnings", "revision_id": state.active_revision, "claim_results": claim_results, "issues": issues}
|
||||
if not self._commit_invocation(next_state, [{
|
||||
"event": "completed_best_effort",
|
||||
"revision_id": state.active_revision,
|
||||
"termination_code": reason.value,
|
||||
"message": "Further CAD repair was bounded; the last executable checkpoint was published.",
|
||||
"issues": issues,
|
||||
"claim_results": claim_results,
|
||||
"completion_result_path": "completion-result.md",
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Accepted(result)
|
||||
|
||||
def record_final_review(self, task_id: str, review: FinalReview, *, invocation_id: str) -> Accepted | Rejected:
|
||||
state = self.repository.get_state(task_id)
|
||||
if state is None or state.phase != TaskPhase.FINAL_VALIDATION:
|
||||
@@ -901,6 +909,19 @@ class ActionCommandHandler:
|
||||
message=str(error),
|
||||
)
|
||||
if review.verdict != "pass" or deterministic_fail or visual_not_passed:
|
||||
accepted_fragment = next((
|
||||
event.get("fragment_hash") for event in reversed(self.repository.ledger_events(task_id))
|
||||
if event.get("event") == "accepted" and event.get("revision_id") == state.active_revision
|
||||
), "")
|
||||
atomic_id = next((
|
||||
str(event.get("actual_atomic_id") or "") for event in reversed(self.repository.ledger_events(task_id))
|
||||
if event.get("event") == "accepted" and event.get("revision_id") == state.active_revision
|
||||
), "")
|
||||
exact_fingerprint = canonical_hash({
|
||||
"active_revision": state.active_revision,
|
||||
"atomic_id": atomic_id,
|
||||
"fragment_hash": accepted_fragment,
|
||||
}) if accepted_fragment and atomic_id else ""
|
||||
next_state = transition(state, "final_repair", repair_required=True, error=ErrorCode.CLAIM_VERIFICATION_FAILED if deterministic_fail else ErrorCode.CANDIDATE_REVIEW_REJECTED)
|
||||
result = {"status": "repair", "revision_id": state.active_revision}
|
||||
if not self._commit_invocation(next_state, [{
|
||||
@@ -909,6 +930,18 @@ class ActionCommandHandler:
|
||||
"claim_results": claim_results,
|
||||
"review_claim_coverage": [item.model_dump(mode="json") for item in review.claim_coverage],
|
||||
"visual_not_passed": [str(item.get("claim_id") or "") for item in visual_not_passed],
|
||||
"issues": list(review.issues),
|
||||
"evidence": list(review.evidence),
|
||||
"failed_checklist_items": [
|
||||
str(requirement.get("statement") or "")
|
||||
for requirement in (self._requirements_contract(task_id) or {}).get("requirements") or ()
|
||||
if isinstance(requirement, dict)
|
||||
and any(str(claim.get("claim_id") or "") in {str(item.get("claim_id") or "") for item in deterministic_fail + visual_not_passed} for claim in requirement.get("acceptance_claims") or () if isinstance(claim, dict))
|
||||
],
|
||||
"atomic_id": atomic_id,
|
||||
"fragment_hash": accepted_fragment,
|
||||
"failure_exact_fingerprint": exact_fingerprint,
|
||||
"normalized_error_code": ErrorCode.CLAIM_VERIFICATION_FAILED.value if deterministic_fail else ErrorCode.CANDIDATE_REVIEW_REJECTED.value,
|
||||
}], invocation, result):
|
||||
return Rejected(self._stale())
|
||||
return Accepted(result)
|
||||
|
||||
Reference in New Issue
Block a user