10abf8985e
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / quality (pull_request) Successful in 19s
CI / build (pull_request) Successful in 29s
CI / security (pull_request) Successful in 33s
CI / typecheck (pull_request) Successful in 35s
CI / unit_tests (pull_request) Successful in 2m15s
CI / docker (pull_request) Successful in 39s
CI / integration_tests (pull_request) Successful in 3m4s
CI / coverage (pull_request) Successful in 5m1s
CI / lint (push) Successful in 12s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 16s
CI / security (push) Successful in 31s
CI / typecheck (push) Successful in 33s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 3m20s
CI / integration_tests (push) Successful in 4m10s
CI / docker (push) Successful in 1m3s
CI / coverage (push) Successful in 4m20s
CI / benchmark-publish (push) Successful in 16m0s
CI / benchmark-regression (pull_request) Successful in 31m40s
Created ScoredFragment frozen model wrapping ContextFragment with composite_score, score_breakdown, and rank fields. Added pipeline- specific fragment models in domain/contexts/ with proper equality based on uko_uri + detail_depth for deduplication support. ISSUES CLOSED: #538
228 lines
7.3 KiB
Python
228 lines
7.3 KiB
Python
"""Robot Framework helper for ScoredFragment and ContextFragment integration tests.
|
|
|
|
Provides a CLI-style interface for Robot to invoke pipeline model
|
|
operations and verify results. Exit code 0 = success, 1 = failure.
|
|
|
|
Usage:
|
|
python robot/helper_context_fragment_models.py scored-create
|
|
python robot/helper_context_fragment_models.py scored-breakdown
|
|
python robot/helper_context_fragment_models.py scored-equality
|
|
python robot/helper_context_fragment_models.py scored-dedup
|
|
python robot/helper_context_fragment_models.py scored-from-relevance
|
|
python robot/helper_context_fragment_models.py scored-frozen
|
|
python robot/helper_context_fragment_models.py strategy-source
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
|
|
from pydantic import ValidationError
|
|
|
|
_SRC = str(Path(__file__).resolve().parents[1] / "src")
|
|
if _SRC not in sys.path:
|
|
sys.path.insert(0, _SRC)
|
|
|
|
from cleveragents.domain.contexts.fragment import ScoredFragment # noqa: E402
|
|
from cleveragents.domain.models.core.context_fragment import ( # noqa: E402
|
|
ContextFragment,
|
|
FragmentProvenance,
|
|
)
|
|
|
|
_DEFAULT_PROV = FragmentProvenance(resource_uri="test://robot")
|
|
|
|
|
|
def _make_fragment(**kwargs: object) -> ContextFragment:
|
|
"""Create a ContextFragment with sensible test defaults."""
|
|
defaults: dict[str, object] = {
|
|
"uko_node": "test://default",
|
|
"content": "test content",
|
|
"token_count": 10,
|
|
"provenance": _DEFAULT_PROV,
|
|
}
|
|
defaults.update(kwargs)
|
|
return ContextFragment(**defaults) # type: ignore[arg-type]
|
|
|
|
|
|
def _cmd_scored_create() -> int:
|
|
"""Create a ScoredFragment and verify defaults."""
|
|
frag = _make_fragment(uko_node="project://app/main.py", content="hello")
|
|
scored = ScoredFragment(fragment=frag, composite_score=0.85)
|
|
if scored.composite_score != 0.85:
|
|
print(f"fail: expected composite_score=0.85, got {scored.composite_score}")
|
|
return 1
|
|
if scored.rank != 0:
|
|
print(f"fail: expected rank=0, got {scored.rank}")
|
|
return 1
|
|
if scored.score_breakdown != {}:
|
|
print(f"fail: expected empty breakdown, got {scored.score_breakdown}")
|
|
return 1
|
|
if scored.uko_node != "project://app/main.py":
|
|
print(f"fail: expected uko_node=project://app/main.py, got {scored.uko_node}")
|
|
return 1
|
|
print("scored-create-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_scored_breakdown() -> int:
|
|
"""Create a ScoredFragment with full breakdown."""
|
|
frag = _make_fragment(uko_node="project://app/io.py", content="async IO")
|
|
breakdown = {"relevance": 0.9, "hierarchy": 0.8, "recency": 0.95}
|
|
scored = ScoredFragment(
|
|
fragment=frag,
|
|
composite_score=0.92,
|
|
score_breakdown=breakdown,
|
|
rank=1,
|
|
)
|
|
if scored.composite_score != 0.92:
|
|
print(f"fail: expected composite_score=0.92, got {scored.composite_score}")
|
|
return 1
|
|
if scored.rank != 1:
|
|
print(f"fail: expected rank=1, got {scored.rank}")
|
|
return 1
|
|
if scored.score_breakdown.get("relevance") != 0.9:
|
|
print(f"fail: expected relevance=0.9, got {scored.score_breakdown}")
|
|
return 1
|
|
print("scored-breakdown-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_scored_equality() -> int:
|
|
"""Verify equality based on uko_node + detail_depth."""
|
|
frag_a = _make_fragment(
|
|
uko_node="project://app/main.py",
|
|
content="A",
|
|
detail_depth=3,
|
|
)
|
|
frag_b = _make_fragment(
|
|
uko_node="project://app/main.py",
|
|
content="B",
|
|
detail_depth=3,
|
|
)
|
|
sa = ScoredFragment.from_fragment(frag_a, composite_score=0.5)
|
|
sb = ScoredFragment.from_fragment(frag_b, composite_score=0.9)
|
|
if sa != sb:
|
|
print("fail: expected equal scored fragments")
|
|
return 1
|
|
if hash(sa) != hash(sb):
|
|
print("fail: expected same hash")
|
|
return 1
|
|
# Different uko_node should be not equal
|
|
frag_c = _make_fragment(
|
|
uko_node="project://app/other.py",
|
|
content="C",
|
|
detail_depth=3,
|
|
)
|
|
sc = ScoredFragment.from_fragment(frag_c, composite_score=0.5)
|
|
if sa == sc:
|
|
print("fail: expected different scored fragments")
|
|
return 1
|
|
print("scored-equality-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_scored_dedup() -> int:
|
|
"""Verify set-based deduplication."""
|
|
frag_a = _make_fragment(
|
|
uko_node="project://app/main.py",
|
|
content="A",
|
|
detail_depth=3,
|
|
)
|
|
frag_b = _make_fragment(
|
|
uko_node="project://app/main.py",
|
|
content="B",
|
|
detail_depth=3,
|
|
)
|
|
frag_c = _make_fragment(
|
|
uko_node="project://app/other.py",
|
|
content="C",
|
|
detail_depth=3,
|
|
)
|
|
scored_set = {
|
|
ScoredFragment.from_fragment(frag_a, composite_score=0.5),
|
|
ScoredFragment.from_fragment(frag_b, composite_score=0.9),
|
|
ScoredFragment.from_fragment(frag_c, composite_score=0.7),
|
|
}
|
|
if len(scored_set) != 2:
|
|
print(f"fail: expected 2 unique, got {len(scored_set)}")
|
|
return 1
|
|
print("scored-dedup-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_scored_from_relevance() -> int:
|
|
"""Create ScoredFragment using from_relevance factory."""
|
|
frag = _make_fragment(
|
|
uko_node="project://app/util.py",
|
|
content="utils",
|
|
relevance_score=0.75,
|
|
)
|
|
scored = ScoredFragment.from_relevance(frag)
|
|
if scored.composite_score != 0.75:
|
|
print(f"fail: expected composite_score=0.75, got {scored.composite_score}")
|
|
return 1
|
|
if scored.score_breakdown.get("relevance") != 0.75:
|
|
print(f"fail: expected relevance=0.75, got {scored.score_breakdown}")
|
|
return 1
|
|
print("scored-from-relevance-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_scored_frozen() -> int:
|
|
"""Verify ScoredFragment is frozen."""
|
|
frag = _make_fragment()
|
|
scored = ScoredFragment(fragment=frag, composite_score=0.5)
|
|
try:
|
|
scored.composite_score = 0.99 # type: ignore[misc]
|
|
print("fail: expected error when modifying frozen model")
|
|
return 1
|
|
except ValidationError:
|
|
pass
|
|
print("scored-frozen-ok")
|
|
return 0
|
|
|
|
|
|
def _cmd_strategy_source() -> int:
|
|
"""Verify strategy_source field on ContextFragment."""
|
|
# Default should be empty string
|
|
frag = _make_fragment()
|
|
if frag.strategy_source != "":
|
|
print(f"fail: expected empty strategy_source, got '{frag.strategy_source}'")
|
|
return 1
|
|
# Explicit value
|
|
frag2 = _make_fragment(strategy_source="keyword-search")
|
|
if frag2.strategy_source != "keyword-search":
|
|
print(
|
|
f"fail: expected strategy_source='keyword-search', "
|
|
f"got '{frag2.strategy_source}'"
|
|
)
|
|
return 1
|
|
print("strategy-source-ok")
|
|
return 0
|
|
|
|
|
|
_COMMANDS: dict[str, Callable[[], int]] = {
|
|
"scored-create": _cmd_scored_create,
|
|
"scored-breakdown": _cmd_scored_breakdown,
|
|
"scored-equality": _cmd_scored_equality,
|
|
"scored-dedup": _cmd_scored_dedup,
|
|
"scored-from-relevance": _cmd_scored_from_relevance,
|
|
"scored-frozen": _cmd_scored_frozen,
|
|
"strategy-source": _cmd_strategy_source,
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
"""Dispatch to the requested sub-command."""
|
|
if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS:
|
|
valid = ", ".join(sorted(_COMMANDS))
|
|
print(f"Usage: {sys.argv[0]} <{valid}>", file=sys.stderr)
|
|
return 1
|
|
return _COMMANDS[sys.argv[1]]()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|