fix: stop misreading per-work-item spec as run-level company plan
Every completed company session's follow-up was answered with the canned "Legacy company runtime run ... read-only" text (project 000, 2026-07-07). Root cause: snapshot loaders read task.metadata work_item_runtime_plan as a serialized run-level CompanyWorkItemRuntimePlan, but work-item tasks persist a per-item assignment spec (projection_id/turn_type/summary/deliverables/...) under that key. from_dict on the wrong shape silently yields an empty plan (no projections, empty metadata), _runtime_uses_multi_team_org returns False, and the resume path falls through to the legacy read-only branch. Add is_serialized_company_work_item_runtime_plan (a run-level plan always serializes with projections + runtime_model; a spec always carries projection_id) and route all full-plan metadata reads through serialized_company_plan_from_metadata, which skips wrong-shaped candidates so the loaders fall back to the sample-metadata-constructed plan instead of an empty one. Fixes existing DBs read-side; no data migration. Verified: old path on the 000 shape classifies multi_team_org=False, new path True; regression tests cover shape discrimination, snapshot classification, and the follow-up never reporting legacy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+4
-7
@@ -88,6 +88,7 @@ from opc.layer2_organization.company_mode import (
|
||||
deserialize_company_work_item_runtime_plan,
|
||||
serialize_company_runtime_spec,
|
||||
serialize_company_work_item_runtime_plan,
|
||||
serialized_company_plan_from_metadata,
|
||||
)
|
||||
from opc.layer2_organization.company_runtime import canonical_role_session_id
|
||||
from opc.layer2_organization.metadata_ownership import (
|
||||
@@ -4988,7 +4989,7 @@ class OPCEngine:
|
||||
|
||||
plan_data = None
|
||||
for task in sorted(latest_by_projection_id.values(), key=lambda item: (item.created_at, item.id), reverse=True):
|
||||
candidate = task.metadata.get("company_work_item_plan") or task.metadata.get("work_item_runtime_plan")
|
||||
candidate = serialized_company_plan_from_metadata(task.metadata)
|
||||
if candidate:
|
||||
plan_data = candidate
|
||||
break
|
||||
@@ -6458,7 +6459,7 @@ class OPCEngine:
|
||||
for parent_session_id, group in runtime_groups.items():
|
||||
plan_data = None
|
||||
for task in sorted(group, key=lambda item: (item.created_at, item.id), reverse=True):
|
||||
candidate = task.metadata.get("company_work_item_plan") or task.metadata.get("work_item_runtime_plan")
|
||||
candidate = serialized_company_plan_from_metadata(task.metadata)
|
||||
if candidate:
|
||||
plan_data = candidate
|
||||
break
|
||||
@@ -8112,11 +8113,7 @@ class OPCEngine:
|
||||
or task_metadata.get("company_profile", "")
|
||||
or getattr(self.config.org, "company_profile", "corporate")
|
||||
).strip() or "corporate"
|
||||
plan_payload = (
|
||||
task_metadata.get("company_work_item_plan")
|
||||
or task_metadata.get("work_item_runtime_plan")
|
||||
or {}
|
||||
)
|
||||
plan_payload = serialized_company_plan_from_metadata(task_metadata) or {}
|
||||
work_item_plan = (
|
||||
deserialize_company_work_item_runtime_plan(plan_payload)
|
||||
if isinstance(plan_payload, dict) and plan_payload
|
||||
|
||||
Reference in New Issue
Block a user