commit c45c48a7cfca903ea187cf1b57773ae47d54159e
parent 18359a016c6499e98679d2cf4ca597e4195a2b32
Author: triesap <tyson@radroots.org>
Date: Sun, 12 Apr 2026 00:56:19 +0000
contract: activate negotiated request context fields
Diffstat:
5 files changed, 82 insertions(+), 7 deletions(-)
diff --git a/src/hyf_core/request_context.mojo b/src/hyf_core/request_context.mojo
@@ -1,7 +1,7 @@
from std.collections import List, Optional
from mojson import Value
-from mojson.deserialize import get_bool, get_string
+from mojson.deserialize import get_bool, get_int, get_string
def _has_key(value: Value, key: String) -> Bool:
@@ -34,6 +34,11 @@ def _require_non_empty(value: String, context: String) raises:
raise Error(context + " must not be empty")
+def _require_positive_int(value: Int, context: String) raises:
+ if value <= 0:
+ raise Error(context + " must be greater than zero")
+
+
def _parse_string_list(value: Value, context: String) raises -> List[String]:
if value.is_null():
return List[String]()
@@ -85,8 +90,13 @@ def request_context_allowed_keys() -> List[String]:
var features = List[String]()
features.append("consumer")
features.append("execution_mode_preference")
+ features.append("deadline_ms")
features.append("scope")
+ features.append("time_range")
+ features.append("evidence_limit")
+ features.append("consistency")
features.append("return_provenance")
+ features.append("explain_plan")
return features^
@@ -94,8 +104,14 @@ def accepted_request_context_feature_names() -> List[String]:
var features = List[String]()
features.append("consumer")
features.append("execution_mode_preference")
+ features.append("deadline_ms")
features.append("scope.listing_ids")
+ features.append("time_range.start")
+ features.append("time_range.end")
+ features.append("evidence_limit")
+ features.append("consistency")
features.append("return_provenance")
+ features.append("explain_plan")
return features^
@@ -191,12 +207,38 @@ def parse_request_context(json: Value) raises -> RequestContext:
"request context execution_mode_preference must be 'deterministic' or 'assisted'"
)
+ if _has_key(json, "deadline_ms"):
+ context.deadline_ms = get_int(json, "deadline_ms")
+ _require_positive_int(
+ context.deadline_ms, "request context deadline_ms"
+ )
+
if _has_key(json, "scope"):
var scope_json = json["scope"].clone()
if not scope_json.is_null():
context.scope = _parse_scope(scope_json)
+ if _has_key(json, "time_range"):
+ var time_range_json = json["time_range"].clone()
+ if not time_range_json.is_null():
+ context.time_range = _parse_time_range(time_range_json)
+
+ if _has_key(json, "evidence_limit"):
+ context.evidence_limit = get_int(json, "evidence_limit")
+ _require_positive_int(
+ context.evidence_limit, "request context evidence_limit"
+ )
+
+ if _has_key(json, "consistency"):
+ context.consistency = get_string(json, "consistency")
+ _require_non_empty(
+ context.consistency, "request context consistency"
+ )
+
if _has_key(json, "return_provenance"):
context.return_provenance = get_bool(json, "return_provenance")
+ if _has_key(json, "explain_plan"):
+ context.explain_plan = get_bool(json, "explain_plan")
+
return context^
diff --git a/tests/fixtures/v1/scenarios/capabilities_ok.json b/tests/fixtures/v1/scenarios/capabilities_ok.json
@@ -35,8 +35,14 @@
"output.request_context_contract.accepted_features": [
"consumer",
"execution_mode_preference",
+ "deadline_ms",
"scope.listing_ids",
- "return_provenance"
+ "time_range.start",
+ "time_range.end",
+ "evidence_limit",
+ "consistency",
+ "return_provenance",
+ "explain_plan"
],
"output.request_context_contract.effective_features": [
"execution_mode_preference",
diff --git a/tests/fixtures/v1/scenarios/query_rewrite_local_pickup_weekend.json b/tests/fixtures/v1/scenarios/query_rewrite_local_pickup_weekend.json
@@ -9,7 +9,15 @@
"trace_id": "trace-rewrite-fixture-1",
"capability": "query_rewrite",
"context": {
- "return_provenance": true
+ "deadline_ms": 2500,
+ "time_range": {
+ "start": "2026-04-12",
+ "end": "2026-04-13"
+ },
+ "evidence_limit": 5,
+ "consistency": "default",
+ "return_provenance": true,
+ "explain_plan": true
},
"input": {
"query": "apples near me with weekend pickup"
diff --git a/tests/fixtures/v1/scenarios/status_ok.json b/tests/fixtures/v1/scenarios/status_ok.json
@@ -43,8 +43,14 @@
"output.request_context_contract.accepted_features": [
"consumer",
"execution_mode_preference",
+ "deadline_ms",
"scope.listing_ids",
- "return_provenance"
+ "time_range.start",
+ "time_range.end",
+ "evidence_limit",
+ "consistency",
+ "return_provenance",
+ "explain_plan"
],
"output.request_context_contract.effective_features": [
"execution_mode_preference",
diff --git a/tests/test_hyf.mojo b/tests/test_hyf.mojo
@@ -183,7 +183,7 @@ def _array_string_values(value: Value) raises -> List[String]:
def test_decode_request_parses_context_and_input() raises:
var request = decode_request(
- '{"version":1,"request_id":"req-1","trace_id":"trace-1","capability":"query_rewrite","context":{"consumer":"radroots-cli","execution_mode_preference":"deterministic","return_provenance":true},"input":{"query":"eggs'
+ '{"version":1,"request_id":"req-1","trace_id":"trace-1","capability":"query_rewrite","context":{"consumer":"radroots-cli","execution_mode_preference":"deterministic","deadline_ms":2500,"time_range":{"start":"2026-04-12","end":"2026-04-13"},"evidence_limit":5,"consistency":"default","return_provenance":true,"explain_plan":true},"input":{"query":"eggs'
' near me"}}'
)
@@ -193,7 +193,13 @@ def test_decode_request_parses_context_and_input() raises:
assert_equal(request.capability, "query_rewrite")
assert_equal(request.context.consumer, "radroots-cli")
assert_equal(request.context.execution_mode_preference, "deterministic")
+ assert_equal(request.context.deadline_ms, 2500)
+ assert_equal(request.context.time_range.value().start, "2026-04-12")
+ assert_equal(request.context.time_range.value().end, "2026-04-13")
+ assert_equal(request.context.evidence_limit, 5)
+ assert_equal(request.context.consistency, "default")
assert_equal(request.context.return_provenance, True)
+ assert_equal(request.context.explain_plan, True)
assert_equal(request.input["query"].string_value(), "eggs near me")
@@ -216,10 +222,17 @@ def test_decode_request_requires_input_object() raises:
)
-def test_decode_request_rejects_unsupported_context_field() raises:
+def test_decode_request_rejects_unknown_context_field() raises:
with assert_raises():
_ = decode_request(
- '{"version":1,"request_id":"req-ctx-1","capability":"query_rewrite","context":{"deadline_ms":2500},"input":{"query":"eggs"}}'
+ '{"version":1,"request_id":"req-ctx-1","capability":"query_rewrite","context":{"planner":"strict"},"input":{"query":"eggs"}}'
+ )
+
+
+def test_decode_request_rejects_invalid_activated_context_field() raises:
+ with assert_raises():
+ _ = decode_request(
+ '{"version":1,"request_id":"req-ctx-2","capability":"query_rewrite","context":{"deadline_ms":0},"input":{"query":"eggs"}}'
)