test_hyf.mojo (102490B)
1 import std.os 2 from std.os.path import exists 3 from std.pathlib import Path, _dir_of_current_file 4 from std.testing import ( 5 TestSuite, 6 assert_equal, 7 assert_raises, 8 assert_true, 9 ) 10 from safe_tempdir import SafeTempDir 11 12 from json import Value, dumps, loads, validate 13 14 from fixture_assertions import ( 15 assert_matches_scenario_response, 16 load_scenario_request_json, 17 status_request_with_invalid_version_json, 18 ) 19 20 from fixture_loader import ( 21 fixture_manifest_path, 22 load_fixture_json_file, 23 load_fixture_manifest, 24 load_fixture_scenario, 25 load_fixture_scenario_expected, 26 load_fixture_scenario_request, 27 load_fixture_top_level_field_from_path, 28 ) 29 from fixture_validator import validate_fixture_corpus 30 from projection_assertions import assert_projection 31 from hyf_core.backends.selector import ( 32 execute_capability as execute_core_capability, 33 resolve_backend, 34 ) 35 from hyf_core.capabilities.registry import canonical_business_capabilities 36 from hyf_core.metadata import current_build_identity, current_package_surface 37 from hyf_core.request_context import ( 38 default_request_context, 39 ) 40 from hyf_stdio.control.capabilities import build_capabilities_output 41 from hyf_stdio.codec import decode_request, encode_error, encode_success 42 from hyf_stdio.envelope import WireErrorResponse, WireSuccessResponse 43 from hyf_stdio.errors import WireError 44 from hyf_runtime.startup import ( 45 RuntimeStartupContext, 46 RuntimeStartupInput, 47 resolve_startup_context, 48 ) 49 from hyf_stdio.server import ( 50 handle_request_line_with_runtime_context, 51 ) 52 from stdio_process_helper import run_stdio_entrypoint 53 54 55 comptime _EXPECTED_INTERNAL_ERROR_MESSAGE = ( 56 "internal hyf daemon error; inspect local diagnostics" 57 ) 58 comptime _HYF_DIAGNOSTICS_DIR_ENV = "HYF_DIAGNOSTICS_DIR" 59 60 61 struct ScopedEnvVar: 62 var name: String 63 var value: String 64 var previous: String 65 var had_previous: Bool 66 67 def __init__(out self, name: String, value: String): 68 self.name = String(name) 69 self.value = String(value) 70 self.previous = std.os.getenv(name) 71 self.had_previous = self.previous != "" 72 73 def __enter__(mut self) raises: 74 _ = std.os.setenv(self.name, self.value, overwrite=True) 75 76 def __exit__(mut self): 77 if self.had_previous: 78 _ = std.os.setenv(self.name, self.previous, overwrite=True) 79 else: 80 _ = std.os.unsetenv(self.name) 81 82 83 def _dispatch(line: String) raises -> Value: 84 var result = Value(None) 85 with SafeTempDir() as temp_dir: 86 var runtime_context = resolve_startup_context( 87 RuntimeStartupInput( 88 env_paths_profile="repo_local", 89 env_repo_local_base_root=temp_dir, 90 user_home="/home/unused", 91 argv=List[String](), 92 ) 93 ) 94 result = loads( 95 handle_request_line_with_runtime_context(line, runtime_context) 96 ) 97 return result^ 98 99 100 def _capability_output_entry_by_id( 101 output: Value, capability_id: String 102 ) raises -> Value: 103 for entry in output["business_capabilities"].array_items(): 104 if entry["id"].string_value() == capability_id: 105 return entry.clone() 106 raise Error("missing business capability entry '" + capability_id + "'") 107 108 109 def _sample_request_json_for_callable_capability( 110 capability_id: String, 111 ) raises -> String: 112 if capability_id == "query_rewrite": 113 return load_scenario_request_json( 114 "scenarios/query_rewrite_local_pickup_weekend.json" 115 ) 116 if capability_id == "semantic_rank": 117 return load_scenario_request_json( 118 "scenarios/semantic_rank_local_pickup_weekend.json" 119 ) 120 if capability_id == "explain_result": 121 return load_scenario_request_json( 122 "scenarios/explain_result_local_pickup_weekend.json" 123 ) 124 raise Error( 125 "missing sample request for callable capability '" + capability_id + "'" 126 ) 127 128 129 def _test_manifest_path() raises -> Path: 130 return _dir_of_current_file() / ".." / "pixi.toml" 131 132 133 def _parse_manifest_quoted_value(value: String) raises -> String: 134 var trimmed = value.strip() 135 if ( 136 trimmed.byte_length() < 2 137 or not trimmed.startswith('"') 138 or not trimmed.endswith('"') 139 ): 140 raise Error("manifest assignment value must be quoted") 141 return String(trimmed[byte = 1 : trimmed.byte_length() - 1]) 142 143 144 def _manifest_workspace_value(target_key: String) raises -> String: 145 var in_workspace = False 146 147 for raw_line in _test_manifest_path().read_text().splitlines(): 148 var line = String(raw_line).strip() 149 if line == "" or line.startswith("#"): 150 continue 151 152 if line.startswith("["): 153 in_workspace = line == "[workspace]" 154 continue 155 156 if not in_workspace: 157 continue 158 159 var equals_index = line.find("=") 160 if equals_index < 0: 161 continue 162 163 var key = String(line[byte=0:equals_index]).strip() 164 if key != target_key: 165 continue 166 167 return _parse_manifest_quoted_value( 168 String(line[byte = equals_index + 1 :]) 169 ) 170 171 raise Error("missing workspace manifest key '" + target_key + "'") 172 173 174 def _has_key(value: Value, key: String) -> Bool: 175 for candidate in value.object_keys(): 176 if candidate == key: 177 return True 178 return False 179 180 181 def _array_string_values(value: Value) raises -> List[String]: 182 var items = List[String]() 183 for item in value.array_items(): 184 items.append(item.string_value()) 185 return items^ 186 187 188 def test_decode_request_parses_context_and_input() raises: 189 var request = decode_request( 190 '{"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' 191 ' near me"}}' 192 ) 193 194 assert_equal(request.version, 1) 195 assert_equal(request.request_id, "req-1") 196 assert_equal(request.trace_id.value(), "trace-1") 197 assert_equal(request.capability, "query_rewrite") 198 assert_equal(request.context.consumer, "radroots-cli") 199 assert_equal(request.context.execution_mode_preference, "deterministic") 200 assert_equal(request.context.deadline_ms, 2500) 201 assert_equal(request.context.time_range.value().start, "2026-04-12") 202 assert_equal(request.context.time_range.value().end, "2026-04-13") 203 assert_equal(request.context.evidence_limit, 5) 204 assert_equal(request.context.consistency, "default") 205 assert_equal(request.context.return_provenance, True) 206 assert_equal(request.context.explain_plan, True) 207 assert_equal(request.input["query"].string_value(), "eggs near me") 208 209 210 def test_decode_request_rejects_unexpected_field() raises: 211 with assert_raises(): 212 _ = decode_request( 213 '{"version":1,"request_id":"req-1","capability":"query_rewrite","input":{"query":"eggs"},"unexpected":true}' 214 ) 215 216 217 def test_decode_request_requires_input_object() raises: 218 with assert_raises(): 219 _ = decode_request( 220 '{"version":1,"request_id":"req-no-input-1","capability":"query_rewrite"}' 221 ) 222 223 with assert_raises(): 224 _ = decode_request( 225 '{"version":1,"request_id":"req-bad-input-1","capability":"query_rewrite","input":"eggs"}' 226 ) 227 228 229 def test_decode_request_rejects_unknown_context_field() raises: 230 with assert_raises(): 231 _ = decode_request( 232 '{"version":1,"request_id":"req-ctx-1","capability":"query_rewrite","context":{"planner":"strict"},"input":{"query":"eggs"}}' 233 ) 234 235 236 def test_decode_request_rejects_invalid_activated_context_field() raises: 237 with assert_raises(): 238 _ = decode_request( 239 '{"version":1,"request_id":"req-ctx-2","capability":"query_rewrite","context":{"deadline_ms":0},"input":{"query":"eggs"}}' 240 ) 241 242 243 def test_decode_request_rejects_unsupported_scope_field() raises: 244 with assert_raises(): 245 _ = decode_request( 246 '{"version":1,"request_id":"req-scope-1","capability":"semantic_rank","context":{"scope":{"farm_ids":["farm-1"]}},"input":{"query":"eggs","candidates":[{"id":"lst_1","title":"Eggs","farm":"One' 247 ' Farm","delivery":"pickup","distance_km":1.0,"freshness_minutes":5}]}}' 248 ) 249 250 251 def test_encode_success_and_error_shapes() raises: 252 var output = loads("{}") 253 output.set("kind", Value("ok")) 254 255 var meta = loads("{}") 256 meta.set("execution_mode", Value("deterministic")) 257 258 var success = loads( 259 encode_success( 260 WireSuccessResponse( 261 version=1, 262 request_id="req-success", 263 trace_id=String("trace-success"), 264 output=output.copy(), 265 meta=meta.copy(), 266 ) 267 ) 268 ) 269 assert_equal(Int(success["version"].int_value()), 1) 270 assert_equal(success["request_id"].string_value(), "req-success") 271 assert_equal(success["trace_id"].string_value(), "trace-success") 272 assert_equal(success["ok"].bool_value(), True) 273 assert_equal(success["output"]["kind"].string_value(), "ok") 274 assert_equal( 275 success["meta"]["execution_mode"].string_value(), 276 "deterministic", 277 ) 278 assert_true(not _has_key(success["meta"], "latency_ms")) 279 280 var failure = loads( 281 encode_error( 282 WireErrorResponse( 283 version=1, 284 request_id="req-error", 285 trace_id=String("trace-error"), 286 error=WireError(code="invalid_request", message="bad request"), 287 ) 288 ) 289 ) 290 assert_equal(Int(failure["version"].int_value()), 1) 291 assert_equal(failure["request_id"].string_value(), "req-error") 292 assert_equal(failure["trace_id"].string_value(), "trace-error") 293 assert_equal(failure["ok"].bool_value(), False) 294 assert_equal(failure["error"]["code"].string_value(), "invalid_request") 295 assert_equal(failure["error"]["message"].string_value(), "bad request") 296 297 298 def test_handle_request_line_returns_invalid_request_for_bad_line() raises: 299 var result = _dispatch("") 300 assert_equal(Int(result["version"].int_value()), 1) 301 assert_equal(result["request_id"].string_value(), "") 302 assert_equal(_has_key(result, "trace_id"), False) 303 assert_equal(result["ok"].bool_value(), False) 304 assert_equal(result["error"]["code"].string_value(), "invalid_request") 305 306 307 def test_current_build_identity_matches_manifest_package_surface() raises: 308 var package_surface = current_package_surface() 309 var build_identity = current_build_identity() 310 var manifest_package_name = _manifest_workspace_value("name") 311 var manifest_package_version = _manifest_workspace_value("version") 312 313 assert_equal(package_surface.package_name, manifest_package_name) 314 assert_equal(package_surface.package_version, manifest_package_version) 315 assert_equal(build_identity.package_name, manifest_package_name) 316 assert_equal(build_identity.package_version, manifest_package_version) 317 318 319 def test_repo_local_fixture_manifest_declares_expected_scenarios() raises: 320 assert_true(exists(fixture_manifest_path())) 321 322 var manifest = load_fixture_manifest() 323 assert_equal( 324 manifest["fixture_namespace"].string_value(), 325 "radroots-canonical-hyf-v1", 326 ) 327 assert_equal(Int(manifest["schema_version"].int_value()), 1) 328 assert_equal(manifest["family_kind"].string_value(), "wire_compatibility") 329 assert_equal(manifest["transport"].string_value(), "stdio") 330 assert_equal( 331 manifest["request_framing"].string_value(), 332 "newline_delimited_json", 333 ) 334 assert_equal( 335 manifest["family_role"].string_value(), 336 "dependency_surface", 337 ) 338 assert_equal( 339 manifest["canonical_authority_path"].string_value(), 340 "testing/fixtures/canonical/hyf/v1", 341 ) 342 assert_equal( 343 manifest["shared_scenario_sync_policy"].string_value(), 344 "same_logical_workstream", 345 ) 346 347 var scenario_files = _array_string_values(manifest["scenario_files"]) 348 assert_equal(len(scenario_files), 8) 349 assert_equal(scenario_files[0], "scenarios/status_ok.json") 350 assert_equal( 351 scenario_files[7], "scenarios/query_rewrite_unexpected_field.json" 352 ) 353 354 355 def test_repo_local_fixture_loader_reads_all_mirrored_scenarios() raises: 356 var manifest = load_fixture_manifest() 357 assert_equal( 358 manifest["fixture_namespace"].string_value(), 359 "radroots-canonical-hyf-v1", 360 ) 361 362 var status_scenario = load_fixture_scenario("scenarios/status_ok.json") 363 assert_equal(status_scenario["fixture_id"].string_value(), "status_ok") 364 assert_equal( 365 status_scenario["request"]["capability"].string_value(), 366 "sys.status", 367 ) 368 assert_true(_has_key(status_scenario, "expected")) 369 370 var rewrite_scenario = load_fixture_scenario( 371 "scenarios/query_rewrite_local_pickup_weekend.json" 372 ) 373 assert_equal( 374 rewrite_scenario["fixture_id"].string_value(), 375 "query_rewrite_local_pickup_weekend", 376 ) 377 assert_equal( 378 rewrite_scenario["request"]["capability"].string_value(), 379 "query_rewrite", 380 ) 381 assert_equal( 382 rewrite_scenario["request"]["input"]["query"].string_value(), 383 "apples near me with weekend pickup", 384 ) 385 386 387 def test_fixture_loader_reads_top_level_request_and_expected_structurally() raises: 388 with SafeTempDir() as temp_dir: 389 var scenario_path = Path(temp_dir) / "scenario.json" 390 scenario_path.write_text( 391 "{" 392 + '"fixture_id":"shadowed-top-level-fields",' 393 + '"description":"this description mentions request and expected' 394 ' before the real fields",' 395 + '"request":{"version":1,"request_id":"shadow-1","capability":"sys.status","input":{}},' 396 + '"expected":{"ok":true,"equals":{"output.kind":"status"}}' 397 + "}" 398 ) 399 400 var scenario = load_fixture_json_file(scenario_path) 401 var request = load_fixture_scenario_request("scenarios/status_ok.json") 402 var expected = load_fixture_scenario_expected( 403 "scenarios/status_ok.json" 404 ) 405 var temp_request = load_fixture_top_level_field_from_path( 406 scenario_path, "request" 407 ) 408 var temp_expected = load_fixture_top_level_field_from_path( 409 scenario_path, "expected" 410 ) 411 412 assert_equal( 413 scenario["fixture_id"].string_value(), 414 "shadowed-top-level-fields", 415 ) 416 assert_equal( 417 temp_request["request_id"].string_value(), 418 "shadow-1", 419 ) 420 assert_equal( 421 temp_request["capability"].string_value(), 422 "sys.status", 423 ) 424 assert_true(temp_expected["ok"].bool_value()) 425 assert_equal( 426 temp_expected["equals"]["output.kind"].string_value(), 427 "status", 428 ) 429 assert_equal(request["capability"].string_value(), "sys.status") 430 assert_true(expected["ok"].bool_value()) 431 432 433 def test_status_reports_registered_deterministic_ready() raises: 434 var result = _dispatch( 435 load_scenario_request_json("scenarios/status_ok.json") 436 ) 437 assert_matches_scenario_response(result, "scenarios/status_ok.json") 438 439 440 def test_capabilities_report_implemented_and_disabled_states() raises: 441 var result = _dispatch( 442 load_scenario_request_json("scenarios/capabilities_ok.json") 443 ) 444 assert_matches_scenario_response(result, "scenarios/capabilities_ok.json") 445 446 447 def test_capabilities_output_reflects_registry_truth_for_all_business_capabilities() raises: 448 var output = build_capabilities_output() 449 for capability in canonical_business_capabilities(): 450 var entry = _capability_output_entry_by_id(output, capability.id) 451 assert_equal(entry["id"].string_value(), capability.id) 452 assert_equal(entry["implemented"].bool_value(), capability.implemented) 453 assert_equal(entry["callable"].bool_value(), capability.callable) 454 assert_equal(entry["assisted_backend_available"].bool_value(), False) 455 assert_equal( 456 entry["deterministic_execution"].string_value(), 457 "enabled" if capability.deterministic_enabled else "disabled", 458 ) 459 assert_equal( 460 entry["implementation_status"].string_value(), 461 "implemented" if capability.implemented else ( 462 "not_implemented" if capability.deterministic_enabled else "disabled" 463 ), 464 ) 465 if capability.disabled_reason != "": 466 assert_equal( 467 entry["disabled_reason"].string_value(), 468 capability.disabled_reason, 469 ) 470 else: 471 assert_true(not _has_key(entry, "disabled_reason")) 472 473 assert_equal( 474 output["provider_runtime_capabilities"][0]["id"].string_value(), 475 "hyf_provider_runtime", 476 ) 477 assert_equal( 478 output["provider_runtime_capabilities"][0]["kind"].string_value(), 479 "provider_runtime", 480 ) 481 assert_equal( 482 output["provider_runtime_capabilities"][0]["transport"].string_value(), 483 "deferred", 484 ) 485 assert_equal( 486 output["provider_runtime_capabilities"][0]["state"].string_value(), 487 "disabled_by_runtime_config", 488 ) 489 assert_equal( 490 output["provider_runtime_capabilities"][0][ 491 "backend_kind" 492 ].string_value(), 493 "deferred", 494 ) 495 496 497 def test_disabled_capability_returns_capability_disabled() raises: 498 var result = _dispatch( 499 load_scenario_request_json( 500 "scenarios/deferred_capability_disabled.json" 501 ) 502 ) 503 assert_matches_scenario_response( 504 result, "scenarios/deferred_capability_disabled.json" 505 ) 506 507 508 def test_all_callable_registry_business_capabilities_are_dispatchable() raises: 509 for capability in canonical_business_capabilities(): 510 if not capability.callable: 511 continue 512 var result = _dispatch( 513 _sample_request_json_for_callable_capability(capability.id) 514 ) 515 assert_equal(Int(result["version"].int_value()), 1) 516 assert_equal(result["ok"].bool_value(), True) 517 518 519 def test_non_callable_registry_business_capabilities_do_not_route_as_success() raises: 520 for capability in canonical_business_capabilities(): 521 if capability.callable: 522 continue 523 var result = _dispatch( 524 '{"version":1,"request_id":"' 525 + capability.id 526 + '-routing-1","capability":"' 527 + capability.id 528 + '","input":{}}' 529 ) 530 assert_equal(Int(result["version"].int_value()), 1) 531 assert_equal( 532 result["request_id"].string_value(), capability.id + "-routing-1" 533 ) 534 assert_equal(result["ok"].bool_value(), False) 535 assert_equal( 536 result["error"]["code"].string_value(), 537 "capability_disabled" if not capability.deterministic_enabled else "capability_unavailable", 538 ) 539 540 541 def test_backend_selector_routes_deterministic_wave() raises: 542 var context = default_request_context() 543 var selection = resolve_backend(context) 544 545 assert_equal(selection.backend_name, "heuristic") 546 assert_equal(selection.available, True) 547 548 var result = execute_core_capability( 549 "query_rewrite", 550 loads('{"text":"eggs near me with weekend pickup"}'), 551 context, 552 ) 553 554 assert_true(result.success) 555 assert_equal( 556 result.success.value().meta.value().backend, 557 "heuristic", 558 ) 559 assert_equal( 560 result.success.value().meta.value().execution_mode, 561 "deterministic", 562 ) 563 564 565 def test_backend_selector_routes_assisted_preference_to_deterministic_fallback() raises: 566 var context = default_request_context() 567 context.execution_mode_preference = "assisted" 568 569 var selection = resolve_backend(context) 570 assert_equal(selection.backend_name, "heuristic") 571 assert_equal(selection.available, True) 572 573 var result = execute_core_capability( 574 "query_rewrite", 575 loads('{"text":"eggs near me"}'), 576 context, 577 ) 578 579 assert_true(result.success) 580 assert_equal( 581 result.success.value().meta.value().execution_mode, 582 "deterministic", 583 ) 584 assert_equal(result.success.value().meta.value().backend, "heuristic") 585 586 587 def test_query_rewrite_returns_deterministic_output() raises: 588 var result = _dispatch( 589 load_scenario_request_json( 590 "scenarios/query_rewrite_local_pickup_weekend.json" 591 ) 592 ) 593 assert_matches_scenario_response( 594 result, "scenarios/query_rewrite_local_pickup_weekend.json" 595 ) 596 597 598 def test_query_rewrite_accepts_query_alias_with_same_behavior() raises: 599 var result = _dispatch( 600 '{"version":1,"request_id":"rewrite-query-1","capability":"query_rewrite","input":{"query":"eggs' 601 ' near me with weekend pickup"}}' 602 ) 603 604 assert_equal(Int(result["version"].int_value()), 1) 605 assert_equal(result["ok"].bool_value(), True) 606 assert_equal( 607 result["output"]["rewritten_text"].string_value(), 608 "eggs", 609 ) 610 assert_equal( 611 result["output"]["extracted_filters"]["fulfillment"].string_value(), 612 "pickup", 613 ) 614 615 616 def test_query_rewrite_rejects_unknown_input_field() raises: 617 var result = _dispatch( 618 load_scenario_request_json( 619 "scenarios/query_rewrite_unexpected_field.json" 620 ) 621 ) 622 assert_matches_scenario_response( 623 result, "scenarios/query_rewrite_unexpected_field.json" 624 ) 625 626 627 def test_query_rewrite_rejects_text_and_query_together() raises: 628 var result = _dispatch( 629 '{"version":1,"request_id":"rewrite-bad-dual-1","capability":"query_rewrite","input":{"text":"eggs' 630 ' near me","query":"eggs"}}' 631 ) 632 633 assert_equal(Int(result["version"].int_value()), 1) 634 assert_equal(result["ok"].bool_value(), False) 635 assert_equal(result["request_id"].string_value(), "rewrite-bad-dual-1") 636 assert_equal(result["error"]["code"].string_value(), "invalid_request") 637 assert_true( 638 result["error"]["message"].string_value().find("exactly one") >= 0 639 ) 640 641 642 def test_semantic_rank_returns_ranked_ids_and_reasons() raises: 643 var result = _dispatch( 644 load_scenario_request_json( 645 "scenarios/semantic_rank_local_pickup_weekend.json" 646 ) 647 ) 648 assert_matches_scenario_response( 649 result, "scenarios/semantic_rank_local_pickup_weekend.json" 650 ) 651 652 653 def test_semantic_rank_scope_listing_ids_remains_effective() raises: 654 var result = _dispatch( 655 '{"version":1,"request_id":"rank-scope-1","capability":"semantic_rank","context":{"scope":{"listing_ids":["lst_8k1p"]}},"input":{"query":"eggs","candidates":[{"id":"lst_7ak2","title":"Pasture' 656 ' eggs","farm":"La Huerta del' 657 ' Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2},{"id":"lst_8k1p","title":"Free' 658 ' range eggs","farm":"Santa' 659 ' Elena","delivery":"delivery","distance_km":8.7,"freshness_minutes":18}]}}' 660 ) 661 662 assert_equal(Int(result["version"].int_value()), 1) 663 assert_equal(result["ok"].bool_value(), True) 664 assert_equal( 665 result["output"]["ranked_ids"][0].string_value(), 666 "lst_8k1p", 667 ) 668 assert_equal( 669 result["output"]["scored_candidates"][0]["scope_match"].bool_value(), 670 True, 671 ) 672 assert_true( 673 _has_key(result["output"]["scored_candidates"][0], "heuristic_score") 674 ) 675 676 677 def test_semantic_rank_rejects_unknown_top_level_field() raises: 678 var result = _dispatch( 679 '{"version":1,"request_id":"rank-bad-top-1","capability":"semantic_rank","input":{"query":"eggs' 680 ' near me","candidates":[{"id":"lst_7ak2","title":"Pasture' 681 ' eggs","farm":"La Huerta del' 682 ' Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2}],"tone":"brief"}}' 683 ) 684 685 assert_equal(Int(result["version"].int_value()), 1) 686 assert_equal(result["ok"].bool_value(), False) 687 assert_equal(result["request_id"].string_value(), "rank-bad-top-1") 688 assert_equal(result["error"]["code"].string_value(), "invalid_request") 689 assert_true( 690 result["error"]["message"].string_value().find("unexpected field") >= 0 691 ) 692 693 694 def test_semantic_rank_rejects_unknown_candidate_field() raises: 695 var result = _dispatch( 696 '{"version":1,"request_id":"rank-bad-candidate-1","capability":"semantic_rank","input":{"query":"eggs' 697 ' near me","candidates":[{"id":"lst_7ak2","title":"Pasture' 698 ' eggs","farm":"La Huerta del' 699 ' Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2,"rating":5}]}}' 700 ) 701 702 assert_equal(Int(result["version"].int_value()), 1) 703 assert_equal(result["ok"].bool_value(), False) 704 assert_equal(result["request_id"].string_value(), "rank-bad-candidate-1") 705 assert_equal(result["error"]["code"].string_value(), "invalid_request") 706 assert_true( 707 result["error"]["message"].string_value().find("unexpected field") >= 0 708 ) 709 710 711 def test_semantic_rank_rejects_duplicate_candidate_ids() raises: 712 var result = _dispatch( 713 '{"version":1,"request_id":"rank-dup-1","capability":"semantic_rank","input":{"query":"eggs' 714 ' near me","candidates":[{"id":"lst_dup","title":"Pasture' 715 ' eggs","farm":"La Huerta del' 716 ' Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2},{"id":"lst_dup","title":"Free' 717 ' range eggs","farm":"Santa' 718 ' Elena","delivery":"delivery","distance_km":8.7,"freshness_minutes":18}]}}' 719 ) 720 721 assert_equal(Int(result["version"].int_value()), 1) 722 assert_equal(result["ok"].bool_value(), False) 723 assert_equal(result["request_id"].string_value(), "rank-dup-1") 724 assert_equal(result["error"]["code"].string_value(), "invalid_request") 725 assert_true( 726 result["error"]["message"].string_value().find("duplicate candidate id") 727 >= 0 728 ) 729 730 731 def test_semantic_rank_rejects_invalid_delivery_value() raises: 732 var result = _dispatch( 733 '{"version":1,"request_id":"rank-bad-delivery-1","capability":"semantic_rank","input":{"query":"eggs' 734 ' near me","candidates":[{"id":"lst_7ak2","title":"Pasture' 735 ' eggs","farm":"La Huerta del' 736 ' Sur","delivery":"ship","distance_km":3.2,"freshness_minutes":2}]}}' 737 ) 738 739 assert_equal(Int(result["version"].int_value()), 1) 740 assert_equal(result["ok"].bool_value(), False) 741 assert_equal(result["request_id"].string_value(), "rank-bad-delivery-1") 742 assert_equal(result["error"]["code"].string_value(), "invalid_request") 743 assert_true( 744 result["error"]["message"].string_value().find("must be one of") >= 0 745 ) 746 747 748 def test_explain_result_returns_deterministic_summary_and_provenance() raises: 749 var result = _dispatch( 750 load_scenario_request_json( 751 "scenarios/explain_result_local_pickup_weekend.json" 752 ) 753 ) 754 assert_matches_scenario_response( 755 result, "scenarios/explain_result_local_pickup_weekend.json" 756 ) 757 758 759 def test_explain_result_accepts_result_alias() raises: 760 var result = _dispatch( 761 '{"version":1,"request_id":"explain-result-1","capability":"explain_result","input":{"query":"eggs' 762 " near me with weekend" 763 ' pickup","result":{"id":"lst_7ak2","title":"Pasture eggs","farm":"La' 764 " Huerta del" 765 ' Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2}}}' 766 ) 767 768 assert_equal(Int(result["version"].int_value()), 1) 769 assert_equal(result["ok"].bool_value(), True) 770 assert_equal( 771 result["output"]["result_id"].string_value(), 772 "lst_7ak2", 773 ) 774 assert_equal( 775 result["output"]["explanation_kind"].string_value(), 776 "deterministic", 777 ) 778 779 780 def test_explain_result_rejects_unknown_top_level_field() raises: 781 var result = _dispatch( 782 '{"version":1,"request_id":"explain-bad-top-1","capability":"explain_result","input":{"query":"eggs' 783 ' near me","candidate":{"id":"lst_7ak2","title":"Pasture' 784 ' eggs","farm":"La Huerta del' 785 ' Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2},"tone":"brief"}}' 786 ) 787 788 assert_equal(Int(result["version"].int_value()), 1) 789 assert_equal(result["ok"].bool_value(), False) 790 assert_equal(result["request_id"].string_value(), "explain-bad-top-1") 791 assert_equal(result["error"]["code"].string_value(), "invalid_request") 792 assert_true( 793 result["error"]["message"].string_value().find("unexpected field") >= 0 794 ) 795 796 797 def test_explain_result_rejects_unknown_candidate_field() raises: 798 var result = _dispatch( 799 '{"version":1,"request_id":"explain-bad-candidate-1","capability":"explain_result","input":{"query":"eggs' 800 ' near me","candidate":{"id":"lst_7ak2","title":"Pasture' 801 ' eggs","farm":"La Huerta del' 802 ' Sur","delivery":"pickup","distance_km":3.2,"freshness_minutes":2,"rating":5}}}' 803 ) 804 805 assert_equal(Int(result["version"].int_value()), 1) 806 assert_equal(result["ok"].bool_value(), False) 807 assert_equal(result["request_id"].string_value(), "explain-bad-candidate-1") 808 assert_equal(result["error"]["code"].string_value(), "invalid_request") 809 assert_true( 810 result["error"]["message"].string_value().find("unexpected field") >= 0 811 ) 812 813 814 def test_explain_result_rejects_invalid_delivery_value() raises: 815 var result = _dispatch( 816 '{"version":1,"request_id":"explain-bad-delivery-1","capability":"explain_result","input":{"query":"eggs' 817 ' near me","candidate":{"id":"lst_7ak2","title":"Pasture' 818 ' eggs","farm":"La Huerta del' 819 ' Sur","delivery":"ship","distance_km":3.2,"freshness_minutes":2}}}' 820 ) 821 822 assert_equal(Int(result["version"].int_value()), 1) 823 assert_equal(result["ok"].bool_value(), False) 824 assert_equal(result["request_id"].string_value(), "explain-bad-delivery-1") 825 assert_equal(result["error"]["code"].string_value(), "invalid_request") 826 assert_true( 827 result["error"]["message"].string_value().find("must be one of") >= 0 828 ) 829 830 831 def test_semantic_rank_invalid_input_returns_invalid_request() raises: 832 var result = _dispatch( 833 '{"version":1,"request_id":"rank-bad-1","trace_id":"trace-rank-bad-1","capability":"semantic_rank","input":{"query":"eggs' 834 ' near me with weekend pickup","candidates":[]}}' 835 ) 836 837 assert_equal(Int(result["version"].int_value()), 1) 838 assert_equal(result["ok"].bool_value(), False) 839 assert_equal(result["request_id"].string_value(), "rank-bad-1") 840 assert_equal(result["trace_id"].string_value(), "trace-rank-bad-1") 841 assert_equal(result["error"]["code"].string_value(), "invalid_request") 842 assert_true( 843 result["error"]["message"].string_value().find("must not be empty") >= 0 844 ) 845 846 847 def test_missing_input_returns_invalid_request() raises: 848 var result = _dispatch( 849 '{"version":1,"request_id":"missing-input-1","trace_id":"trace-missing-input-1","capability":"query_rewrite"}' 850 ) 851 852 assert_equal(Int(result["version"].int_value()), 1) 853 assert_equal(result["ok"].bool_value(), False) 854 assert_equal(result["request_id"].string_value(), "missing-input-1") 855 assert_equal(result["trace_id"].string_value(), "trace-missing-input-1") 856 assert_equal(result["error"]["code"].string_value(), "invalid_request") 857 assert_true( 858 result["error"]["message"] 859 .string_value() 860 .find("field 'input' is required") 861 >= 0 862 ) 863 864 865 def test_assisted_request_falls_back_deterministically_when_provider_is_unavailable() raises: 866 var result = _dispatch( 867 load_scenario_request_json( 868 "scenarios/assisted_backend_unavailable.json" 869 ) 870 ) 871 assert_matches_scenario_response( 872 result, "scenarios/assisted_backend_unavailable.json" 873 ) 874 875 876 def test_invalid_request_preserves_request_and_trace_correlation() raises: 877 var result = _dispatch(status_request_with_invalid_version_json()) 878 879 assert_equal(Int(result["version"].int_value()), 1) 880 assert_equal(result["request_id"].string_value(), "status-fixture-1") 881 assert_equal(result["trace_id"].string_value(), "trace-status-fixture-1") 882 assert_equal(result["ok"].bool_value(), False) 883 assert_equal(result["error"]["code"].string_value(), "invalid_request") 884 assert_true( 885 result["error"]["message"].string_value().find("unsupported") >= 0 886 ) 887 888 889 def test_internal_error_is_bounded_on_wire() raises: 890 with SafeTempDir() as temp_dir: 891 var diagnostics_dir = Path(temp_dir) / "hyf-internal-diagnostics" 892 with ScopedEnvVar( 893 _HYF_DIAGNOSTICS_DIR_ENV, diagnostics_dir.__fspath__() 894 ): 895 var result = run_stdio_entrypoint( 896 "tests/internal_error_stdio_main.mojo", 897 '{"version":1,"request_id":"status-internal-1","trace_id":"trace-status-internal-1","capability":"sys.status","input":{}}', 898 ) 899 900 _assert_internal_error_is_bounded(result) 901 902 903 def _assert_internal_error_is_bounded(result: Value) raises: 904 assert_equal(Int(result["version"].int_value()), 1) 905 assert_equal(result["request_id"].string_value(), "status-internal-1") 906 assert_equal(result["trace_id"].string_value(), "trace-status-internal-1") 907 assert_equal(result["ok"].bool_value(), False) 908 assert_equal(result["error"]["code"].string_value(), "internal_error") 909 assert_equal( 910 result["error"]["message"].string_value(), 911 _EXPECTED_INTERNAL_ERROR_MESSAGE, 912 ) 913 assert_true( 914 result["error"]["message"].string_value().find("simulated test-only") 915 < 0 916 ) 917 918 919 def test_internal_error_diagnostics_records_detail() raises: 920 with SafeTempDir() as temp_dir: 921 var diagnostics_dir = Path(temp_dir) / "hyf-internal-diagnostics" 922 923 with ScopedEnvVar( 924 _HYF_DIAGNOSTICS_DIR_ENV, diagnostics_dir.__fspath__() 925 ): 926 _ = run_stdio_entrypoint( 927 "tests/internal_error_stdio_main.mojo", 928 '{"version":1,"request_id":"status-internal-diag-1","trace_id":"trace-status-internal-diag-1","capability":"sys.status","input":{}}', 929 ) 930 931 assert_true(exists(diagnostics_dir)) 932 var entries = std.os.listdir(diagnostics_dir) 933 assert_equal(len(entries), 1) 934 assert_true(entries[0].startswith("hyf-internal-error-pid-")) 935 936 var content = (diagnostics_dir / entries[0]).read_text() 937 var lines = content.splitlines() 938 assert_equal(len(lines), 1) 939 assert_true( 940 content.find('request_id="status-internal-diag-1"') >= 0 941 ) 942 assert_true( 943 content.find( 944 'detail="simulated test-only status builder failure"' 945 ) 946 >= 0 947 ) 948 949 950 def test_semantic_fixture_manifest_declares_repo_local_family() raises: 951 var manifest_path = ( 952 _dir_of_current_file() / "fixtures" / "hyf_v1_jev" / "manifest.json" 953 ) 954 assert_true(exists(manifest_path)) 955 var manifest = loads(manifest_path.read_text()) 956 assert_equal( 957 manifest["fixture_namespace"].string_value(), 958 "radroots-hyf-v1-jev-semantic", 959 ) 960 assert_equal(Int(manifest["schema_version"].int_value()), 1) 961 assert_equal(manifest["family_kind"].string_value(), "semantic_acceptance") 962 assert_equal(manifest["family_role"].string_value(), "hyf_local") 963 assert_equal(manifest["transport"].string_value(), "stdio") 964 assert_equal( 965 manifest["request_framing"].string_value(), "newline_delimited_json" 966 ) 967 assert_equal( 968 manifest["shared_wire_authority"]["declared_path"].string_value(), 969 "testing/fixtures/canonical/hyf/v1", 970 ) 971 assert_equal( 972 manifest["shared_wire_authority"][ 973 "local_offline_mirror" 974 ].string_value(), 975 "tests/fixtures/v1", 976 ) 977 assert_equal( 978 manifest["repo_local_families"]["domain"].string_value(), 979 "tests/fixtures/hyf_v1_jev/domain", 980 ) 981 assert_equal(manifest["installation_status"].string_value(), "installed") 982 assert_equal(Int(manifest["declared_case_count"].int_value()), 116) 983 assert_equal(Int(manifest["declared_raw_payload_count"].int_value()), 5) 984 985 986 def _wire_schema_path(name: String) raises -> Path: 987 return _dir_of_current_file() / ".." / "schemas" / "hyf_v1_jev" / name 988 989 990 def _wire_schema_json(name: String) raises -> Value: 991 return loads(_wire_schema_path(name).read_text()) 992 993 994 def test_wire_operation_schemas_accept_valid_and_reject_invalid() raises: 995 var manifest = _wire_schema_json("manifest.json") 996 assert_equal(manifest["schema_version"].int_value(), 1) 997 assert_equal(manifest["spec_id"].string_value(), "hyf_v1_jev") 998 999 var validated = 0 1000 for binding in manifest["bindings"].array_items(): 1001 if _has_key(binding, "request_schema"): 1002 var request_schema_name = binding["request_schema"].string_value() 1003 var request_valid = binding["request_valid"].string_value() 1004 var request_schema = _wire_schema_json(request_schema_name) 1005 var request_doc = loads( 1006 ( 1007 _dir_of_current_file() 1008 / ".." 1009 / "schemas" 1010 / "hyf_v1_jev" 1011 / request_valid 1012 ).read_text() 1013 ) 1014 assert_true( 1015 validate(request_doc, request_schema).valid, 1016 "request example failed schema: " + request_valid, 1017 ) 1018 validated += 1 1019 1020 if _has_key(binding, "request_invalid"): 1021 var invalid_doc = loads( 1022 ( 1023 _dir_of_current_file() 1024 / ".." 1025 / "schemas" 1026 / "hyf_v1_jev" 1027 / binding["request_invalid"].string_value() 1028 ).read_text() 1029 ) 1030 assert_true( 1031 not validate(invalid_doc, request_schema).valid, 1032 "invalid request example unexpectedly passed schema", 1033 ) 1034 1035 if _has_key(binding, "response_schema"): 1036 var response_schema = _wire_schema_json( 1037 binding["response_schema"].string_value() 1038 ) 1039 var response_doc = loads( 1040 ( 1041 _dir_of_current_file() 1042 / ".." 1043 / "schemas" 1044 / "hyf_v1_jev" 1045 / binding["response_valid"].string_value() 1046 ).read_text() 1047 ) 1048 assert_true( 1049 validate(response_doc, response_schema).valid, 1050 "response example failed schema", 1051 ) 1052 validated += 1 1053 1054 if _has_key(binding, "response_invalid"): 1055 var invalid_response = loads( 1056 ( 1057 _dir_of_current_file() 1058 / ".." 1059 / "schemas" 1060 / "hyf_v1_jev" 1061 / binding["response_invalid"].string_value() 1062 ).read_text() 1063 ) 1064 assert_true( 1065 not validate(invalid_response, response_schema).valid, 1066 "invalid response example unexpectedly passed schema", 1067 ) 1068 1069 assert_true(validated >= 6) 1070 1071 1072 def _assert_manifest_examples( 1073 manifest_name: String, expected_valid: Int 1074 ) raises: 1075 var manifest = _wire_schema_json(manifest_name) 1076 assert_equal(manifest["spec_id"].string_value(), "hyf_v1_jev") 1077 var valid_count = 0 1078 for binding in manifest["bindings"].array_items(): 1079 var schema = _wire_schema_json(binding["schema"].string_value()) 1080 for rel in binding["valid"].array_items(): 1081 var doc = loads( 1082 ( 1083 _dir_of_current_file() 1084 / ".." 1085 / "schemas" 1086 / "hyf_v1_jev" 1087 / rel.string_value() 1088 ).read_text() 1089 ) 1090 assert_true( 1091 validate(doc, schema).valid, 1092 "valid example failed schema: " + rel.string_value(), 1093 ) 1094 valid_count += 1 1095 for rel in binding["invalid"].array_items(): 1096 var doc = loads( 1097 ( 1098 _dir_of_current_file() 1099 / ".." 1100 / "schemas" 1101 / "hyf_v1_jev" 1102 / rel.string_value() 1103 ).read_text() 1104 ) 1105 assert_true( 1106 not validate(doc, schema).valid, 1107 "invalid example unexpectedly passed: " + rel.string_value(), 1108 ) 1109 assert_equal(valid_count, expected_valid) 1110 1111 1112 def test_domain_representation_schemas_accept_valid_and_reject_invalid() raises: 1113 _assert_manifest_examples("domain_manifest.json", 5) 1114 1115 1116 def test_temporal_evidence_schemas_accept_valid_and_reject_invalid() raises: 1117 _assert_manifest_examples("temporal_manifest.json", 7) 1118 1119 1120 def _outcome_is_contradictory(doc: Value) raises -> Bool: 1121 var eligibility = doc["eligibility"].string_value() 1122 var mandatory_fail = False 1123 var mandatory_unknown = False 1124 for check in doc["checks"].array_items(): 1125 var result = check["result"].string_value() 1126 if check["mandatory"].bool_value(): 1127 if result == "fail": 1128 mandatory_fail = True 1129 elif result == "unknown": 1130 mandatory_unknown = True 1131 if mandatory_fail and eligibility != "ineligible": 1132 return True 1133 if not mandatory_fail and mandatory_unknown and eligibility == "eligible": 1134 return True 1135 return False 1136 1137 1138 def test_outcome_composition_rejects_contradictions() raises: 1139 _assert_manifest_examples("outcome_manifest.json", 3) 1140 var manifest = _wire_schema_json("outcome_manifest.json") 1141 for binding in manifest["bindings"].array_items(): 1142 var schema = _wire_schema_json(binding["schema"].string_value()) 1143 for rel in binding["valid"].array_items(): 1144 var doc = loads( 1145 ( 1146 _dir_of_current_file() 1147 / ".." 1148 / "schemas" 1149 / "hyf_v1_jev" 1150 / rel.string_value() 1151 ).read_text() 1152 ) 1153 assert_true(validate(doc, schema).valid) 1154 assert_true( 1155 not _outcome_is_contradictory(doc), 1156 "valid outcome treated as contradictory: " + rel.string_value(), 1157 ) 1158 for rel in binding["semantic_invalid"].array_items(): 1159 var doc = loads( 1160 ( 1161 _dir_of_current_file() 1162 / ".." 1163 / "schemas" 1164 / "hyf_v1_jev" 1165 / rel.string_value() 1166 ).read_text() 1167 ) 1168 assert_true( 1169 validate(doc, schema).valid, 1170 "semantic-invalid example must remain structurally valid", 1171 ) 1172 assert_true( 1173 _outcome_is_contradictory(doc), 1174 "contradictory outcome not detected: " + rel.string_value(), 1175 ) 1176 1177 1178 def test_semantic_fixture_corpus_is_installed_and_planned() raises: 1179 var fixture_dir = _dir_of_current_file() / "fixtures" / "hyf_v1_jev" 1180 var manifest = loads((fixture_dir / "manifest.json").read_text()) 1181 assert_equal(manifest["installation_status"].string_value(), "installed") 1182 assert_equal(manifest["family_kind"].string_value(), "semantic_acceptance") 1183 1184 var cases = manifest["cases"].array_items() 1185 assert_equal(len(cases), 116) 1186 for entry in cases: 1187 assert_true(entry["mandatory"].bool_value()) 1188 var case_path = fixture_dir / entry["path"].string_value() 1189 assert_true( 1190 exists(case_path), "missing case: " + entry["path"].string_value() 1191 ) 1192 var doc = loads(case_path.read_text()) 1193 assert_equal( 1194 doc["case_id"].string_value(), entry["case_id"].string_value() 1195 ) 1196 assert_equal(doc["implementation_status"].string_value(), "planned") 1197 assert_equal( 1198 doc["required_from_step"].string_value(), 1199 entry["required_from_step"].string_value(), 1200 ) 1201 assert_true(len(doc["requirements"].array_items()) > 0) 1202 assert_true(_has_key(doc, "provenance")) 1203 assert_true(len(doc["then"].array_items()) > 0) 1204 1205 var raw_files = manifest["raw_files"].array_items() 1206 assert_equal(len(raw_files), 5) 1207 for raw in raw_files: 1208 assert_true(exists(fixture_dir / raw.string_value())) 1209 1210 1211 def _write_min_fixture_corpus(base: Path, mutation: String) raises: 1212 var domain = base / "domain" 1213 std.os.makedirs(domain.__fspath__(), exist_ok=True) 1214 var case_text = ( 1215 '{"fixture_format_version":1,"case_id":"T001",' 1216 '"requirements":["HYF-TEST-001"],"implementation_status":"planned",' 1217 '"required_from_step":"S009","mandatory":true,"given":{},' 1218 '"provider_script":[],' 1219 '"then":[{"operator":"equals","path":"/x","value":1}],' 1220 '"provenance":{"kind":"synthetic"}}' 1221 ) 1222 if mutation == "unknown_operator": 1223 case_text = case_text.replace('"equals"', '"not_registered"') 1224 elif mutation == "empty_then": 1225 case_text = case_text.replace( 1226 '[{"operator":"equals","path":"/x","value":1}]', "[]" 1227 ) 1228 elif mutation == "missing_provenance": 1229 case_text = case_text.replace(',"provenance":{"kind":"synthetic"}', "") 1230 elif mutation == "empty_requirements": 1231 case_text = case_text.replace('["HYF-TEST-001"]', "[]") 1232 (domain / "T001.json").write_text(case_text) 1233 1234 var case_entry = ( 1235 '{"case_id":"T001","path":"domain/T001.json",' 1236 '"required_from_step":"S009","mandatory":true}' 1237 ) 1238 if mutation == "duplicate_case_id": 1239 case_entry = case_entry + "," + case_entry 1240 elif mutation == "dangling_path": 1241 case_entry = ( 1242 '{"case_id":"T001","path":"domain/missing.json",' 1243 '"required_from_step":"S009","mandatory":true}' 1244 ) 1245 elif mutation == "activation_step_mismatch": 1246 case_entry = ( 1247 '{"case_id":"T001","path":"domain/T001.json",' 1248 '"required_from_step":"S999","mandatory":true}' 1249 ) 1250 var manifest = ( 1251 '{"schema_version":1,"spec_id":"hyf_v1_jev",' 1252 '"installation_status":"installed","cases":[' 1253 + case_entry 1254 + '],"raw_files":[]}' 1255 ) 1256 (base / "manifest.json").write_text(manifest) 1257 1258 1259 def test_fixture_validator_accepts_corpus_and_rejects_corruptions() raises: 1260 var corpus_dir = _dir_of_current_file() / "fixtures" / "hyf_v1_jev" 1261 assert_equal(len(validate_fixture_corpus(corpus_dir.__fspath__())), 0) 1262 var mutations = List[String]() 1263 mutations.append("duplicate_case_id") 1264 mutations.append("dangling_path") 1265 mutations.append("unknown_operator") 1266 mutations.append("empty_then") 1267 mutations.append("missing_provenance") 1268 mutations.append("empty_requirements") 1269 mutations.append("activation_step_mismatch") 1270 for mutation in mutations: 1271 with SafeTempDir() as temp_dir: 1272 var base = Path(temp_dir) 1273 _write_min_fixture_corpus(base, mutation) 1274 assert_true( 1275 len(validate_fixture_corpus(base.__fspath__())) > 0, 1276 "validator accepted corruption: " + mutation, 1277 ) 1278 1279 1280 def test_projection_assertions_enforce_exactness_and_reject_unknown_operators() raises: 1281 var actual = loads( 1282 '{"assessment":{"eligibility":"eligible"},' 1283 '"plans":[{"plan_id":"p1","allocations":[{"lot_id":"lot-1",' 1284 '"revision":"l1","quantity":30}]}],' 1285 '"execution":{"hyf_business_writes":0}}' 1286 ) 1287 var passing = List[Value]() 1288 passing.append( 1289 loads( 1290 '{"operator":"equals","path":"/assessment/eligibility","value":"eligible"}' 1291 ) 1292 ) 1293 passing.append( 1294 loads('{"operator":"absent","path":"/assessment/failed_checks"}') 1295 ) 1296 passing.append( 1297 loads( 1298 '{"operator":"contains","path":"/plans/0/allocations","value":{"lot_id":"lot-1","revision":"l1","quantity":30}}' 1299 ) 1300 ) 1301 passing.append( 1302 loads( 1303 '{"operator":"tolerance","path":"/plans/0/allocations/0/quantity","value":30,"tolerance":0}' 1304 ) 1305 ) 1306 assert_projection(actual, passing) 1307 1308 var wrong_value = List[Value]() 1309 wrong_value.append( 1310 loads( 1311 '{"operator":"equals","path":"/assessment/eligibility","value":"ineligible"}' 1312 ) 1313 ) 1314 with assert_raises(): 1315 assert_projection(actual, wrong_value) 1316 1317 var missing_revision = List[Value]() 1318 missing_revision.append( 1319 loads( 1320 '{"operator":"present","path":"/plans/0/allocations/0/expected_revision"}' 1321 ) 1322 ) 1323 with assert_raises(): 1324 assert_projection(actual, missing_revision) 1325 1326 var wrong_order = List[Value]() 1327 wrong_order.append( 1328 loads( 1329 '{"operator":"equals","path":"/plans/0/allocations/0","value":{"lot_id":"lot-2","revision":"l1","quantity":30}}' 1330 ) 1331 ) 1332 with assert_raises(): 1333 assert_projection(actual, wrong_order) 1334 1335 var out_of_tolerance = List[Value]() 1336 out_of_tolerance.append( 1337 loads( 1338 '{"operator":"tolerance","path":"/plans/0/allocations/0/quantity","value":31,"tolerance":0}' 1339 ) 1340 ) 1341 with assert_raises(): 1342 assert_projection(actual, out_of_tolerance) 1343 1344 var unknown_operator = List[Value]() 1345 unknown_operator.append( 1346 loads( 1347 '{"operator":"approximately","path":"/assessment/eligibility","value":"eligible"}' 1348 ) 1349 ) 1350 with assert_raises(): 1351 assert_projection(actual, unknown_operator) 1352 1353 1354 def main() raises: 1355 TestSuite.discover_tests[__functions_in_module()]().run() 1356 1357 1358 from hyf_core.capabilities.registry import ( 1359 capability_assisted_supported, 1360 capability_exposure, 1361 ) 1362 1363 1364 def test_capability_exposure_separates_support_permission_readiness() raises: 1365 assert_true(capability_assisted_supported("query_rewrite")) 1366 assert_true(not capability_assisted_supported("semantic_rank")) 1367 var supported_but_blocked = capability_exposure( 1368 "query_rewrite", False, True, False 1369 ) 1370 assert_true(supported_but_blocked.implementation_supported) 1371 assert_true(not supported_but_blocked.provider_configured) 1372 assert_true(not supported_but_blocked.exposed) 1373 var fully_ready = capability_exposure("query_rewrite", True, True, True) 1374 assert_true(fully_ready.exposed) 1375 var permission_denied = capability_exposure( 1376 "query_rewrite", True, False, True 1377 ) 1378 assert_true(not permission_denied.exposed) 1379 1380 1381 from hyf_core.capabilities.registry import ( 1382 gated_operation_descriptors, 1383 gated_operation_is_exposed, 1384 ) 1385 1386 1387 def test_gated_operation_descriptors_are_prepared_not_exposed() raises: 1388 var descriptors = gated_operation_descriptors() 1389 assert_equal(len(descriptors), 3) 1390 for descriptor in descriptors: 1391 assert_true(not descriptor.exposed) 1392 assert_true(not gated_operation_is_exposed("farm_update.interpret", False)) 1393 assert_true(gated_operation_is_exposed("buyer_request.match", True)) 1394 assert_true(not gated_operation_is_exposed("query_rewrite", True)) 1395 1396 1397 # ── H009 strict JSON boundary characterization (current behavior) ──────────── 1398 1399 1400 def test_strict_json_boundary_characterizes_duplicate_keys() raises: 1401 # H009: pin the current duplicate-key behavior without declaring the final 1402 # policy. The shared decoder accepts a repeated key, preserves every entry 1403 # and resolves lookup to the first occurrence; a type-conflicting duplicate 1404 # is likewise not rejected. 1405 var value = loads('{"n":1,"m":2,"n":3}') 1406 assert_equal(value.object_count(), 3) 1407 assert_equal(value["n"].int_value(), 1) 1408 assert_equal(dumps(value), '{"n":1,"m":2,"n":3}') 1409 var conflicting = loads('{"n":1,"n":"x"}') 1410 assert_equal(conflicting.object_count(), 2) 1411 assert_equal(conflicting["n"].int_value(), 1) 1412 1413 1414 def test_strict_json_boundary_characterizes_numeric_and_null_values() raises: 1415 # H009: current int_value() performs no type check. Exponents, floats, null 1416 # and out-of-range integers decode to 0, and a string/bool/array value is 1417 # interpreted without a type error. Pinned as current behavior, not as an 1418 # approved contract. 1419 var exponent = loads('{"n":1e2}') 1420 assert_equal(exponent["n"].int_value(), 0) 1421 var fractional = loads('{"n":1.5}') 1422 assert_equal(fractional["n"].int_value(), 0) 1423 var null_value = loads('{"n":null}') 1424 assert_equal(null_value["n"].int_value(), 0) 1425 var overflow = loads('{"n":9223372036854775808}') 1426 assert_equal(overflow["n"].int_value(), 0) 1427 var negative = loads('{"n":-1}') 1428 assert_equal(negative["n"].int_value(), -1) 1429 var plain = loads('{"n":7}') 1430 assert_equal(plain["n"].int_value(), 7) 1431 var string_value = loads('{"n":"7"}') 1432 assert_true(string_value["n"].int_value() != 7) 1433 var boolean = loads('{"n":true}') 1434 assert_equal(boolean["n"].int_value(), 1) 1435 var array = loads('{"n":[1,2]}') 1436 assert_true(array["n"].int_value() != 0) 1437 1438 1439 def test_strict_json_boundary_accepts_invalid_utf8_in_a_string() raises: 1440 # H009: the shared decoder currently accepts a string value that contains 1441 # invalid UTF-8 bytes instead of rejecting the document. 1442 var bytes = List[UInt8]() 1443 for byte in '{"s":"'.as_bytes(): 1444 bytes.append(UInt8(Int(byte))) 1445 bytes.append(255) 1446 bytes.append(254) 1447 for byte in '"}'.as_bytes(): 1448 bytes.append(UInt8(Int(byte))) 1449 var raw = String( 1450 unsafe_from_utf8=Span(ptr=bytes.unsafe_ptr(), length=len(bytes)) 1451 ) 1452 var value = loads(raw) 1453 assert_equal(value.object_count(), 1) 1454 assert_true(_has_key(value, "s")) 1455 1456 1457 def test_stdio_envelope_boundary_characterizes_duplicate_keys() raises: 1458 # H009: the stdio request envelope currently accepts duplicated envelope 1459 # and input keys and resolves each to its first occurrence. 1460 var envelope = decode_request( 1461 '{"version":1,"version":2,"request_id":"a","request_id":"b",' 1462 '"capability":"query_rewrite","input":{"query":"eggs","query":"milk"}}' 1463 ) 1464 assert_equal(envelope.version, 1) 1465 assert_equal(envelope.request_id, "a") 1466 assert_equal(envelope.input["query"].string_value(), "eggs") 1467 1468 1469 def test_stdio_envelope_boundary_rejects_null_and_numeric_fields() raises: 1470 # H009: required envelope fields carry bounded, type-checked rejections for 1471 # null, a non-integer number, a non-string and a missing field. 1472 var cases = List[String]() 1473 cases.append( 1474 '{"version":null,"request_id":"a","capability":"query_rewrite",' 1475 '"input":{"query":"eggs"}}' 1476 ) 1477 cases.append( 1478 '{"version":1.5,"request_id":"a","capability":"query_rewrite",' 1479 '"input":{"query":"eggs"}}' 1480 ) 1481 cases.append( 1482 '{"request_id":"a","capability":"query_rewrite","input":{"query":"eggs"}}' 1483 ) 1484 cases.append( 1485 '{"version":1,"request_id":7,"capability":"query_rewrite",' 1486 '"input":{"query":"eggs"}}' 1487 ) 1488 cases.append( 1489 '{"version":1,"request_id":"a","capability":null,' 1490 '"input":{"query":"eggs"}}' 1491 ) 1492 var messages = List[String]() 1493 for index in range(len(cases)): 1494 var message = "" 1495 try: 1496 _ = decode_request(cases[index]) 1497 except e: 1498 message = String(e) 1499 messages.append(message) 1500 assert_true(messages[0].find("must be an integer") >= 0) 1501 assert_true(messages[1].find("must be an integer") >= 0) 1502 assert_true(messages[2].find("'version' is required") >= 0) 1503 assert_true(messages[3].find("not a string") >= 0) 1504 assert_true(messages[4].find("not a string") >= 0) 1505 1506 1507 # ADR-0025 D45 C004: strict hyf_ops_v2 capability context and pre-activation guard. 1508 from hyf_core.operation_context import ( 1509 corrected_operation_activation_enabled, 1510 is_corrected_operation, 1511 operation_context_selects_v2, 1512 ) 1513 from hyf_runtime.config import operation_enabled as _operation_enabled 1514 1515 1516 def _v2_versions_json() -> String: 1517 return ( 1518 '"versions":{"schema":"hyf_ops_v2",' 1519 '"taxonomy":"hyf_ops_v2.taxonomy.v1",' 1520 '"normalization":"hyf_ops_v2.normalization.v1",' 1521 '"review_policy":"hyf_ops_v2.review_policy.v1",' 1522 '"ranking_policy":"hyf_ops_v2.ranking_policy.v1",' 1523 '"question_bundle":"hyf_ops_v2.question_bundle.v1",' 1524 '"model":"jev-1.13.0"}' 1525 ) 1526 1527 1528 def _v2_farm_references_json() -> String: 1529 return ( 1530 '"references":{"taxonomy":{"version":"hyf_ops_v2.taxonomy.v1",' 1531 '"provenance":"host_supplied","products":[' 1532 '{"catalogue_id":"tomato.roma","terms":["Roma tomatoes"]}]},' 1533 '"normalization":{"version":"hyf_ops_v2.normalization.v1",' 1534 '"provenance":"host_supplied","units":[{"unit":"lb","dimension":"mass"}],' 1535 '"conversions":[],"packs":[]}}' 1536 ) 1537 1538 1539 def _v2_farm_source_json() -> String: 1540 return ( 1541 '"source":{"source_id":"s1","revision":"r1",' 1542 '"text":"80 lb of Roma tomatoes",' 1543 '"source_time":"2026-09-24T08:30:00-07:00",' 1544 '"timezone":"America/Vancouver","actor_id":"farm-1","farm_id":"farm-1"}' 1545 ) 1546 1547 1548 def _v2_farm_request() -> String: 1549 return ( 1550 '{"version":1,"request_id":"v2-farm-1",' 1551 '"capability":"farm_update.interpret",' 1552 '"context":{"consumer":"radroots-cli",' 1553 '"execution_mode_preference":"deterministic","deadline_ms":2500,' 1554 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 1555 '"timezone":"America/Vancouver","locale":"en-CA",' 1556 + _v2_versions_json() 1557 + ',"return_provenance":true,"actor_id":"farm-1","farm_id":"farm-1"},' 1558 '"input":{' 1559 + _v2_farm_source_json() 1560 + "," 1561 + _v2_farm_references_json() 1562 + "}}" 1563 ) 1564 1565 1566 def _v2_farm_request_with_context(context_body: String) -> String: 1567 return ( 1568 '{"version":1,"request_id":"v2-farm-variant",' 1569 '"capability":"farm_update.interpret","context":{' 1570 + context_body 1571 + '},"input":{' 1572 + _v2_farm_source_json() 1573 + "," 1574 + _v2_farm_references_json() 1575 + "}}" 1576 ) 1577 1578 1579 def _decode_error_message(line: String) -> String: 1580 try: 1581 _ = decode_request(line) 1582 except e: 1583 return String(e) 1584 return "" 1585 1586 1587 def test_c004_corrected_operation_registry_and_activation_boundary() raises: 1588 assert_true(is_corrected_operation("farm_update.interpret")) 1589 assert_true(is_corrected_operation("buyer_request.interpret")) 1590 assert_true(is_corrected_operation("buyer_request.match")) 1591 assert_true(not is_corrected_operation("query_rewrite")) 1592 # C042-C046 own activation; C004 binds the guard but never activates. 1593 assert_true(not corrected_operation_activation_enabled()) 1594 1595 1596 def test_c004_decode_request_parses_operation_v2_context() raises: 1597 var request = decode_request(_v2_farm_request()) 1598 assert_equal(request.capability, "farm_update.interpret") 1599 assert_true(request.operation_context) 1600 var context = request.operation_context.value().copy() 1601 assert_equal(context.consumer, "radroots-cli") 1602 assert_equal(context.execution_mode_preference, "deterministic") 1603 assert_equal(context.deadline_ms, 2500) 1604 assert_equal(context.evaluation_time, "2026-09-24T09:00:00-07:00") 1605 assert_equal(context.timezone.value(), "America/Vancouver") 1606 assert_equal(context.locale.value(), "en-CA") 1607 assert_equal(context.return_provenance, True) 1608 assert_equal(context.actor_id, "farm-1") 1609 assert_equal(context.farm_id.value(), "farm-1") 1610 assert_equal(context.versions.schema, "hyf_ops_v2") 1611 assert_equal(context.versions.taxonomy, "hyf_ops_v2.taxonomy.v1") 1612 assert_equal(context.versions.normalization, "hyf_ops_v2.normalization.v1") 1613 assert_equal(context.versions.review_policy, "hyf_ops_v2.review_policy.v1") 1614 assert_equal( 1615 context.versions.ranking_policy, "hyf_ops_v2.ranking_policy.v1" 1616 ) 1617 assert_equal( 1618 context.versions.question_bundle, "hyf_ops_v2.question_bundle.v1" 1619 ) 1620 assert_equal(context.versions.model, "jev-1.13.0") 1621 1622 1623 def test_c004_operation_v2_context_defaults_are_not_host_guesses() raises: 1624 var request = decode_request( 1625 _v2_farm_request_with_context( 1626 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 1627 + _v2_versions_json() 1628 + ',"actor_id":"farm-1","farm_id":"farm-1"' 1629 ) 1630 ) 1631 assert_true(request.operation_context) 1632 var context = request.operation_context.value().copy() 1633 assert_equal(context.consumer, "unknown") 1634 assert_equal(context.execution_mode_preference, "deterministic") 1635 assert_equal(context.deadline_ms, 2500) 1636 assert_equal(context.return_provenance, False) 1637 # Absent timezone/locale stay unknown; they are not filled from the host clock. 1638 assert_true(not context.timezone) 1639 assert_true(not context.locale) 1640 1641 1642 def test_c004_operation_v2_context_is_strict() raises: 1643 var missing_actor = _v2_farm_request_with_context( 1644 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 1645 + _v2_versions_json() 1646 + ',"farm_id":"farm-1"' 1647 ) 1648 assert_true(_decode_error_message(missing_actor).find("actor_id") >= 0) 1649 1650 var duplicate_actor = _v2_farm_request_with_context( 1651 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 1652 + _v2_versions_json() 1653 + ',"actor_id":"farm-1","actor_id":"farm-2","farm_id":"farm-1"' 1654 ) 1655 assert_true(_decode_error_message(duplicate_actor).find("duplicate") >= 0) 1656 1657 var missing_farm = _v2_farm_request_with_context( 1658 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 1659 + _v2_versions_json() 1660 + ',"actor_id":"farm-1"' 1661 ) 1662 assert_true(_decode_error_message(missing_farm).find("farm_id") >= 0) 1663 1664 var null_timezone = _v2_farm_request_with_context( 1665 '"evaluation_time":"2026-09-24T09:00:00-07:00","timezone":null,' 1666 + _v2_versions_json() 1667 + ',"actor_id":"farm-1","farm_id":"farm-1"' 1668 ) 1669 assert_true(_decode_error_message(null_timezone).find("string") >= 0) 1670 1671 var unknown_field = _v2_farm_request_with_context( 1672 '"evaluation_time":"2026-09-24T09:00:00-07:00","planner":"strict",' 1673 + _v2_versions_json() 1674 + ',"actor_id":"farm-1","farm_id":"farm-1"' 1675 ) 1676 assert_true(_decode_error_message(unknown_field).find("unexpected") >= 0) 1677 1678 var empty_actor = _v2_farm_request_with_context( 1679 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 1680 + _v2_versions_json() 1681 + ',"actor_id":"","farm_id":"farm-1"' 1682 ) 1683 assert_true(_decode_error_message(empty_actor).find("actor_id") >= 0) 1684 1685 1686 def test_c004_operation_v2_versions_are_closed_and_complete() raises: 1687 var incomplete = _v2_farm_request_with_context( 1688 '"evaluation_time":"2026-09-24T09:00:00-07:00","versions":{' 1689 '"schema":"hyf_ops_v2","taxonomy":"t","normalization":"n",' 1690 '"review_policy":"r","ranking_policy":"k","model":"jev-1.13.0"},' 1691 '"actor_id":"farm-1","farm_id":"farm-1"' 1692 ) 1693 assert_true(_decode_error_message(incomplete).find("question_bundle") >= 0) 1694 1695 var unknown_axis = _v2_farm_request_with_context( 1696 '"evaluation_time":"2026-09-24T09:00:00-07:00","versions":{' 1697 '"schema":"hyf_ops_v2","taxonomy":"t","normalization":"n",' 1698 '"review_policy":"r","ranking_policy":"k","question_bundle":"q",' 1699 '"model":"jev-1.13.0","extra":"x"},' 1700 '"actor_id":"farm-1","farm_id":"farm-1"' 1701 ) 1702 assert_true(_decode_error_message(unknown_axis).find("unexpected") >= 0) 1703 1704 1705 def test_c004_operation_v2_buyer_forbids_farm_identity() raises: 1706 var buyer_with_farm = ( 1707 '{"version":1,"request_id":"v2-buyer-farm",' 1708 '"capability":"buyer_request.interpret",' 1709 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 1710 + _v2_versions_json() 1711 + ',"actor_id":"buyer-7","farm_id":"farm-1"},' 1712 '"input":{"source":{"source_id":"s1","revision":"r1","text":"25 lb",' 1713 '"source_time":"2026-09-24T08:45:00-07:00","actor_id":"buyer-7"},' 1714 + _v2_farm_references_json() 1715 + "}}" 1716 ) 1717 assert_true(_decode_error_message(buyer_with_farm).find("unexpected") >= 0) 1718 1719 var buyer_ok = ( 1720 '{"version":1,"request_id":"v2-buyer-ok",' 1721 '"capability":"buyer_request.interpret",' 1722 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 1723 + _v2_versions_json() 1724 + ',"actor_id":"buyer-7"},' 1725 '"input":{"source":{"source_id":"s1","revision":"r1","text":"25 lb",' 1726 '"source_time":"2026-09-24T08:45:00-07:00","actor_id":"buyer-7"},' 1727 + _v2_farm_references_json() 1728 + "}}" 1729 ) 1730 var request = decode_request(buyer_ok) 1731 assert_true(request.operation_context) 1732 assert_true(not request.operation_context.value().copy().farm_id) 1733 assert_equal(request.operation_context.value().copy().actor_id, "buyer-7") 1734 1735 1736 def test_c004_selector_detection_does_not_broaden_legacy_context() raises: 1737 var context = loads("{}") 1738 context.set("versions", loads('{"schema":"hyf_ops_v2"}')) 1739 assert_true(operation_context_selects_v2(context)) 1740 assert_true(not operation_context_selects_v2(loads('{"consumer":"cli"}'))) 1741 assert_true( 1742 not operation_context_selects_v2( 1743 loads('{"versions":{"schema":"hyf_ops_v3"}}') 1744 ) 1745 ) 1746 assert_true(not operation_context_selects_v2(loads('{"versions":1}'))) 1747 1748 # An unrelated capability keeps the unchanged legacy admission and rejects 1749 # the advertised-but-unsupported `versions` field. 1750 var legacy_with_versions = ( 1751 '{"version":1,"request_id":"legacy-versions",' 1752 '"capability":"query_rewrite","context":{' 1753 + _v2_versions_json() 1754 + '},"input":{"query":"eggs"}}' 1755 ) 1756 assert_true( 1757 _decode_error_message(legacy_with_versions).find("unexpected") >= 0 1758 ) 1759 1760 # The unchanged legacy envelope still parses its original context. 1761 var legacy_request = decode_request( 1762 '{"version":1,"request_id":"legacy-ok","capability":"query_rewrite",' 1763 '"context":{"consumer":"radroots-cli","deadline_ms":2500},' 1764 '"input":{"query":"eggs"}}' 1765 ) 1766 assert_true(not legacy_request.operation_context) 1767 assert_equal(legacy_request.context.consumer, "radroots-cli") 1768 1769 1770 def test_c004_operation_v2_guard_blocks_shortcut_even_when_enabled() raises: 1771 with SafeTempDir() as temp_dir: 1772 var runtime_context = resolve_startup_context( 1773 RuntimeStartupInput( 1774 env_paths_profile="repo_local", 1775 env_repo_local_base_root=temp_dir, 1776 user_home="/home/unused", 1777 argv=List[String](), 1778 ) 1779 ) 1780 runtime_context.config.effective.runtime.enable_farm_update_interpret = ( 1781 True 1782 ) 1783 assert_true( 1784 _operation_enabled(runtime_context.config, "farm_update.interpret") 1785 ) 1786 var response = loads( 1787 handle_request_line_with_runtime_context( 1788 _v2_farm_request(), runtime_context 1789 ) 1790 ) 1791 assert_equal(response["ok"].bool_value(), False) 1792 assert_equal( 1793 response["error"]["code"].string_value(), "capability_unavailable" 1794 ) 1795 # Never the placeholder shortcut output, and zero provider calls. 1796 assert_true(not _has_key(response, "output")) 1797 1798 1799 def test_c004_legacy_gated_operation_still_executes_when_enabled() raises: 1800 with SafeTempDir() as temp_dir: 1801 var runtime_context = resolve_startup_context( 1802 RuntimeStartupInput( 1803 env_paths_profile="repo_local", 1804 env_repo_local_base_root=temp_dir, 1805 user_home="/home/unused", 1806 argv=List[String](), 1807 ) 1808 ) 1809 runtime_context.config.effective.runtime.enable_farm_update_interpret = ( 1810 True 1811 ) 1812 var legacy = ( 1813 '{"version":1,"request_id":"legacy-farm-1",' 1814 '"capability":"farm_update.interpret","input":{' 1815 + _v2_farm_source_json() 1816 + "}}" 1817 ) 1818 var response = loads( 1819 handle_request_line_with_runtime_context(legacy, runtime_context) 1820 ) 1821 assert_equal(response["ok"].bool_value(), True) 1822 assert_true(_has_key(response["output"], "claims")) 1823 1824 1825 def test_c004_v2_schema_assets_and_manifest_integrity() raises: 1826 var schema_dir = _dir_of_current_file() / ".." / "schemas" / "hyf_ops_v2" 1827 var manifest = loads((schema_dir / "manifest.json").read_text()) 1828 assert_equal(manifest["selector"]["value"].string_value(), "hyf_ops_v2") 1829 assert_equal(Int(manifest["envelope_version"].int_value()), 1) 1830 assert_equal( 1831 manifest["activation"]["guard_error_code"].string_value(), 1832 "capability_unavailable", 1833 ) 1834 assert_equal( 1835 manifest["activation"]["state"].string_value(), "pre_activation" 1836 ) 1837 1838 var versions = loads((schema_dir / "version_manifest.json").read_text())[ 1839 "versions" 1840 ] 1841 var axes = List[String]() 1842 axes.append("schema") 1843 axes.append("taxonomy") 1844 axes.append("normalization") 1845 axes.append("review_policy") 1846 axes.append("ranking_policy") 1847 axes.append("question_bundle") 1848 axes.append("model") 1849 for axis in axes: 1850 assert_true(_has_key(versions, axis)) 1851 assert_true(versions[axis].string_value() != "") 1852 assert_equal(versions["schema"].string_value(), "hyf_ops_v2") 1853 1854 var operations = manifest["operations"] 1855 for operation in operations.object_keys(): 1856 var entry = operations[operation] 1857 var request_schema = loads( 1858 (schema_dir / entry["request_schema"].string_value()).read_text() 1859 ) 1860 var response_schema = loads( 1861 (schema_dir / entry["response_schema"].string_value()).read_text() 1862 ) 1863 assert_equal( 1864 request_schema["properties"]["capability"]["const"].string_value(), 1865 operation, 1866 ) 1867 var context_def = request_schema["$defs"][ 1868 "farm_context" if operation 1869 == "farm_update.interpret" else "buyer_context" 1870 ] 1871 var context_required = List[String]() 1872 for value in context_def["required"].array_items(): 1873 context_required.append(value.string_value()) 1874 assert_true("actor_id" in context_required) 1875 assert_true("versions" in context_required) 1876 assert_true("evaluation_time" in context_required) 1877 var context_properties = context_def["properties"] 1878 if operation == "farm_update.interpret": 1879 assert_true(_has_key(context_properties, "farm_id")) 1880 else: 1881 assert_true(not _has_key(context_properties, "farm_id")) 1882 var response_required = List[String]() 1883 for required in response_schema["required"].array_items(): 1884 response_required.append(required.string_value()) 1885 assert_equal(len(response_required), 3) 1886 assert_true("version" in response_required) 1887 assert_true("request_id" in response_required) 1888 assert_true("ok" in response_required) 1889 1890 var corpus = loads((schema_dir / "examples" / "corpus.json").read_text()) 1891 var entries = corpus["entries"].array_items() 1892 assert_true(len(entries) >= 30) 1893 for entry in entries: 1894 assert_true(exists(schema_dir / entry["file"].string_value())) 1895 1896 1897 def test_c004_bp01_money_and_provenance_bindings() raises: 1898 # ADR-0027 D47 BP01: the v2 copy binds scaled money on snapshot.price and a 1899 # required closed provenance object on every successful output. 1900 var schema_dir = _dir_of_current_file() / ".." / "schemas" / "hyf_ops_v2" 1901 var match_request = loads( 1902 (schema_dir / "buyer_request_match.request.schema.json").read_text() 1903 ) 1904 var price = match_request["$defs"]["snapshot_price"] 1905 var price_required = List[String]() 1906 for value in price["required"].array_items(): 1907 price_required.append(value.string_value()) 1908 assert_equal(len(price_required), 5) 1909 for field in ["state", "amount", "scale", "currency", "basis"]: 1910 assert_true(field in price_required) 1911 assert_equal(price["additionalProperties"].bool_value(), False) 1912 assert_true(_has_key(price["properties"], "fees")) 1913 assert_equal(len(price["allOf"].array_items()), 2) 1914 1915 # price remains optional on the snapshot; the quantity fields stay required. 1916 var snapshot_required = List[String]() 1917 for value in match_request["$defs"]["snapshot"]["required"].array_items(): 1918 snapshot_required.append(value.string_value()) 1919 assert_true("lot_id" in snapshot_required) 1920 assert_true(not ("price" in snapshot_required)) 1921 1922 var farm_response = loads( 1923 (schema_dir / "farm_update_interpret.response.schema.json").read_text() 1924 ) 1925 var buyer_response = loads( 1926 ( 1927 schema_dir / "buyer_request_interpret.response.schema.json" 1928 ).read_text() 1929 ) 1930 var match_response = loads( 1931 (schema_dir / "buyer_request_match.response.schema.json").read_text() 1932 ) 1933 var farm_required = List[String]() 1934 for value in farm_response["$defs"]["farm_output"][ 1935 "required" 1936 ].array_items(): 1937 farm_required.append(value.string_value()) 1938 assert_true("provenance" in farm_required) 1939 var buyer_required = List[String]() 1940 for value in buyer_response["$defs"]["interpret_output"][ 1941 "required" 1942 ].array_items(): 1943 buyer_required.append(value.string_value()) 1944 assert_true("provenance" in buyer_required) 1945 var match_required = List[String]() 1946 for value in match_response["$defs"]["match_output"][ 1947 "required" 1948 ].array_items(): 1949 match_required.append(value.string_value()) 1950 assert_true("provenance" in match_required) 1951 1952 # Farm provenance keeps the prior-record family; buyer provenance is closed 1953 # without it; match provenance records need and evaluated snapshots. 1954 assert_true( 1955 _has_key( 1956 farm_response["$defs"]["farm_output_provenance"]["properties"], 1957 "prior_records", 1958 ) 1959 ) 1960 assert_true( 1961 not _has_key( 1962 buyer_response["$defs"]["interpret_output_provenance"][ 1963 "properties" 1964 ], 1965 "prior_records", 1966 ) 1967 ) 1968 var match_provenance_required = List[String]() 1969 for value in match_response["$defs"]["match_output_provenance"][ 1970 "required" 1971 ].array_items(): 1972 match_provenance_required.append(value.string_value()) 1973 assert_true("need" in match_provenance_required) 1974 assert_true("snapshots" in match_provenance_required) 1975 1976 var corpus = loads((schema_dir / "examples" / "corpus.json").read_text()) 1977 var corpus_files = List[String]() 1978 for entry in corpus["entries"].array_items(): 1979 corpus_files.append(entry["file"].string_value()) 1980 assert_true("examples/valid/price.known_zero.json" in corpus_files) 1981 assert_true("examples/valid/price.unknown.json" in corpus_files) 1982 assert_true("examples/invalid/price.adjacent_overflow.json" in corpus_files) 1983 assert_true( 1984 "examples/invalid/farm_update_interpret.response.missing_provenance.json" 1985 in corpus_files 1986 ) 1987 1988 var semantic = loads((schema_dir / "semantic-cases.json").read_text()) 1989 var case_ids = List[String]() 1990 for semantic_case in semantic["cases"].array_items(): 1991 case_ids.append(semantic_case["id"].string_value()) 1992 for case_id in [ 1993 "price_known_requires_scaled_facts", 1994 "price_unknown_is_not_zero", 1995 "price_coefficient_int64_bound", 1996 "price_basis_closed", 1997 "price_fee_family_closed", 1998 "provenance_required_on_success", 1999 "provenance_identity_closed", 2000 "provenance_farm_prior_records_only", 2001 ]: 2002 assert_true(case_id in case_ids) 2003 2004 # The manifest documents both bindings. 2005 var manifest = loads((schema_dir / "manifest.json").read_text()) 2006 assert_true(_has_key(manifest, "money_binding")) 2007 assert_true(_has_key(manifest, "provenance_binding")) 2008 2009 2010 def test_c004_operation_v2_escaped_duplicate_key_is_rejected() raises: 2011 # \u0061 is 'a'; the parser decodes key escapes, so the second key is a 2012 # duplicate actor_id and must be rejected by decoded-key identity. 2013 var escaped = _v2_farm_request_with_context( 2014 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 2015 + _v2_versions_json() 2016 + ',"actor_id":"farm-1","\\u0061ctor_id":"farm-2","farm_id":"farm-1"' 2017 ) 2018 assert_true(_decode_error_message(escaped).find("duplicate") >= 0) 2019 2020 2021 def test_c004_operation_v2_whitespace_only_identity_is_rejected() raises: 2022 var blank_actor = _v2_farm_request_with_context( 2023 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 2024 + _v2_versions_json() 2025 + ',"actor_id":" ","farm_id":"farm-1"' 2026 ) 2027 assert_true(_decode_error_message(blank_actor).find("blank") >= 0) 2028 2029 var blank_version = _v2_farm_request_with_context( 2030 '"evaluation_time":"2026-09-24T09:00:00-07:00","versions":{' 2031 '"schema":"hyf_ops_v2","taxonomy":" ","normalization":"n",' 2032 '"review_policy":"r","ranking_policy":"k","question_bundle":"q",' 2033 '"model":"m"},"actor_id":"farm-1","farm_id":"farm-1"' 2034 ) 2035 assert_true(_decode_error_message(blank_version).find("blank") >= 0) 2036 2037 2038 # ADR-0026 D46 CR04 / ADR-0027 D47 BP02: unambiguous duplicate admission, 2039 # safe correlation and an executed zero-dispatch observer for all three 2040 # corrected operations. 2041 from hyf_stdio.dispatch_observer import RecordingDispatchAttemptObserver 2042 from hyf_stdio.server import ( 2043 handle_request_line_with_runtime_context_and_observer, 2044 ) 2045 2046 2047 def _v2_farm_request_minimal(request_id: String) -> String: 2048 return ( 2049 '{"version":1,"request_id":"' 2050 + request_id 2051 + '","capability":"farm_update.interpret",' 2052 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2053 + _v2_versions_json() 2054 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2055 ) 2056 2057 2058 def _v2_buyer_request_minimal(capability: String, request_id: String) -> String: 2059 return ( 2060 '{"version":1,"request_id":"' 2061 + request_id 2062 + '","capability":"' 2063 + capability 2064 + '","context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2065 + _v2_versions_json() 2066 + ',"actor_id":"buyer-7"},"input":{}}' 2067 ) 2068 2069 2070 def _temp_runtime_context(temp_dir: String) raises -> RuntimeStartupContext: 2071 return resolve_startup_context( 2072 RuntimeStartupInput( 2073 env_paths_profile="repo_local", 2074 env_repo_local_base_root=temp_dir, 2075 user_home="/home/unused", 2076 argv=List[String](), 2077 ) 2078 ) 2079 2080 2081 def test_c004_cr04_duplicate_capability_cannot_hide_corrected_operation() raises: 2082 # Corrected capability first, legacy capability second. 2083 var v2_first = ( 2084 '{"version":1,"request_id":"dup-cap-a",' 2085 '"capability":"farm_update.interpret","capability":"query_rewrite",' 2086 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2087 + _v2_versions_json() 2088 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2089 ) 2090 assert_true(_decode_error_message(v2_first).find("duplicate") >= 0) 2091 2092 # Legacy capability first, corrected capability second: the corrected value 2093 # must still make the envelope v2-targeting and therefore ambiguous. 2094 var v2_second = ( 2095 '{"version":1,"request_id":"dup-cap-b",' 2096 '"capability":"query_rewrite","capability":"buyer_request.match",' 2097 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2098 + _v2_versions_json() 2099 + ',"actor_id":"buyer-7"},"input":{}}' 2100 ) 2101 assert_true(_decode_error_message(v2_second).find("duplicate") >= 0) 2102 2103 2104 def test_c004_cr04_duplicate_context_cannot_hide_v2_selector() raises: 2105 # Legacy context first, v2 context second. 2106 var legacy_first = ( 2107 '{"version":1,"request_id":"dup-ctx-a",' 2108 '"capability":"farm_update.interpret",' 2109 '"context":{"consumer":"cli"},' 2110 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2111 + _v2_versions_json() 2112 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2113 ) 2114 assert_true(_decode_error_message(legacy_first).find("duplicate") >= 0) 2115 2116 # v2 context first, legacy context second. 2117 var v2_first = ( 2118 '{"version":1,"request_id":"dup-ctx-b",' 2119 '"capability":"buyer_request.interpret",' 2120 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2121 + _v2_versions_json() 2122 + ',"actor_id":"buyer-7"},"context":{"consumer":"cli"},"input":{}}' 2123 ) 2124 assert_true(_decode_error_message(v2_first).find("duplicate") >= 0) 2125 2126 2127 def test_c004_cr04_duplicate_correlation_and_equal_values_are_rejected() raises: 2128 var duplicate_request_id = ( 2129 '{"version":1,"request_id":"dup-rid-a","request_id":"dup-rid-b",' 2130 '"capability":"farm_update.interpret",' 2131 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2132 + _v2_versions_json() 2133 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2134 ) 2135 assert_true( 2136 _decode_error_message(duplicate_request_id).find("duplicate") >= 0 2137 ) 2138 2139 # Equal values are still ambiguous duplicates. 2140 var equal_values = ( 2141 '{"version":1,"request_id":"dup-eq-a","request_id":"dup-eq-a",' 2142 '"capability":"buyer_request.match",' 2143 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2144 + _v2_versions_json() 2145 + ',"actor_id":"buyer-7"},"input":{}}' 2146 ) 2147 assert_true(_decode_error_message(equal_values).find("duplicate") >= 0) 2148 2149 # Escaped equivalent of `capability` is a decoded-key duplicate. 2150 var escaped_capability = ( 2151 '{"version":1,"request_id":"dup-esc",' 2152 '"capability":"farm_update.interpret","\\u0063apability":"query_rewrite",' 2153 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2154 + _v2_versions_json() 2155 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2156 ) 2157 assert_true( 2158 _decode_error_message(escaped_capability).find("duplicate") >= 0 2159 ) 2160 2161 2162 def test_c004_cr04_unrelated_legacy_duplicate_keeps_existing_admission() raises: 2163 # An unrelated legacy capability is not v2-targeting, so the new duplicate 2164 # gate deliberately does not apply and the existing legacy admission is 2165 # unchanged (first-wins envelope parse proceeds). 2166 var legacy_duplicate = ( 2167 '{"version":1,"request_id":"legacy-dup",' 2168 '"capability":"query_rewrite","capability":"query_rewrite",' 2169 '"input":{"query":"eggs"}}' 2170 ) 2171 var request = decode_request(legacy_duplicate) 2172 assert_true(not request.operation_context) 2173 assert_equal(request.capability, "query_rewrite") 2174 2175 2176 def test_c004_cr04_ambiguous_duplicate_correlation_is_untrusted() raises: 2177 with SafeTempDir() as temp_dir: 2178 var runtime_context = _temp_runtime_context(temp_dir) 2179 var line = ( 2180 '{"version":1,"request_id":"dup-cor-a","request_id":"dup-cor-b",' 2181 '"trace_id":"dup-trace-a","trace_id":"dup-trace-b",' 2182 '"capability":"farm_update.interpret",' 2183 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2184 + _v2_versions_json() 2185 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2186 ) 2187 var response = loads( 2188 handle_request_line_with_runtime_context(line, runtime_context) 2189 ) 2190 assert_equal(response["ok"].bool_value(), False) 2191 assert_equal( 2192 response["error"]["code"].string_value(), "invalid_request" 2193 ) 2194 # Ambiguous duplicates are never first/last-wins correlation. 2195 assert_equal(response["request_id"].string_value(), "") 2196 assert_true(not _has_key(response, "trace_id")) 2197 2198 # A single unambiguous correlation is still preserved on the same error. 2199 var unambiguous = ( 2200 '{"version":1,"request_id":"dup-cor-ok","trace_id":"trace-ok",' 2201 '"capability":"farm_update.interpret",' 2202 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2203 + _v2_versions_json() 2204 + ',"actor_id":"farm-1"},"input":{}}' 2205 ) 2206 var preserved = loads( 2207 handle_request_line_with_runtime_context( 2208 unambiguous, runtime_context 2209 ) 2210 ) 2211 assert_equal(preserved["ok"].bool_value(), False) 2212 assert_equal(preserved["request_id"].string_value(), "dup-cor-ok") 2213 assert_equal(preserved["trace_id"].string_value(), "trace-ok") 2214 2215 2216 def test_c004_cr04_context_admission_is_bounded_and_linear() raises: 2217 # A large repeated allowed key is one decoded-key duplicate and is rejected 2218 # by the linear seen-key scan rather than an all-pairs comparison. 2219 var repeated = List[String]() 2220 for _ in range(256): 2221 repeated.append('"actor_id":"farm-1"') 2222 var many_duplicates = _v2_farm_request_with_context( 2223 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 2224 + _v2_versions_json() 2225 + "," 2226 + ",".join(repeated) 2227 + ',"farm_id":"farm-1"' 2228 ) 2229 assert_true(_decode_error_message(many_duplicates).find("duplicate") >= 0) 2230 2231 # An unknown key is still rejected by the fixed allowed-key set. 2232 var unknown_and_dup = _v2_farm_request_with_context( 2233 '"evaluation_time":"2026-09-24T09:00:00-07:00","planner":"strict",' 2234 + _v2_versions_json() 2235 + ',"actor_id":"farm-1","actor_id":"farm-2","farm_id":"farm-1"' 2236 ) 2237 var message = _decode_error_message(unknown_and_dup) 2238 assert_true( 2239 message.find("duplicate") >= 0 or message.find("unexpected") >= 0 2240 ) 2241 2242 2243 def test_c004_cr04_zero_dispatch_observer_executed_controls() raises: 2244 with SafeTempDir() as temp_dir: 2245 var runtime_context = _temp_runtime_context(temp_dir) 2246 runtime_context.config.effective.runtime.enable_farm_update_interpret = ( 2247 True 2248 ) 2249 runtime_context.config.effective.runtime.enable_buyer_request_interpret = ( 2250 True 2251 ) 2252 runtime_context.config.effective.runtime.enable_buyer_request_match = ( 2253 True 2254 ) 2255 # The observation state is owned by this test invocation: a bounded 2256 # in-memory list threaded through the real pre-dispatch boundary. No 2257 # environment variable, file path or global state is involved. 2258 var observer = RecordingDispatchAttemptObserver(attempts=List[String]()) 2259 2260 # Negative controls: every recognized v2 request for all three 2261 # corrected operations returns capability_unavailable and performs 2262 # zero dispatch attempts, including with the legacy flags enabled. 2263 var v2_requests = List[String]() 2264 v2_requests.append(_v2_farm_request_minimal("sentry-farm")) 2265 v2_requests.append( 2266 _v2_buyer_request_minimal( 2267 "buyer_request.interpret", "sentry-interpret" 2268 ) 2269 ) 2270 v2_requests.append( 2271 _v2_buyer_request_minimal("buyer_request.match", "sentry-match") 2272 ) 2273 for line in v2_requests: 2274 assert_true( 2275 _operation_enabled( 2276 runtime_context.config, 2277 loads(line)["capability"].string_value(), 2278 ) 2279 ) 2280 var response = loads( 2281 handle_request_line_with_runtime_context_and_observer( 2282 line, runtime_context, observer 2283 ) 2284 ) 2285 assert_equal(response["ok"].bool_value(), False) 2286 assert_equal( 2287 response["error"]["code"].string_value(), 2288 "capability_unavailable", 2289 ) 2290 assert_equal(len(observer.attempts), 0) 2291 2292 # Malformed duplicate controls are rejected before any dispatch point, 2293 # so they record nothing either. 2294 var malformed = List[String]() 2295 malformed.append( 2296 '{"version":1,"request_id":"dup-ctx",' 2297 '"capability":"farm_update.interpret",' 2298 '"context":{"consumer":"cli"},' 2299 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2300 + _v2_versions_json() 2301 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2302 ) 2303 malformed.append( 2304 '{"version":1,"request_id":"dup-rid","request_id":"dup-rid-2",' 2305 '"capability":"buyer_request.match",' 2306 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2307 + _v2_versions_json() 2308 + ',"actor_id":"buyer-7"},"input":{}}' 2309 ) 2310 malformed.append( 2311 '{"version":1,"request_id":"dup-esc",' 2312 '"capability":"farm_update.interpret",' 2313 '"\\u0063apability":"query_rewrite",' 2314 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2315 + _v2_versions_json() 2316 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2317 ) 2318 for line in malformed: 2319 var response = loads( 2320 handle_request_line_with_runtime_context_and_observer( 2321 line, runtime_context, observer 2322 ) 2323 ) 2324 assert_equal(response["ok"].bool_value(), False) 2325 assert_equal( 2326 response["error"]["code"].string_value(), "invalid_request" 2327 ) 2328 assert_equal(len(observer.attempts), 0) 2329 2330 # Positive control: an actual legacy dispatch records exactly one 2331 # attempt through the same seam, proving it observes the real call path. 2332 var legacy = ( 2333 '{"version":1,"request_id":"legacy-sentry",' 2334 '"capability":"farm_update.interpret","input":{' 2335 + _v2_farm_source_json() 2336 + "}}" 2337 ) 2338 var legacy_response = loads( 2339 handle_request_line_with_runtime_context_and_observer( 2340 legacy, runtime_context, observer 2341 ) 2342 ) 2343 assert_equal(legacy_response["ok"].bool_value(), True) 2344 assert_equal(len(observer.attempts), 1) 2345 assert_equal(observer.attempts[0], "farm_update.interpret") 2346 2347 2348 def test_c004_cr04_large_unknown_key_context_is_bounded() raises: 2349 # ADR-0026 D46 CR04 asks for large unknown-key contexts and field-count 2350 # edge cases: a 128-key unknown context must be rejected by the fixed 2351 # allowed-key set without an unbounded scan. 2352 var unknown = List[String]() 2353 for index in range(128): 2354 unknown.append('"unknown_' + String(index) + '":"x"') 2355 var large_unknown = _v2_farm_request_with_context( 2356 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 2357 + _v2_versions_json() 2358 + ',"actor_id":"farm-1","farm_id":"farm-1",' 2359 + ",".join(unknown) 2360 ) 2361 assert_true(_decode_error_message(large_unknown).find("unexpected") >= 0) 2362 2363 # A duplicated unknown key is rejected by the bounded seen-key scan. 2364 var duplicate_unknown = _v2_farm_request_with_context( 2365 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 2366 + _v2_versions_json() 2367 + ',"actor_id":"farm-1","farm_id":"farm-1",' 2368 + '"unknown_x":"a","unknown_x":"b"' 2369 ) 2370 var message = _decode_error_message(duplicate_unknown) 2371 assert_true( 2372 message.find("duplicate") >= 0 or message.find("unexpected") >= 0 2373 ) 2374 2375 2376 def test_c004_cr04_duplicate_version_input_and_trace_fields() raises: 2377 # CR04 requires every duplicate correlation/envelope field to fail, not only 2378 # capability/context: version, input, trace_id and request_id. 2379 var base = ( 2380 '{"version":1,"trace_id":"t1","request_id":"dup-fields",' 2381 '"capability":"farm_update.interpret",' 2382 '"context":{"evaluation_time":"2026-09-24T09:00:00-07:00",' 2383 + _v2_versions_json() 2384 + ',"actor_id":"farm-1","farm_id":"farm-1"},"input":{}}' 2385 ) 2386 var duplicate_trace = base.replace( 2387 '"trace_id":"t1"', '"trace_id":"t1","trace_id":"t2"' 2388 ) 2389 assert_true(_decode_error_message(duplicate_trace).find("duplicate") >= 0) 2390 2391 var duplicate_version = base.replace( 2392 '"version":1', '"version":1,"version":1' 2393 ) 2394 assert_true(_decode_error_message(duplicate_version).find("duplicate") >= 0) 2395 2396 var duplicate_input = base.replace('"input":{}', '"input":{},"input":{}') 2397 assert_true(_decode_error_message(duplicate_input).find("duplicate") >= 0) 2398 2399 var duplicate_request_id = base.replace( 2400 '"request_id":"dup-fields"', 2401 '"request_id":"dup-fields","request_id":"dup-fields-2"', 2402 ) 2403 assert_true( 2404 _decode_error_message(duplicate_request_id).find("duplicate") >= 0 2405 ) 2406 2407 2408 def test_c004_cr04_escaped_duplicate_matrix() raises: 2409 # ADR-0028 D48 EQ03 / ADR-0026 D46 CR04: decoded-key identity must catch an 2410 # escaped equivalent of every v2-targeting duplicate field, with equal and 2411 # conflicting values and both orders, through the real admission path. 2412 var v2_ctx = ( 2413 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 2414 + _v2_versions_json() 2415 + ',"actor_id":"farm-1","farm_id":"farm-1"' 2416 ) 2417 2418 # Escaped `context`, both orders (conflicting). 2419 var ctx_legacy_first = ( 2420 '{"version":1,"request_id":"esc-ctx-a",' 2421 '"capability":"farm_update.interpret",' 2422 '"context":{"consumer":"cli"},' 2423 '"\\u0063ontext":{' 2424 + v2_ctx 2425 + '},"input":{}}' 2426 ) 2427 assert_true(_decode_error_message(ctx_legacy_first).find("duplicate") >= 0) 2428 var ctx_v2_first = ( 2429 '{"version":1,"request_id":"esc-ctx-b",' 2430 '"capability":"buyer_request.interpret",' 2431 '"context":{' 2432 + v2_ctx 2433 + '},"\\u0063ontext":{"consumer":"cli"},"input":{}}' 2434 ) 2435 assert_true(_decode_error_message(ctx_v2_first).find("duplicate") >= 0) 2436 2437 # Escaped `request_id`, equal and conflicting, both orders. 2438 var rid_equal = ( 2439 '{"version":1,"request_id":"esc-rid-eq",' 2440 '"\\u0072equest_id":"esc-rid-eq",' 2441 '"capability":"farm_update.interpret","context":{' 2442 + v2_ctx 2443 + '},"input":{}}' 2444 ) 2445 assert_true(_decode_error_message(rid_equal).find("duplicate") >= 0) 2446 var rid_conflict = ( 2447 '{"version":1,"request_id":"esc-rid-a",' 2448 '"\\u0072equest_id":"esc-rid-b",' 2449 '"capability":"buyer_request.match","context":{' 2450 + v2_ctx 2451 + '},"input":{}}' 2452 ) 2453 assert_true(_decode_error_message(rid_conflict).find("duplicate") >= 0) 2454 var rid_conflict_reversed = ( 2455 '{"version":1,"\\u0072equest_id":"esc-rid-d",' 2456 '"request_id":"esc-rid-c",' 2457 '"capability":"buyer_request.interpret","context":{' 2458 + v2_ctx 2459 + '},"input":{}}' 2460 ) 2461 assert_true( 2462 _decode_error_message(rid_conflict_reversed).find("duplicate") >= 0 2463 ) 2464 2465 # Escaped `trace_id`, equal and conflicting, both orders. 2466 var tid_equal = ( 2467 '{"version":1,"request_id":"esc-tid-eq","trace_id":"esc-trace",' 2468 '"\\u0074race_id":"esc-trace",' 2469 '"capability":"farm_update.interpret","context":{' 2470 + v2_ctx 2471 + '},"input":{}}' 2472 ) 2473 assert_true(_decode_error_message(tid_equal).find("duplicate") >= 0) 2474 var tid_conflict_reversed = ( 2475 '{"version":1,"request_id":"esc-tid-b","\\u0074race_id":"esc-trace-b",' 2476 '"trace_id":"esc-trace-a",' 2477 '"capability":"buyer_request.match","context":{' 2478 + v2_ctx 2479 + '},"input":{}}' 2480 ) 2481 assert_true( 2482 _decode_error_message(tid_conflict_reversed).find("duplicate") >= 0 2483 ) 2484 2485 # Escaped `version` and `input`, both orders. 2486 var version_dup = ( 2487 '{"version":1,"\\u0076ersion":1,"request_id":"esc-ver",' 2488 '"capability":"farm_update.interpret","context":{' 2489 + v2_ctx 2490 + '},"input":{}}' 2491 ) 2492 assert_true(_decode_error_message(version_dup).find("duplicate") >= 0) 2493 var input_dup = ( 2494 '{"version":1,"request_id":"esc-input",' 2495 '"capability":"buyer_request.match","context":{' 2496 + v2_ctx 2497 + '},"input":{},"\\u0069nput":{}}' 2498 ) 2499 assert_true(_decode_error_message(input_dup).find("duplicate") >= 0) 2500 2501 # Negative control: a single correctly escaped key is not a false duplicate 2502 # and still decodes through the same admission path. 2503 var escaped_single = ( 2504 '{"version":1,"\\u0072equest_id":"esc-single-ok",' 2505 '"capability":"farm_update.interpret","context":{' 2506 + v2_ctx 2507 + '},"input":{}}' 2508 ) 2509 var decoded = decode_request(escaped_single) 2510 assert_equal(decoded.request_id, "esc-single-ok") 2511 assert_true(decoded.operation_context) 2512 2513 2514 def _c004_corr_envelope(fields: String) -> String: 2515 return ( 2516 '{"version":1,' 2517 + fields 2518 + ',"capability":"farm_update.interpret","input":{}}' 2519 ) 2520 2521 2522 def test_c004_cr04_correlation_duplicate_matrix() raises: 2523 # ADR-0029 D49 EV03 / ADR-0026 D46 CR04: the complete bounded 2524 # context/request_id/trace_id equal/conflicting x both-member-order matrix, 2525 # plain and escaped, through the real admission path, plus valid single-key 2526 # controls that must still decode. The envelope is v2-targeting through the 2527 # corrected capability, so the duplicate gate applies to every case. 2528 var v2_ctx = ( 2529 '"evaluation_time":"2026-09-24T09:00:00-07:00",' 2530 + _v2_versions_json() 2531 + ',"actor_id":"farm-1","farm_id":"farm-1"' 2532 ) 2533 var legacy_ctx = '{"consumer":"cli"}' 2534 var v2_obj = "{" + v2_ctx + "}" 2535 2536 var duplicates = List[String]() 2537 # request_id: equal/conflicting, plain and escaped, both orders. 2538 duplicates.append( 2539 _c004_corr_envelope('"request_id":"rid-a","request_id":"rid-a"') 2540 ) 2541 duplicates.append( 2542 _c004_corr_envelope('"request_id":"rid-a","request_id":"rid-b"') 2543 ) 2544 duplicates.append( 2545 _c004_corr_envelope('"request_id":"rid-c","\\u0072equest_id":"rid-c"') 2546 ) 2547 duplicates.append( 2548 _c004_corr_envelope('"\\u0072equest_id":"rid-d","request_id":"rid-d"') 2549 ) 2550 duplicates.append( 2551 _c004_corr_envelope('"request_id":"rid-e","\\u0072equest_id":"rid-f"') 2552 ) 2553 duplicates.append( 2554 _c004_corr_envelope('"\\u0072equest_id":"rid-g","request_id":"rid-h"') 2555 ) 2556 # trace_id: equal/conflicting, plain and escaped, both orders. 2557 duplicates.append( 2558 _c004_corr_envelope( 2559 '"request_id":"tid-1","trace_id":"t-a","trace_id":"t-a"' 2560 ) 2561 ) 2562 duplicates.append( 2563 _c004_corr_envelope( 2564 '"request_id":"tid-2","trace_id":"t-a","trace_id":"t-b"' 2565 ) 2566 ) 2567 duplicates.append( 2568 _c004_corr_envelope( 2569 '"request_id":"tid-3","trace_id":"t-c","\\u0074race_id":"t-c"' 2570 ) 2571 ) 2572 duplicates.append( 2573 _c004_corr_envelope( 2574 '"request_id":"tid-4","\\u0074race_id":"t-d","trace_id":"t-d"' 2575 ) 2576 ) 2577 duplicates.append( 2578 _c004_corr_envelope( 2579 '"request_id":"tid-5","trace_id":"t-e","\\u0074race_id":"t-f"' 2580 ) 2581 ) 2582 duplicates.append( 2583 _c004_corr_envelope( 2584 '"request_id":"tid-6","\\u0074race_id":"t-g","trace_id":"t-h"' 2585 ) 2586 ) 2587 # context: equal/conflicting, plain and escaped, both orders. 2588 duplicates.append( 2589 _c004_corr_envelope( 2590 '"request_id":"ctx-1","context":' 2591 + legacy_ctx 2592 + ',"context":' 2593 + v2_obj 2594 ) 2595 ) 2596 duplicates.append( 2597 _c004_corr_envelope( 2598 '"request_id":"ctx-2","context":' 2599 + v2_obj 2600 + ',"context":' 2601 + legacy_ctx 2602 ) 2603 ) 2604 duplicates.append( 2605 _c004_corr_envelope( 2606 '"request_id":"ctx-3","context":' + v2_obj + ',"context":' + v2_obj 2607 ) 2608 ) 2609 duplicates.append( 2610 _c004_corr_envelope( 2611 '"request_id":"ctx-4","context":' 2612 + legacy_ctx 2613 + ',"\\u0063ontext":' 2614 + v2_obj 2615 ) 2616 ) 2617 duplicates.append( 2618 _c004_corr_envelope( 2619 '"request_id":"ctx-5","context":' 2620 + v2_obj 2621 + ',"\\u0063ontext":' 2622 + legacy_ctx 2623 ) 2624 ) 2625 duplicates.append( 2626 _c004_corr_envelope( 2627 '"request_id":"ctx-6","context":' 2628 + v2_obj 2629 + ',"\\u0063ontext":' 2630 + v2_obj 2631 ) 2632 ) 2633 # context: escaped-first equal/conflicting (ADR-0030 D50 EC02 completes the 2634 # missing escaped-context-first cells; the escaped key leads both orders). 2635 duplicates.append( 2636 _c004_corr_envelope( 2637 '"request_id":"ctx-7","\\u0063ontext":' 2638 + v2_obj 2639 + ',"context":' 2640 + v2_obj 2641 ) 2642 ) 2643 duplicates.append( 2644 _c004_corr_envelope( 2645 '"request_id":"ctx-8","\\u0063ontext":' 2646 + v2_obj 2647 + ',"context":' 2648 + legacy_ctx 2649 ) 2650 ) 2651 duplicates.append( 2652 _c004_corr_envelope( 2653 '"request_id":"ctx-9","\\u0063ontext":' 2654 + legacy_ctx 2655 + ',"context":' 2656 + v2_obj 2657 ) 2658 ) 2659 2660 for line in duplicates: 2661 var message = _decode_error_message(line) 2662 assert_true(message.find("duplicate") >= 0, message) 2663 2664 # Valid single-key controls must decode through the same admission path. 2665 var single_plain = decode_request( 2666 _c004_corr_envelope('"request_id":"single-plain"') 2667 ) 2668 assert_equal(single_plain.request_id, "single-plain") 2669 2670 var single_escaped_rid = decode_request( 2671 _c004_corr_envelope('"\\u0072equest_id":"single-esc-rid"') 2672 ) 2673 assert_equal(single_escaped_rid.request_id, "single-esc-rid") 2674 2675 var single_trace = decode_request( 2676 _c004_corr_envelope('"request_id":"single-trace","trace_id":"t-single"') 2677 ) 2678 assert_equal(single_trace.trace_id.value(), "t-single") 2679 2680 var single_escaped_trace = decode_request( 2681 _c004_corr_envelope( 2682 '"request_id":"single-esc-trace","\\u0074race_id":"t-esc"' 2683 ) 2684 ) 2685 assert_equal(single_escaped_trace.trace_id.value(), "t-esc") 2686 2687 var single_context = decode_request( 2688 _c004_corr_envelope('"request_id":"single-ctx","context":' + v2_obj) 2689 ) 2690 assert_true(single_context.operation_context) 2691 2692 var single_escaped_context = decode_request( 2693 _c004_corr_envelope( 2694 '"request_id":"single-esc-ctx","\\u0063ontext":' + v2_obj 2695 ) 2696 ) 2697 assert_true(single_escaped_context.operation_context)