fix(company): route delete cascade through transition_work_item; centralize resume identity restore

- delete_work_item descendant cascade now goes through transition_work_item
  (audit reason, attempt-ledger settlement, phase hooks) instead of raw
  store phase writes plus manual task.status mutation; task-owned audit
  stamps and execution-lock release only happen when a cancellation
  actually occurred, removing a desync path (task=CANCELLED under
  work_item=APPROVED) in drift scenarios.
- transition_work_item gains blocked_reason/handoff_status passthrough so
  callers no longer need a second store write for the same transition.
- new build_company_resume_identity_restore helper in metadata_ownership
  replaces the ad-hoc delegation_seat_id/role/session literals in
  engine._restore_and_pin_company_resume_execution_identity, keeping seat
  identity writes inside the ownership contract module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
LZH-YS1998
2026-07-26 22:14:24 +08:00
parent 26e45217e5
commit 322a5ec9b1
4 changed files with 67 additions and 29 deletions
@@ -387,6 +387,33 @@ def build_work_item_owner_execution_copy(work_item: DelegationWorkItem | None) -
}
def build_company_resume_identity_restore(
*,
role_id: str,
seat_id: str,
role_runtime_session_id: str,
) -> dict[str, Any]:
"""Map checkpoint-validated resume identity onto Task execution-copy keys.
Company resume restores missing Task projection fields from the durable
checkpoint after the authoritative WorkItem has been cross-checked (the
checkpoint may hold values the WorkItem row lacks, so this is not always
derivable via ``build_work_item_owner_execution_copy``). The key spelling
lives here, next to the owner spec, so runtime code never hand-writes
WorkItem-owned execution-copy keys.
"""
payload: dict[str, Any] = {
"work_item_role_id": str(role_id or "").strip(),
}
seat = str(seat_id or "").strip()
if seat:
payload["delegation_seat_id"] = seat
session = str(role_runtime_session_id or "").strip()
if session:
payload["delegation_role_session_id"] = session
return payload
def strip_disallowed_work_item_metadata_from_runtime_task(task: Task) -> list[str]:
"""Remove WorkItem-owned fields that are not valid Task execution copies."""
metadata = dict(getattr(task, "metadata", {}) or {})