fe69d132f1
ISSUES CLOSED: #178
176 lines
5.3 KiB
Python
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())
|