Files
OpenOPC/opc/layer2_organization/metadata_ownership.py
T

628 lines
41 KiB
Python

"""Company-mode metadata ownership rules.
This module is the executable owner matrix for WorkItem/runtime Task
metadata. In company mode, DelegationWorkItem owns business/collaboration
state; runtime Task owns execution/session/audit state. Task may carry a
small execution-copy envelope, but those copies are not scheduling facts.
"""
from __future__ import annotations
import copy
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Iterable, Mapping
from opc.core.models import DelegationWorkItem, Task
from opc.layer2_organization.work_item_links import linked_work_item_id_for_task
class MetadataOwner(str, Enum):
WORK_ITEM = "work_item"
RUNTIME_TASK = "runtime_task"
EXECUTION_COPY = "execution_copy"
@dataclass(frozen=True)
class MetadataFieldSpec:
key: str
owner: MetadataOwner
allowed_locations: tuple[str, ...] = ("work_item",)
legacy_fallback: bool = False
migration_policy: str = ""
description: str = ""
@property
def allows_task_execution_copy(self) -> bool:
return "task_execution_copy" in self.allowed_locations
@property
def allows_task_legacy_read(self) -> bool:
return "task_legacy_read" in self.allowed_locations or self.legacy_fallback
@dataclass(frozen=True)
class MetadataOwnershipIssue:
code: str
severity: str
key: str
owner: str
work_item_id: str = ""
runtime_task_id: str = ""
message: str = ""
details: dict[str, Any] = field(default_factory=dict)
@dataclass(frozen=True)
class MetadataOwnershipMigrationChange:
work_item_id: str
runtime_task_id: str
updates: dict[str, Any]
conflicts: dict[str, dict[str, Any]] = field(default_factory=dict)
@dataclass(frozen=True)
class MetadataOwnershipMigrationReport:
dry_run: bool
scanned_work_items: int
changed_work_items: int
changes: tuple[MetadataOwnershipMigrationChange, ...]
issues: tuple[MetadataOwnershipIssue, ...] = ()
def _spec(
key: str,
owner: MetadataOwner,
*,
allowed_locations: Iterable[str] | None = None,
legacy_fallback: bool = False,
migration_policy: str = "",
description: str = "",
) -> MetadataFieldSpec:
if allowed_locations is None:
allowed_locations = ("work_item",) if owner == MetadataOwner.WORK_ITEM else ("task",)
return MetadataFieldSpec(
key=key,
owner=owner,
allowed_locations=tuple(allowed_locations),
legacy_fallback=legacy_fallback,
migration_policy=migration_policy,
description=description,
)
_WORK_ITEM_FIELDS: tuple[MetadataFieldSpec, ...] = (
_spec("work_kind", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("current_turn_mode", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("dependency_work_item_ids", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("waiting_on_work_item_ids", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("delegated_children_pending", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("handoff_context", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("context_preview", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("prompt_contract", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("review_target_prompt_contract", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("report_target_prompt_contract", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("prompt_contract_blocker", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("manager_mutation_revision", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("manager_mutation_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("manager_mutation_action", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("manager_mutation_reason", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("manager_mutation_at", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("manager_mutation_by_role_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("manager_mutation_by_seat_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("manager_mutation_user_input", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("latest_user_directive", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("progress_log", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_legacy_read"), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("work_item_role_name", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("employee_assignment", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("employee_prompt_context", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("employee_delta_context", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("completion_report", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("deliverable_summary", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("work_item_summary", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("work_item_summary_for_downstream", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("work_item_artifact_index", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("verification_status", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("verification_evidence", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("verification", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("structured_review_verdict", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("review_owner_role_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_owner_seat_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_attempt", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_attempt_count", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_target_work_item_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_source_report_work_item_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
_spec("review_resolution", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
_spec("review_resolution_state", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
_spec("review_resolution_applied_work_item_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
_spec("review_target_worker_task_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_target_worker_role_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_target_worker_seat_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_completion_report", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_target_title", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_target_description", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_evidence", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("rework_feedback", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_feedback_version", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_rework_count", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_retry_hint", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_retry_of_attempt", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("review_retry_reason", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_attempt", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_attempt_count", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_target_work_item_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_target_worker_task_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_target_worker_role_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_target_worker_seat_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_target_title", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_target_description", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_source_summary", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_source_result_content", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("report_source_evidence", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("follow_up_actions", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("follow_up_action", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("follow_up_reason", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("follow_up_dedupe_key", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("synthesis_turn_started", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("synthesis_ready_at", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("synthesis_source_work_item_ids", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("synthesis_reports_to_role_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("synthesis_reports_to_seat_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), legacy_fallback=True, migration_policy="work_item_wins"),
_spec("delivery_package", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("downstream_assignments", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("open_questions", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("assumptions", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("decisions", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("risks", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), legacy_fallback=True, migration_policy="backfill_if_missing"),
_spec("self_evolution_work_item", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_root", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_checkpoint_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_human_action", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_human_feedback", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_delivery_task_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_delivery_projection_id", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_delivery_summary", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_patch_max_retries", MetadataOwner.WORK_ITEM, allowed_locations=("work_item", "task_execution_copy"), migration_policy="work_item_wins"),
_spec("self_evolution_recorded", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
_spec("self_evolution_patch", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
_spec("self_evolution_completed_at", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
_spec("self_evolution_error", MetadataOwner.WORK_ITEM, allowed_locations=("work_item",), migration_policy="work_item_wins"),
)
_RUNTIME_TASK_FIELDS: tuple[MetadataFieldSpec, ...] = (
_spec("runtime_v2", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("runtime_verification", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("runtime_verification_evidence", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("runtime_verification_status", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("member_session_state", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("external_resume_session_id", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("external_resume_agent_type", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("working_memory", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("interrupted_recovery", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("last_stop_reason", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("peer_wait", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("comms_cross_role_history", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("comms_last_blocked_reactivation_at", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("comms_last_blocked_reactivation_key", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("runtime_control_state", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("automated_verification_results", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("runtime_session_team_instance_id", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("runtime_session_team_id", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
_spec("runtime_session_seat_id", MetadataOwner.RUNTIME_TASK, allowed_locations=("task",), migration_policy="task_only"),
)
_EXECUTION_COPY_FIELDS: tuple[MetadataFieldSpec, ...] = (
_spec("mode", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("execution_mode", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("execution_model", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("runtime_model", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("original_message", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("company_profile", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("delegation_playbook", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("runtime_topology", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("organization_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("org_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("delegation_run_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("delegation_cell_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("delegation_team_instance_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("delegation_team_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("delegation_seat_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("delegation_role_session_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("work_item_role_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("seat_manager_role_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("manager_role_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("manager_seat_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("managed_team_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("seat_contact_role_ids", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("allowed_delegate_role_ids", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("force_native_execution", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("preferred_external_agent", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("selected_execution_agent", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("execution_agent_locked", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("selected_execution_agent_source", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("work_item_execution_strategy", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("adaptive", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("execution_task_ids", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("parent_session_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("work_item_batch_id", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("target_output_dir", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("output_root", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("workspace_root", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("comms_workspace_root", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("comms_root", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("user_visible", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("authoritative_output", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("review_owner_kind", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("requires_user_feedback", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("feedback_scope", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("review_task", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("review_execution_work_item", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("report_execution_work_item", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
_spec("skip_work_item_sync", MetadataOwner.EXECUTION_COPY, allowed_locations=("task_execution_copy",), migration_policy="copy_from_runtime_context"),
)
METADATA_FIELD_SPECS: dict[str, MetadataFieldSpec] = {
spec.key: spec
for spec in (
*_WORK_ITEM_FIELDS,
*_RUNTIME_TASK_FIELDS,
*_EXECUTION_COPY_FIELDS,
)
}
WORK_ITEM_OWNED_KEYS: frozenset[str] = frozenset(
key for key, spec in METADATA_FIELD_SPECS.items() if spec.owner == MetadataOwner.WORK_ITEM
)
RUNTIME_TASK_OWNED_KEYS: frozenset[str] = frozenset(
key for key, spec in METADATA_FIELD_SPECS.items() if spec.owner == MetadataOwner.RUNTIME_TASK
)
EXECUTION_COPY_KEYS: frozenset[str] = frozenset(
key
for key, spec in METADATA_FIELD_SPECS.items()
if spec.owner == MetadataOwner.EXECUTION_COPY or spec.allows_task_execution_copy
)
LEGACY_READONLY_KEYS: frozenset[str] = frozenset()
def metadata_owner_for_key(key: str) -> MetadataOwner | None:
spec = METADATA_FIELD_SPECS.get(str(key or "").strip())
return spec.owner if spec is not None else None
def metadata_spec_for_key(key: str) -> MetadataFieldSpec | None:
return METADATA_FIELD_SPECS.get(str(key or "").strip())
def is_work_item_owned_key(key: str) -> bool:
return metadata_owner_for_key(key) == MetadataOwner.WORK_ITEM
def is_runtime_task_owned_key(key: str) -> bool:
return metadata_owner_for_key(key) == MetadataOwner.RUNTIME_TASK
def is_execution_copy_key(key: str) -> bool:
return str(key or "").strip() in EXECUTION_COPY_KEYS
def supports_legacy_task_fallback(key: str) -> bool:
spec = metadata_spec_for_key(key)
return bool(spec and spec.legacy_fallback)
def _has_value(value: Any) -> bool:
return value not in (None, "", [], {})
def copy_work_item_execution_metadata(
work_item: DelegationWorkItem | None,
*,
keys: Iterable[str] | None = None,
) -> dict[str, Any]:
"""Return WorkItem-owned values allowed on Task as execution copies."""
if work_item is None:
return {}
metadata = dict(getattr(work_item, "metadata", {}) or {})
selected = list(keys) if keys is not None else sorted(EXECUTION_COPY_KEYS)
copied: dict[str, Any] = {}
for key in selected:
spec = metadata_spec_for_key(key)
if spec is None or not spec.allows_task_execution_copy:
continue
if key not in metadata:
continue
value = metadata.get(key)
if not _has_value(value):
continue
copied[key] = copy.deepcopy(value)
return copied
def build_work_item_owner_execution_copy(work_item: DelegationWorkItem | None) -> dict[str, Any]:
"""Build the runtime Task owner envelope from the WorkItem facts."""
if work_item is None:
return {}
metadata = dict(getattr(work_item, "metadata", {}) or {})
payload = {
"delegation_run_id": str(getattr(work_item, "run_id", "") or "").strip(),
"delegation_cell_id": str(getattr(work_item, "cell_id", "") or "").strip(),
"delegation_team_instance_id": str(getattr(work_item, "team_instance_id", "") or "").strip(),
"delegation_team_id": str(
getattr(work_item, "team_id", "")
or metadata.get("team_id", "")
or getattr(work_item, "cell_id", "")
or ""
).strip(),
"delegation_seat_id": str(
getattr(work_item, "seat_id", "")
or metadata.get("seat_id", "")
or ""
).strip(),
"delegation_role_session_id": str(
getattr(work_item, "role_runtime_session_id", "")
or metadata.get("assigned_role_runtime_id", "")
or ""
).strip(),
"work_item_role_id": str(getattr(work_item, "role_id", "") or metadata.get("role_id", "") or "").strip(),
"work_kind": str(metadata.get("work_kind", "") or getattr(work_item, "kind", "") or "").strip().lower(),
"manager_role_id": str(getattr(work_item, "manager_role_id", "") or metadata.get("manager_role_id", "") or "").strip(),
"manager_seat_id": str(getattr(work_item, "manager_seat_id", "") or metadata.get("manager_seat_id", "") or "").strip(),
"work_item_batch_id": str(getattr(work_item, "batch_id", "") or "").strip(),
}
return {
key: copy.deepcopy(value)
for key, value in payload.items()
if key in EXECUTION_COPY_KEYS and _has_value(value)
}
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 {})
removed: list[str] = []
for key in sorted(WORK_ITEM_OWNED_KEYS):
if key in EXECUTION_COPY_KEYS:
continue
if key in metadata:
metadata.pop(key, None)
removed.append(key)
if removed:
task.metadata = metadata
return removed
def filter_work_item_owned_metadata(updates: Mapping[str, Any]) -> dict[str, Any]:
return {
str(key): copy.deepcopy(value)
for key, value in dict(updates or {}).items()
if is_work_item_owned_key(str(key)) and _has_value(value)
}
def filter_runtime_task_owned_metadata(updates: Mapping[str, Any]) -> dict[str, Any]:
return {
str(key): copy.deepcopy(value)
for key, value in dict(updates or {}).items()
if is_runtime_task_owned_key(str(key)) and _has_value(value)
}
def validate_metadata_ownership(
work_item: DelegationWorkItem | None,
task: Task | None,
) -> list[MetadataOwnershipIssue]:
"""Read-only diagnostics for WorkItem/runtime Task metadata drift."""
if work_item is None and task is None:
return []
item_metadata = dict(getattr(work_item, "metadata", {}) or {}) if work_item is not None else {}
task_metadata = dict(getattr(task, "metadata", {}) or {}) if task is not None else {}
work_item_id = str(getattr(work_item, "work_item_id", "") or "").strip() or linked_work_item_id_for_task(task)
runtime_task_id = str(getattr(task, "id", "") or "").strip()
issues: list[MetadataOwnershipIssue] = []
for key in sorted(WORK_ITEM_OWNED_KEYS):
if key not in task_metadata:
continue
task_value = task_metadata.get(key)
if not _has_value(task_value):
continue
work_item_has_value = key in item_metadata and _has_value(item_metadata.get(key))
if not work_item_has_value:
issues.append(
MetadataOwnershipIssue(
code="metadata_ownership_violation",
severity="warning",
key=key,
owner=MetadataOwner.WORK_ITEM.value,
work_item_id=work_item_id,
runtime_task_id=runtime_task_id,
message=f"WorkItem-owned metadata `{key}` is present on runtime Task but missing on WorkItem.",
)
)
continue
if item_metadata.get(key) != task_value and not is_execution_copy_key(key):
issues.append(
MetadataOwnershipIssue(
code="metadata_ownership_conflict",
severity="warning",
key=key,
owner=MetadataOwner.WORK_ITEM.value,
work_item_id=work_item_id,
runtime_task_id=runtime_task_id,
message=f"WorkItem-owned metadata `{key}` differs between WorkItem and runtime Task; WorkItem wins.",
details={"work_item_value": item_metadata.get(key), "task_value": task_value},
)
)
for key in sorted(RUNTIME_TASK_OWNED_KEYS):
if key in item_metadata and _has_value(item_metadata.get(key)):
issues.append(
MetadataOwnershipIssue(
code="metadata_ownership_violation",
severity="warning",
key=key,
owner=MetadataOwner.RUNTIME_TASK.value,
work_item_id=work_item_id,
runtime_task_id=runtime_task_id,
message=f"Runtime Task-owned metadata `{key}` should not be stored on WorkItem.",
)
)
return issues
async def update_work_item_owned_metadata(
store: Any,
work_item_id: str,
updates: Mapping[str, Any],
) -> dict[str, Any]:
"""Persist only WorkItem-owned metadata updates through the store."""
filtered = filter_work_item_owned_metadata(updates)
if not filtered or store is None or not hasattr(store, "update_delegation_work_item"):
return {}
await store.update_delegation_work_item(work_item_id, metadata_updates=filtered)
return filtered
async def append_work_item_progress(
store: Any,
work_item_id: str,
message: str,
*,
limit: int = 20,
dedupe: bool = False,
) -> list[Any]:
"""Append user-visible progress to the WorkItem-owned progress log."""
wid = str(work_item_id or "").strip()
note = str(message or "").strip()
if not wid or not note or store is None or not hasattr(store, "get_delegation_work_item"):
return []
try:
work_item = await store.get_delegation_work_item(wid)
except Exception:
return []
if work_item is None:
return []
metadata = dict(getattr(work_item, "metadata", {}) or {})
progress = list(metadata.get("progress_log", []) or [])
if not dedupe or note not in progress:
progress.append(note)
progress = progress[-max(1, int(limit or 20)) :]
await update_work_item_owned_metadata(store, wid, {"progress_log": progress})
return progress
async def sync_work_item_current_turn_mode(
store: Any,
work_item_id: str,
current_turn_mode: str,
) -> bool:
"""Persist the WorkItem-owned current turn mode from runtime evaluation."""
wid = str(work_item_id or "").strip()
mode = str(current_turn_mode or "").strip()
if not wid or not mode:
return False
return bool(await update_work_item_owned_metadata(store, wid, {"current_turn_mode": mode}))
def update_runtime_task_owned_metadata(task: Task, updates: Mapping[str, Any]) -> dict[str, Any]:
"""Apply only runtime Task-owned metadata updates to an in-memory Task."""
filtered = filter_runtime_task_owned_metadata(updates)
if not filtered:
return {}
task.metadata = {**dict(task.metadata or {}), **filtered}
return filtered
async def migrate_work_item_owned_metadata_from_linked_tasks(
store: Any,
*,
run_id: str | None = None,
work_item_ids: Iterable[str] | None = None,
dry_run: bool = True,
) -> MetadataOwnershipMigrationReport:
"""Explicit maintenance backfill from legacy Task metadata to WorkItem.
This is intentionally not called from hot read paths. WorkItem wins on
conflicts; only missing WorkItem-owned keys are backfilled.
"""
if store is None:
return MetadataOwnershipMigrationReport(True, 0, 0, ())
items: list[DelegationWorkItem] = []
if work_item_ids is not None:
getter = getattr(store, "get_delegation_work_item", None)
if callable(getter):
for raw_id in work_item_ids:
wid = str(raw_id or "").strip()
if not wid:
continue
item = await getter(wid)
if item is not None:
items.append(item)
elif run_id:
lister = getattr(store, "list_delegation_work_items", None)
if callable(lister):
items = list(await lister(str(run_id).strip()))
get_runtime_task = getattr(store, "get_runtime_task_for_work_item", None)
changes: list[MetadataOwnershipMigrationChange] = []
issues: list[MetadataOwnershipIssue] = []
for item in items:
wid = str(getattr(item, "work_item_id", "") or "").strip()
if not wid or not callable(get_runtime_task):
continue
task = await get_runtime_task(wid)
if task is None:
continue
item_metadata = dict(item.metadata or {})
task_metadata = dict(task.metadata or {})
updates: dict[str, Any] = {}
conflicts: dict[str, dict[str, Any]] = {}
for key in sorted(WORK_ITEM_OWNED_KEYS):
if key not in task_metadata or not _has_value(task_metadata.get(key)):
continue
if key not in item_metadata or not _has_value(item_metadata.get(key)):
spec = metadata_spec_for_key(key)
if spec is not None and spec.legacy_fallback:
updates[key] = copy.deepcopy(task_metadata.get(key))
continue
if item_metadata.get(key) != task_metadata.get(key):
conflicts[key] = {
"work_item_value": copy.deepcopy(item_metadata.get(key)),
"task_value": copy.deepcopy(task_metadata.get(key)),
}
if conflicts:
for key in sorted(conflicts):
issues.append(
MetadataOwnershipIssue(
code="metadata_ownership_conflict",
severity="warning",
key=key,
owner=MetadataOwner.WORK_ITEM.value,
work_item_id=wid,
runtime_task_id=str(getattr(task, "id", "") or "").strip(),
message=f"WorkItem-owned metadata `{key}` conflicts during migration; WorkItem wins.",
details=conflicts[key],
)
)
if not updates:
continue
changes.append(
MetadataOwnershipMigrationChange(
work_item_id=wid,
runtime_task_id=str(getattr(task, "id", "") or "").strip(),
updates=updates,
conflicts=conflicts,
)
)
if not dry_run and hasattr(store, "update_delegation_work_item"):
await store.update_delegation_work_item(wid, metadata_updates=updates)
return MetadataOwnershipMigrationReport(
dry_run=bool(dry_run),
scanned_work_items=len(items),
changed_work_items=len(changes),
changes=tuple(changes),
issues=tuple(issues),
)