fix(gateway): rejection envelopes always carry a human-readable message

tracing_gap and incomplete_input rejections set missing and remediate but
left message null. The audit log records message (not remediate) and agents
keyed on message, so a rejected agent saw a null reason and retried the same
verb until it burned out instead of reading remediate and self-correcting.

Both builders (and from_decision) now derive a non-null message that folds
the missing tokens and the actionable remediate into one line, so the agent
and the audit trail always see what was missing and how to fix it.
This commit is contained in:
Renn F
2026-06-04 06:01:06 +02:00
parent 3cfac2e503
commit d47adfe027
2 changed files with 28 additions and 2 deletions
+6
View File
@@ -37,6 +37,12 @@ class TestEnvelopeError:
assert body["error"] == "tracing_gap"
assert body["missing"] == ["progress>=1", "journal:reflect"]
assert "note(scope='reflect'" in body["remediate"]
# message must NOT be null — it carries the missing tokens + remediate so
# the agent and the audit log can see what to do (no more silent flailing).
assert body["message"] is not None
assert "progress>=1" in body["message"]
assert "journal:reflect" in body["message"]
assert "note(scope='reflect'" in body["message"]
def test_invalid_state(self) -> None:
env = Envelope.invalid_state(