commit 4fe170de7b4ef1fe298f2697c9e9d57ca6600704
parent 49410dd3d553a808259a17392a6351a9066ea1c4
Author: triesap <tyson@radroots.org>
Date: Wed, 8 Apr 2026 20:54:00 +0000
control: make hyf feature reporting truthful
Diffstat:
6 files changed, 132 insertions(+), 9 deletions(-)
diff --git a/src/hyf_core/request_context.mojo b/src/hyf_core/request_context.mojo
@@ -78,6 +78,10 @@ struct RequestContext(Copyable, Movable):
def request_context_feature_names() -> List[String]:
+ return request_context_allowed_keys()
+
+
+def request_context_allowed_keys() -> List[String]:
var features = List[String]()
features.append("consumer")
features.append("execution_mode_preference")
@@ -86,6 +90,23 @@ def request_context_feature_names() -> List[String]:
return features^
+def accepted_request_context_feature_names() -> List[String]:
+ var features = List[String]()
+ features.append("consumer")
+ features.append("execution_mode_preference")
+ features.append("scope.listing_ids")
+ features.append("return_provenance")
+ return features^
+
+
+def effective_request_context_feature_names() -> List[String]:
+ var features = List[String]()
+ features.append("execution_mode_preference")
+ features.append("scope.listing_ids")
+ features.append("return_provenance")
+ return features^
+
+
def default_request_context() -> RequestContext:
return RequestContext(
consumer="unknown",
@@ -149,7 +170,7 @@ def parse_request_context(json: Value) raises -> RequestContext:
_require_object(json, "request context")
- var allowed_keys = request_context_feature_names()
+ var allowed_keys = request_context_allowed_keys()
_require_allowed_keys(json, allowed_keys, "request context")
var context = default_request_context()
diff --git a/src/hyf_stdio/control/capabilities.mojo b/src/hyf_stdio/control/capabilities.mojo
@@ -3,7 +3,9 @@ from std.collections import List
from mojson import Value, loads
from hyf_core.capabilities.registry import canonical_business_capabilities
-from hyf_core.request_context import request_context_feature_names
+from hyf_stdio.control.request_context_contract import (
+ build_request_context_contract_value,
+)
def _string_array(values: List[String]) raises -> Value:
@@ -58,7 +60,7 @@ def build_capabilities_output() raises -> Value:
output.set("business_capabilities", capabilities)
output.set("assisted_backend_capabilities", loads("[]"))
output.set(
- "request_context_features",
- _string_array(request_context_feature_names()),
+ "request_context_contract",
+ build_request_context_contract_value(),
)
return output^
diff --git a/src/hyf_stdio/control/request_context_contract.mojo b/src/hyf_stdio/control/request_context_contract.mojo
@@ -0,0 +1,29 @@
+from std.collections import List
+
+from mojson import Value, loads
+
+from hyf_core.request_context import (
+ accepted_request_context_feature_names,
+ effective_request_context_feature_names,
+)
+
+
+def _string_array(values: List[String]) raises -> Value:
+ var array = loads("[]")
+ for value in values:
+ array.append(Value(String(value)))
+ return array^
+
+
+def build_request_context_contract_value() raises -> Value:
+ var contract = loads("{}")
+ contract.set(
+ "accepted_features",
+ _string_array(accepted_request_context_feature_names()),
+ )
+ contract.set(
+ "effective_features",
+ _string_array(effective_request_context_feature_names()),
+ )
+ contract.set("unsupported_field_behavior", Value("reject"))
+ return contract^
diff --git a/src/hyf_stdio/control/status.mojo b/src/hyf_stdio/control/status.mojo
@@ -10,7 +10,9 @@ from hyf_core.capabilities.registry import (
implemented_deterministic_capability_count,
)
from hyf_core.metadata import current_build_identity
-from hyf_core.request_context import request_context_feature_names
+from hyf_stdio.control.request_context_contract import (
+ build_request_context_contract_value,
+)
def _string_array(values: List[String]) raises -> Value:
@@ -107,10 +109,10 @@ def build_status_output() raises -> Value:
var limits = loads("{}")
limits.set("max_requests_per_process", Value(1))
- limits.set(
- "request_context_features",
- _string_array(request_context_feature_names()),
- )
output.set("limits", limits)
+ output.set(
+ "request_context_contract",
+ build_request_context_contract_value(),
+ )
return output^
diff --git a/tests/test_hyf.mojo b/tests/test_hyf.mojo
@@ -31,6 +31,13 @@ def _business_capability(result: Value, capability_id: String) raises -> Value:
raise Error("missing capability '" + capability_id + "' in response")
+def _array_string_values(value: Value) raises -> List[String]:
+ var items = List[String]()
+ for item in value.array_items():
+ items.append(item.string_value())
+ return items^
+
+
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 near me"}}'
@@ -188,6 +195,31 @@ def test_status_reports_registered_deterministic_ready() raises:
),
3,
)
+ assert_true(
+ not _has_key(result["output"]["limits"], "request_context_features")
+ )
+ var status_request_context_contract = result["output"][
+ "request_context_contract"
+ ]
+ var status_accepted = _array_string_values(
+ status_request_context_contract["accepted_features"]
+ )
+ assert_equal(len(status_accepted), 4)
+ assert_equal(status_accepted[0], "consumer")
+ assert_equal(status_accepted[1], "execution_mode_preference")
+ assert_equal(status_accepted[2], "scope.listing_ids")
+ assert_equal(status_accepted[3], "return_provenance")
+ var status_effective = _array_string_values(
+ status_request_context_contract["effective_features"]
+ )
+ assert_equal(len(status_effective), 3)
+ assert_equal(status_effective[0], "execution_mode_preference")
+ assert_equal(status_effective[1], "scope.listing_ids")
+ assert_equal(status_effective[2], "return_provenance")
+ assert_equal(
+ status_request_context_contract["unsupported_field_behavior"].string_value(),
+ "reject",
+ )
def test_capabilities_report_implemented_and_disabled_states() raises:
@@ -217,6 +249,35 @@ def test_capabilities_report_implemented_and_disabled_states() raises:
filter_extraction["disabled_reason"].string_value(),
"deferred_bootstrap_capability",
)
+ assert_true(
+ not _has_key(result["output"], "request_context_features")
+ )
+ var capabilities_request_context_contract = result["output"][
+ "request_context_contract"
+ ]
+ var capabilities_accepted = _array_string_values(
+ capabilities_request_context_contract["accepted_features"]
+ )
+ assert_equal(len(capabilities_accepted), 4)
+ assert_equal(capabilities_accepted[0], "consumer")
+ assert_equal(
+ capabilities_accepted[1], "execution_mode_preference"
+ )
+ assert_equal(capabilities_accepted[2], "scope.listing_ids")
+ assert_equal(capabilities_accepted[3], "return_provenance")
+ var capabilities_effective = _array_string_values(
+ capabilities_request_context_contract["effective_features"]
+ )
+ assert_equal(len(capabilities_effective), 3)
+ assert_equal(
+ capabilities_effective[0], "execution_mode_preference"
+ )
+ assert_equal(capabilities_effective[1], "scope.listing_ids")
+ assert_equal(capabilities_effective[2], "return_provenance")
+ assert_equal(
+ capabilities_request_context_contract["unsupported_field_behavior"].string_value(),
+ "reject",
+ )
def test_disabled_capability_returns_capability_disabled() raises:
diff --git a/tests/test_stdio_contract.mojo b/tests/test_stdio_contract.mojo
@@ -33,6 +33,14 @@ def test_status_success() raises:
response["output"]["execution_mode_request_behavior"]["assisted"].string_value(),
"backend_unavailable",
)
+ assert_equal(
+ response["output"]["request_context_contract"]["accepted_features"][2].string_value(),
+ "scope.listing_ids",
+ )
+ assert_equal(
+ response["output"]["request_context_contract"]["effective_features"][0].string_value(),
+ "execution_mode_preference",
+ )
def test_invalid_envelope_preserves_correlation() raises: