Files
cleveragents-core/robot/helper_definition_of_done.py
T
2026-02-25 10:04:31 +00:00

176 lines
5.3 KiB
Python

"""Robot Framework helper for definition-of-done evaluation.
Provides a CLI-style interface for Robot to invoke DoD parsing,
template rendering, and evaluation. Exit code 0 = success, 1 = failure.
Usage:
python robot/helper_definition_of_done.py parse <dod_text>
python robot/helper_definition_of_done.py render <template> <key> <value>
python robot/helper_definition_of_done.py evaluate <dod_text> <ctx_key> <ctx_value>
python robot/helper_definition_of_done.py summary <plan_id> <dod> <pass> <fail>
python robot/helper_definition_of_done.py validate-summary <plan_id> <dod> <p> <f>
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
# Ensure the src directory is on the import path.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
from cleveragents.domain.models.core.definition_of_done import ( # noqa: E402
DoDCriterion,
DoDResult,
DoDStatus,
DoDSummary,
TextMatchEvaluator,
parse_dod_criteria,
render_dod_template,
)
def _cmd_parse(args: list[str]) -> int:
"""Parse DoD text and print criteria count."""
if len(args) < 1:
print("Usage: parse <dod_text>")
return 1
dod_text = args[0].replace("\\n", "\n")
criteria = parse_dod_criteria(dod_text)
print(f"dod-parse-ok: {len(criteria)} criteria")
for c in criteria:
print(f" [{c.index}] {c.text}")
return 0
def _cmd_render(args: list[str]) -> int:
"""Render a DoD template and print result."""
if len(args) < 3:
print("Usage: render <template> <key> <value>")
return 1
template, key, value = args[0], args[1], args[2]
rendered = render_dod_template(template, {key: value})
print(f"dod-render-ok: {rendered}")
return 0
def _cmd_evaluate(args: list[str]) -> int:
"""Evaluate DoD criteria against a context."""
if len(args) < 3:
print("Usage: evaluate <dod_text> <ctx_key> <ctx_value>")
return 1
dod_text = args[0].replace("\\n", "\n")
ctx_key, ctx_value = args[1], args[2]
criteria = parse_dod_criteria(dod_text)
evaluator = TextMatchEvaluator()
results = evaluator.evaluate(criteria, {ctx_key: ctx_value})
passed = sum(1 for r in results if r.status == DoDStatus.PASSED)
failed = sum(1 for r in results if r.status == DoDStatus.FAILED)
print(f"dod-evaluate-ok: {passed} passed, {failed} failed")
for r in results:
print(f" [{r.criterion.index}] {r.status.value}: {r.criterion.text}")
return 0
def _cmd_summary(args: list[str]) -> int:
"""Build a DoDSummary and print CLI dict."""
if len(args) < 4:
print("Usage: summary <plan_id> <dod_text> <n_passed> <n_failed>")
return 1
plan_id, dod_text = args[0], args[1]
n_passed, n_failed = int(args[2]), int(args[3])
results: list[DoDResult] = []
for i in range(n_passed):
results.append(
DoDResult(
criterion=DoDCriterion(index=i, text=f"crit-{i}"),
status=DoDStatus.PASSED,
reasoning="ok",
)
)
for i in range(n_failed):
results.append(
DoDResult(
criterion=DoDCriterion(index=n_passed + i, text=f"fail-{i}"),
status=DoDStatus.FAILED,
reasoning="not ok",
)
)
summary = DoDSummary(
plan_id=plan_id,
definition_of_done=dod_text,
results=results,
)
cli_dict = summary.to_cli_dict()
print(f"dod-summary-ok: {json.dumps(cli_dict, default=str)}")
return 0
def _cmd_validate_summary(args: list[str]) -> int:
"""Build a DoDSummary and print validation summary."""
if len(args) < 4:
print("Usage: validate-summary <plan_id> <dod_text> <n_passed> <n_failed>")
return 1
plan_id, dod_text = args[0], args[1]
n_passed, n_failed = int(args[2]), int(args[3])
results: list[DoDResult] = []
for i in range(n_passed):
results.append(
DoDResult(
criterion=DoDCriterion(index=i, text=f"crit-{i}"),
status=DoDStatus.PASSED,
reasoning="ok",
)
)
for i in range(n_failed):
results.append(
DoDResult(
criterion=DoDCriterion(index=n_passed + i, text=f"fail-{i}"),
status=DoDStatus.FAILED,
reasoning="not ok",
)
)
summary = DoDSummary(
plan_id=plan_id,
definition_of_done=dod_text,
results=results,
)
vs = summary.to_validation_summary()
print(f"dod-validate-summary-ok: {json.dumps(vs)}")
return 0
def main() -> int:
"""Entry point called by Robot Framework ``Run Process``."""
if len(sys.argv) < 2:
print(
"Usage: helper_definition_of_done.py "
"<parse|render|evaluate|summary|validate-summary> ..."
)
return 1
command = sys.argv[1]
args = sys.argv[2:]
dispatch = {
"parse": _cmd_parse,
"render": _cmd_render,
"evaluate": _cmd_evaluate,
"summary": _cmd_summary,
"validate-summary": _cmd_validate_summary,
}
handler = dispatch.get(command)
if handler is None:
print(f"Unknown command: {command}")
return 1
return handler(args)
if __name__ == "__main__":
sys.exit(main())