Bug
nl2ltl/engines/grounding.py:
def ground_notcoexistence(connectors: Dict[str, float]) -> Set[Template]:
if len(list(connectors)) >= 2:
return {
NotCoExistence(
Atomic(decapitalize(list(connectors)[1])),
Atomic(decapitalize(list(connectors)[1])), # <-- [1] twice
)
}
Both operands are built from list(connectors)[1], so any two-symbol grounding produces a degenerate self-pair. Reproduction:
>>> from nl2ltl.engines.utils import _get_formulas
>>> _get_formulas("notcoexistence", {"reject_request": 1.0, "escalate_to_human": 1.0})
{(NotCoExistence escalate_to_human escalate_to_human)}
Expected: (NotCoExistence reject_request escalate_to_human).
The resulting LTLf, F(x) -> ~F(x), is equivalent to G(!x) — "x never happens" — which silently changes the meaning of the translated requirement (we caught it because a round-trip paraphrase of the formula no longer matched the input sentence).
Fix
Atomic(decapitalize(list(connectors)[0])),
Atomic(decapitalize(list(connectors)[1])),
Observed on nl2ltl from PyPI (Python 3.13). Found while building a Claude-backed custom Engine for translating agent-guardrail policies to DECLARE. Can send a PR if useful.
Bug
nl2ltl/engines/grounding.py:Both operands are built from
list(connectors)[1], so any two-symbol grounding produces a degenerate self-pair. Reproduction:Expected:
(NotCoExistence reject_request escalate_to_human).The resulting LTLf,
F(x) -> ~F(x), is equivalent toG(!x)— "x never happens" — which silently changes the meaning of the translated requirement (we caught it because a round-trip paraphrase of the formula no longer matched the input sentence).Fix
Observed on nl2ltl from PyPI (Python 3.13). Found while building a Claude-backed custom
Enginefor translating agent-guardrail policies to DECLARE. Can send a PR if useful.