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
Original file line number Diff line number Diff line change
@@ -1 +1 @@
null
null
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@
"rule_id": "MISSING_TOPIC_EDGE",
"rule_version": "v1"
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
"nodes": [],
"edges": [],
"orphan_modules": []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@
"rule_version": "v1",
"captured_at": "2026-05-25T19:17:15.256588+00:00"
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ timestamp: 2026-05-25T19:17:15.259389+00:00
- **D: projection**: PASS — rows_upserted=2

## Findings count: 2
## Projection rows: 2
## Projection rows: 2
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
],
"graphify_version": "0.8.2",
"rule_version": "v1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
"pub_edges": [],
"sub_edges": [],
"orphan_topics": []
}
}
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ node_llm_delegation_projection = "omnimarket.nodes.node_llm_delegation_projectio
node_swarm_registry_compute = "omnimarket.nodes.node_swarm_registry_compute"
node_knowledge_query_federation_orchestrator = "omnimarket.nodes.node_knowledge_query_federation_orchestrator"
node_antipattern_index_effect = "omnimarket.nodes.node_antipattern_index_effect"
node_handler_correctness_gate = "omnimarket.nodes.node_handler_correctness_gate"

[project.scripts]
onex-integration-test-runner = "omnimarket.nodes.node_integration_test_runner.cli:main"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
71 changes: 71 additions & 0 deletions src/omnimarket/nodes/node_handler_correctness_gate/contract.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
name: node_handler_correctness_gate
contract_name: node_handler_correctness_gate
node_name: node_handler_correctness_gate
contract_version: {major: 1, minor: 0, patch: 0}
node_version: {major: 1, minor: 0, patch: 0}
node_type: compute
description: >
Pure compute node that scores pre-computed handler outputs against an eval
set and returns pass/fail with a correctness score. The gate itself never
invokes the handler — it only compares outputs.

input_model:
name: ModelCorrectnessCheckRequest
class: ModelCorrectnessCheckRequest
module: omnimarket.nodes.node_handler_correctness_gate.models.model_correctness_check_request

output_model:
name: ModelCorrectnessCheckResult
class: ModelCorrectnessCheckResult
module: omnimarket.nodes.node_handler_correctness_gate.models.model_correctness_check_result

handler:
name: HandlerCorrectnessGate
module: omnimarket.nodes.node_handler_correctness_gate.handlers.handler_correctness_gate
class: HandlerCorrectnessGate

handler_routing:
routing_strategy: operation_match
handlers:
- handler:
name: HandlerCorrectnessGate
module: omnimarket.nodes.node_handler_correctness_gate.handlers.handler_correctness_gate
event_model:
name: ModelCorrectnessCheckRequest
module: omnimarket.nodes.node_handler_correctness_gate.models.model_correctness_check_request

descriptor:
node_archetype: compute
purity: pure
idempotent: true
timeout_ms: 60000
runtime_profiles: [main]

event_bus:
version: {major: 1, minor: 0, patch: 0}
plugin_managed: false
subscribe_topics:
- onex.cmd.omnimarket.handler-correctness-check.v1
publish_topics:
- onex.evt.omnimarket.handler-correctness-result.v1

terminal_event: onex.evt.omnimarket.handler-correctness-result.v1

externally_consumed_topics:
- onex.evt.omnimarket.handler-correctness-result.v1

published_events:
- event_type: HandlerCorrectnessResult
topic: onex.evt.omnimarket.handler-correctness-result.v1
description: Handler correctness gate result with score and failure details.

metadata:
transport_type: kafka
author: OmniNode Team
license: MIT
created: "2026-05-25"
tags: [compute, eval, correctness, gate, OMN-12130]
related_tickets:
- "OMN-12130"
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "sentiment-classifier-v1"
description: "Basic sentiment classification correctness check"
min_score: 0.85
entries:
- input: "This product is terrible and I want a refund"
expected: "negative"
scoring: "exact_match"
- input: "Best purchase I've ever made"
expected: "positive"
scoring: "exact_match"
- input: "It arrived on time"
expected: "neutral"
scoring: "exact_match"
- input: "Absolutely love it, 5 stars"
expected: "positive"
scoring: "exact_match"
- input: "Worst experience ever, never buying again"
expected: "negative"
scoring: "exact_match"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations

from omnimarket.nodes.node_handler_correctness_gate.models.enums import (
EnumScoringMethod,
)
from omnimarket.nodes.node_handler_correctness_gate.models.model_correctness_check_request import (
ModelCorrectnessCheckRequest,
)
from omnimarket.nodes.node_handler_correctness_gate.models.model_correctness_check_result import (
ModelCorrectnessCheckResult,
)
from omnimarket.nodes.node_handler_correctness_gate.models.model_eval_entry import (
ModelEvalEntry,
)
from omnimarket.nodes.node_handler_correctness_gate.models.model_eval_failure import (
ModelEvalFailure,
)


def _score_entry(entry: ModelEvalEntry, actual: str) -> bool:
expected = entry.expected
if entry.scoring == EnumScoringMethod.EXACT_MATCH:
return actual == expected
if entry.scoring == EnumScoringMethod.CONTAINS:
return expected in actual
if entry.scoring == EnumScoringMethod.STARTS_WITH:
return actual.startswith(expected)
return False


class HandlerCorrectnessGate:
def handle(
self, request: ModelCorrectnessCheckRequest
) -> ModelCorrectnessCheckResult:
entries = request.eval_set.entries
total = len(entries)

if total == 0:
return ModelCorrectnessCheckResult(
handler_id=request.handler_id,
score=0.0,
passed=False,
total_entries=0,
correct_entries=0,
failures=(),
eval_set_name=request.eval_set.name,
)

actual_outputs = request.actual_outputs
failures: list[ModelEvalFailure] = []
correct = 0

for idx, entry in enumerate(entries):
actual = actual_outputs[idx] if idx < len(actual_outputs) else ""
if _score_entry(entry, actual):
correct += 1
else:
failures.append(
ModelEvalFailure(
entry_index=idx,
input=entry.input,
expected=entry.expected,
actual=actual,
scoring=entry.scoring,
)
)

score = correct / total
passed = score >= request.eval_set.min_score

return ModelCorrectnessCheckResult(
handler_id=request.handler_id,
score=score,
passed=passed,
total_entries=total,
correct_entries=correct,
failures=tuple(failures),
eval_set_name=request.eval_set.name,
)
23 changes: 23 additions & 0 deletions src/omnimarket/nodes/node_handler_correctness_gate/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: node_handler_correctness_gate
version: "1.0.0"
description: "Pure compute node that scores pre-computed handler outputs against an eval set"
omnibase_core_compat: ">=0.39.0,<1.0.0"
entry_points:
onex.nodes:
node_handler_correctness_gate: "omnimarket.nodes.node_handler_correctness_gate"
capabilities:
standalone: true
full_runtime: false
requires_network: false
requires_repo: false
requires_secrets: false
requires_docker: false
side_effect_class: pure
dependencies:
- "pydantic>=2.0"
authors: ["OmniNode Team"]
license: "MIT"
tags: ["compute", "eval", "correctness", "gate", "OMN-12130"]
pack: "eval"
display_name: "Handler Correctness Gate"
node_role: "compute"
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
11 changes: 11 additions & 0 deletions src/omnimarket/nodes/node_handler_correctness_gate/models/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations

from enum import StrEnum


class EnumScoringMethod(StrEnum):
EXACT_MATCH = "exact_match"
CONTAINS = "contains"
STARTS_WITH = "starts_with"
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations

from pydantic import BaseModel, ConfigDict

from omnimarket.nodes.node_handler_correctness_gate.models.model_eval_set import (
ModelEvalSet,
)


class ModelCorrectnessCheckRequest(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")

handler_id: str
eval_set: ModelEvalSet
actual_outputs: tuple[str, ...]
correlation_id: str
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations

from pydantic import BaseModel, ConfigDict

from omnimarket.nodes.node_handler_correctness_gate.models.model_eval_failure import (
ModelEvalFailure,
)


class ModelCorrectnessCheckResult(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")

handler_id: str
score: float
passed: bool
total_entries: int
correct_entries: int
failures: tuple[ModelEvalFailure, ...] = ()
eval_set_name: str = ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations

from pydantic import BaseModel, ConfigDict

from omnimarket.nodes.node_handler_correctness_gate.models.enums import (
EnumScoringMethod,
)


class ModelEvalEntry(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")

input: str
expected: str
scoring: EnumScoringMethod = EnumScoringMethod.EXACT_MATCH
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations

from pydantic import BaseModel, ConfigDict

from omnimarket.nodes.node_handler_correctness_gate.models.enums import (
EnumScoringMethod,
)


class ModelEvalFailure(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")

entry_index: int
input: str
expected: str
actual: str
scoring: EnumScoringMethod
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations

from pydantic import BaseModel, ConfigDict

from omnimarket.nodes.node_handler_correctness_gate.models.model_eval_entry import (
ModelEvalEntry,
)


class ModelEvalSet(BaseModel):
model_config = ConfigDict(frozen=True, extra="forbid")

entries: tuple[ModelEvalEntry, ...]
min_score: float = 0.85
name: str = ""
description: str = ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-FileCopyrightText: 2026 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT
Loading
Loading