Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions docs/evidence/OMN-11003-model-collision-classification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# OMN-11003 Model Collision Classification

Date: 2026-05-16

Scope: duplicate Python model-name collisions from D4, focused on delegation,
routing, and task-contract names. This slice does not change memory DTOs
(OMN-11015) or intelligence DTOs (OMN-11017), and leaves the explicit
OMN-8596/OMN-8598 families to those tickets except as reference rows.

## Classification

| Collision family | Current locations | Bucket | Owner decision |
| --- | --- | --- | --- |
| `ModelDelegationEvent` | `omniclaude/src/omniclaude/delegation/sqlite_adapter.py`; `omnimarket/src/omnimarket/nodes/node_delegation_orchestrator/models/model_delegation_event.py` | canonical-shared for omnimarket wrapper; intentional local for omniclaude SQLite input | Burned down in this slice by making the omnimarket path re-export canonical `omnibase_compat.contracts.delegation.wire.ModelDelegationEventEnvelope`. The omniclaude class is a local persistence input and is no longer cross-repo-colliding after this change. |
| `ModelDispatchRecord` | `omniclaude/src/omniclaude/hooks/model_dispatch_record.py`; `omnimarket/src/omnimarket/nodes/node_dispatch_worker/models/model_dispatch_record.py`; `omnimarket/src/omnimarket/nodes/node_build_dispatch_effect/handlers/dispatch_history_store.py` | rename/consolidate | High-risk dispatch history collision, but related ticket OMN-10170 already owns the shared `ModelDispatchRecord` relocation path. Defer implementation to avoid competing canonical-home decisions. |
| `ModelRoutingDecision` | `omniclaude`, `omnibase_compat`, `omnimarket`, `omnibase_infra` routing/observability paths | rename/consolidate | Reference only. OMN-8596 owns this family and should decide whether `omnibase_compat.overseer.ModelRoutingDecision` remains canonical or is split by semantic role. |
| `ModelTaskContract`, `ModelMechanicalCheck`, `EnumCheckType` | `omniclaude`, `omnimarket`, `omnibase_core` task-contract/self-check paths | rename/consolidate | Reference only. OMN-8598 owns this family. No task-contract DTO movement in this slice. |

## First Burn-Down Slice

Changed `omnimarket.nodes.node_delegation_orchestrator.models.model_delegation_event`
from a local Pydantic class definition into a compatibility import:

`ModelDelegationEvent = omnibase_compat.contracts.delegation.wire.ModelDelegationEventEnvelope`

This keeps existing omnimarket import paths and handler call sites stable while
removing the local class definition that D4 counted as a cross-repo collision.

## D4 Evidence

Baseline scan against canonical `$OMNI_HOME` before applying the worktree
overlay:

```text
D4 status=FAIL finding_count=183
ModelDelegationEvent: ['omniclaude/src/omniclaude/delegation/sqlite_adapter.py', 'omnimarket/src/omnimarket/nodes/node_delegation_orchestrator/models/model_delegation_event.py']
```

Overlay scan with this OMN-11003 omnimarket worktree replacing canonical
omnimarket in a temporary mini-workspace:

```text
ModelDelegationEvent: []
ModelRoutingDecision: ['omniclaude/src/omniclaude/routing/routing_recorder.py', 'omnibase_compat/src/omnibase_compat/overseer/model_routing_decision.py', 'omnimarket/src/omnimarket/nodes/node_delegation_routing_reducer/models/model_routing_decision.py', 'omnimarket/src/omnimarket/nodes/node_local_supervisor/models/model_local_supervisor_request.py', 'omnibase_infra/src/omnibase_infra/nodes/node_model_router_compute/models/model_routing_decision.py', 'omnibase_infra/src/omnibase_infra/services/observability/agent_actions/models/model_routing_decision.py']
ModelTaskContract: ['omniclaude/src/omniclaude/contracts/task_contract_generator.py', 'omniclaude/src/omniclaude/verification/self_check.py', 'omnimarket/src/omnimarket/nodes/node_session_bootstrap/models/model_task_contract.py']
ModelDispatchRecord: ['omniclaude/src/omniclaude/hooks/model_dispatch_record.py', 'omnimarket/src/omnimarket/nodes/node_build_dispatch_effect/handlers/dispatch_history_store.py', 'omnimarket/src/omnimarket/nodes/node_dispatch_worker/models/model_dispatch_record.py']
D4 status=FAIL finding_count=182
ModelDelegationEvent absent=True
```

Residual D4 failures are expected: `ModelRoutingDecision` is OMN-8596,
task-contract models are OMN-8598, and `ModelDispatchRecord` needs a separate
OMN-10170-aligned shared-model migration.
53 changes: 53 additions & 0 deletions docs/work-tracking/contracts/OMN-11003.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
schema_version: "1.0.0"
ticket_id: "OMN-11003"
title: "Classify duplicate model collisions and burn down delegation event wrapper"
summary: >
Classifies the high-risk delegation/routing/task-contract D4 model-name
collision families and removes omnimarket's local ModelDelegationEvent class
definition by re-exporting the canonical omnibase_compat delegation event
envelope while preserving existing omnimarket import paths.
is_seam_ticket: false
interface_change: false
interfaces_touched: []
emergency_bypass:
enabled: false
justification: ""
follow_up_ticket_id: ""
dod_evidence:
- id: "dod-classification-evidence"
description: "Collision families are classified into canonical-shared, intentional local, and rename/consolidate buckets."
source: "manual"
checks:
- check_type: "command"
check_value: "test -f docs/evidence/OMN-11003-model-collision-classification.md && grep -q 'ModelDelegationEvent' docs/evidence/OMN-11003-model-collision-classification.md && grep -q 'ModelDispatchRecord' docs/evidence/OMN-11003-model-collision-classification.md"
- id: "dod-focused-tests"
description: "Focused delegation compatibility and workflow tests pass."
source: "manual"
checks:
- check_type: "command"
check_value: "uv run pytest tests/test_delegation_dto_omnibase_compat_imports.py tests/unit/delegation/test_delegation_orchestrator.py tests/unit/delegation/test_dispatcher_event_bus.py tests/unit/nodes/node_delegate_skill_orchestrator/test_runtime_dispatch_port.py -q"
- id: "dod-lint"
description: "Touched compatibility shim and focused test files pass ruff."
source: "manual"
checks:
- check_type: "command"
check_value: "uv run ruff check src/omnimarket/nodes/node_delegation_orchestrator/models/model_delegation_event.py tests/test_delegation_dto_omnibase_compat_imports.py tests/unit/delegation/test_dispatcher_event_bus.py"
- id: "dod-d4-targeted"
description: >
D4 overlay scan with this omnimarket worktree removes the targeted
ModelDelegationEvent collision and reduces broad D4 findings from 183 to
182; residual routing/task-contract/dispatch-record collisions remain
intentionally scoped to follow-up tickets.
source: "manual"
checks:
- check_type: "command"
check_value: "D4 overlay: ModelDelegationEvent absent=True; finding_count=182"
- id: "dod-deploy"
description: >
Import compatibility change only. No live deploy, runtime restart, .201
mutation, or event-bus write is required pre-merge.
source: "manual"
checks:
- check_type: "command"
check_value: "printf '%s\n' 'deploy gate: no live deploy/restart required for DTO compatibility import'"
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,12 @@
# SPDX-License-Identifier: MIT

# Copyright (c) 2026 OmniNode Team
"""Delegation event model emitted by the delegation orchestrator."""
"""Compatibility import for the canonical delegation event envelope."""

from __future__ import annotations

from omnibase_compat.contracts.delegation.wire import ModelDelegationResult
from pydantic import BaseModel, ConfigDict


class ModelDelegationEvent(BaseModel):
"""Event emitted when the orchestrator completes or fails a delegation."""

model_config = ConfigDict(frozen=True, extra="forbid")

topic: str
payload: ModelDelegationResult

from omnibase_compat.contracts.delegation.wire import (
ModelDelegationEventEnvelope as ModelDelegationEvent,
)

__all__: list[str] = ["ModelDelegationEvent"]
2 changes: 2 additions & 0 deletions tests/test_delegation_dto_omnibase_compat_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"omnimarket.nodes.node_delegation_orchestrator.models.model_compliance_loop_result.ModelComplianceLoopResult": "omnibase_compat.contracts.delegation.wire.ModelComplianceLoopResult",
"omnimarket.nodes.node_delegation_orchestrator.models.ModelDelegationRequest": "omnibase_compat.contracts.delegation.wire.ModelDelegationRequest",
"omnimarket.nodes.node_delegation_orchestrator.models.ModelDelegationResult": "omnibase_compat.contracts.delegation.wire.ModelDelegationResult",
"omnimarket.nodes.node_delegation_orchestrator.models.ModelDelegationEvent": "omnibase_compat.contracts.delegation.wire.ModelDelegationEventEnvelope",
"omnimarket.nodes.node_delegation_orchestrator.models.model_delegation_event.ModelDelegationEvent": "omnibase_compat.contracts.delegation.wire.ModelDelegationEventEnvelope",
"omnimarket.nodes.node_delegation_orchestrator.models.ModelInferenceIntent": "omnibase_compat.contracts.delegation.wire.ModelInferenceIntent",
"omnimarket.nodes.node_delegation_orchestrator.models.ModelInferenceResponseData": "omnibase_compat.contracts.delegation.wire.ModelInferenceResponseData",
"omnimarket.nodes.node_delegation_orchestrator.models.ModelQualityGateIntent": "omnibase_compat.contracts.delegation.wire.ModelQualityGateIntent",
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/delegation/test_dispatcher_event_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,11 @@ async def test_envelope_payload_matches_expected_topic(self) -> None:
topic_to_payload_type = {
c.kwargs["topic"]: type(c.args[0].payload).__name__ for c in calls
}
# The envelope payload is ModelDelegationEvent (the wrapper); its .payload
# field is ModelDelegationResult. Checking the outer type is sufficient.
# The envelope payload is the canonical delegation event envelope; its
# .payload field is ModelDelegationResult.
assert (
topic_to_payload_type.get(TOPIC_DELEGATION_COMPLETED)
== "ModelDelegationEvent"
== "ModelDelegationEventEnvelope"
)
assert (
topic_to_payload_type.get(TOPIC_DELEGATION_TASK_DELEGATED)
Expand Down
Loading