返回 CodeWhale
exact_fleet_workflow.rs
根目录 / crates / workflow / tests / exact_fleet_workflow.rs
1 //! End-to-end vertical for an exact named Fleet at the crate boundary:
2 //! parse → attach a reusable Reasoning Router → freeze routes → router decision
3 //! → reasoning resolution → immutable Workflow snapshot.
4 //!
5 //! No live provider calls: the router's response is a fixture string.
6
7 use codewhale_workflow::{
8 CapturedReasoningRouter, CredentialReadiness, EffectiveReasoning, EffectiveReasoningSource,
9 EndpointIdentity, FleetDocument, FleetSearchRoot, FleetSnapshot, NamedFleetError,
10 PermissionCeiling, PreflightedRoute, ProviderEffectiveReasoning, QualifiedFleetId,
11 REASONING_ROUTER_DIR, REASONING_ROUTER_SERVICE_KIND, ReasoningCapability, ReasoningRouterError,
12 ReasoningRouterProfile, ReasoningTier, RequestedReasoning, RouterAvailability,
13 RouterCallReasoning, RouterIdentity, ShellCeiling, bounded_routing_payload,
14 parse_router_decision, resolve_exact_member_reasoning, router_call_plan, router_system_prompt,
15 router_user_message,
16 };
17
18 const GLM_FLEET: &str = r#"
19 name = "glm-pair"
20 description = "GLM workers with a shared GPT-5.6 Luna reasoning router"
21 schema = "exact"
22 schema_revision = 1
23 reasoning_router = "luna-low"
24
25 [[members]]
26 id = "implementer"
27 role = "builder"
28 provider = "zai"
29 model = "glm-5"
30 reasoning = "auto"
31 permissions = "read_write"
32
33 [[members]]
34 id = "auditor"
35 role = "reviewer"
36 provider = "zai"
37 model = "glm-5"
38 reasoning = "high"
39 permissions = "read_only"
40 "#;
41
42 /// The user's example: GPT-5.6 Luna, called at `low`.
43 const LUNA: &str = r#"
44 name = "luna-low"
45 schema = "reasoning_router"
46 schema_revision = 1
47 provider = "openai"
48 model = "gpt-5.6-luna"
49 call_reasoning = "low"
50 "#;
51
52 fn fleet_id(name: &str) -> QualifiedFleetId {
53 QualifiedFleetId {
54 name: name.to_string(),
55 origin: "workspace".to_string(),
56 }
57 }
58
59 fn luna() -> CapturedReasoningRouter {
60 let profile = ReasoningRouterProfile::parse(LUNA).expect("router profile");
61 CapturedReasoningRouter::from_profile(&profile, "workspace")
62 }
63
64 fn route(member: &str, provider: &str, model: &str) -> PreflightedRoute {
65 PreflightedRoute {
66 member_id: member.to_string(),
67 provider_id: provider.to_string(),
68 provider_kind: provider.to_string(),
69 declared_model: model.to_string(),
70 wire_model: model.to_string(),
71 endpoint: EndpointIdentity::from_base_url("https://api.example.test/v1"),
72 credential: CredentialReadiness::Configured,
73 capability: ReasoningCapability::tiered(),
74 }
75 }
76
77 /// A workspace holding one Fleet and one Router profile, plus its search roots.
78 fn workspace_with(fleet: &str, router: Option<&str>) -> (tempfile::TempDir, Vec<FleetSearchRoot>) {
79 let tmp = tempfile::tempdir().expect("tmp");
80 std::fs::create_dir_all(tmp.path().join("fleets")).expect("fleets dir");
81 std::fs::write(tmp.path().join("fleets/glm-pair.toml"), fleet).expect("fleet");
82 if let Some(router) = router {
83 std::fs::create_dir_all(tmp.path().join(REASONING_ROUTER_DIR)).expect("routers dir");
84 std::fs::write(
85 tmp.path().join(REASONING_ROUTER_DIR).join("luna-low.toml"),
86 router,
87 )
88 .expect("router");
89 }
90 let roots = vec![FleetSearchRoot::new("workspace", tmp.path())];
91 (tmp, roots)
92 }
93
94 #[test]
95 fn a_fleet_and_its_referenced_router_resolve_reasoning_without_moving_the_route() {
96 let (_tmp, roots) = workspace_with(GLM_FLEET, Some(LUNA));
97 let (document, id) = FleetDocument::load_by_name("glm-pair", &roots).expect("fleet loads");
98 let exact = document.exact().expect("exact");
99
100 // The Router is a *reference* to a separately saved service.
101 assert_eq!(exact.reasoning_router.as_deref(), Some("luna-low"));
102 assert!(exact.legacy_inline_router().is_none());
103
104 let (profile, router_id) =
105 ReasoningRouterProfile::load_by_name("luna-low", &roots).expect("router loads");
106 assert_eq!(router_id.qualified(), "workspace/luna-low");
107 let captured = CapturedReasoningRouter::from_profile(&profile, router_id.origin);
108
109 let snapshot = FleetSnapshot::capture(id, &document, "2026-07-26T00:00:00Z", Some(captured))
110 .expect("capture");
111
112 // Routes are frozen from the snapshot, before any reasoning resolution.
113 let member = snapshot.member("implementer").expect("member");
114 let frozen = member.route.clone();
115 assert_eq!(frozen.provider, "zai");
116 assert_eq!(frozen.model, "glm-5");
117
118 // The Router is a non-dispatchable service with no authority.
119 let router = snapshot.router().expect("router service");
120 assert_eq!(router.service_kind, REASONING_ROUTER_SERVICE_KIND);
121 assert_eq!(router.route.model, "gpt-5.6-luna");
122 assert_eq!(router.requested_call_reasoning, RouterCallReasoning::Low);
123 assert!(!router.dispatchable);
124 assert!(!router.permissions.tools);
125
126 let decision = parse_router_decision(
127 r#"```json
128 {"reasoning":"max"}
129 ```"#,
130 )
131 .expect("router decision parses");
132
133 let identity = RouterIdentity::from_captured(
134 router,
135 Some(&route("router", "openai", "gpt-5.6-luna")),
136 Some(
137 router_call_plan(
138 router.requested_call_reasoning,
139 &ReasoningCapability::tiered(),
140 )
141 .disclosure,
142 ),
143 );
144
145 let resolved = resolve_exact_member_reasoning(
146 &member.id,
147 &frozen,
148 member.requested_reasoning,
149 &ReasoningCapability::tiered(),
150 &RouterAvailability::Ready,
151 Some(&decision),
152 Some(&identity),
153 )
154 .expect("ready router resolves auto");
155
156 assert_eq!(resolved.requested(), RequestedReasoning::Auto);
157 assert_eq!(
158 resolved.effective(),
159 EffectiveReasoning::Tier(ReasoningTier::Max)
160 );
161 assert_eq!(resolved.source(), EffectiveReasoningSource::FleetRouter);
162
163 // The router's own call ran at the configured `low`, and says so.
164 let call = resolved
165 .router()
166 .expect("router identity")
167 .call
168 .as_ref()
169 .expect("call disclosure");
170 assert_eq!(call.requested, "low");
171 assert_eq!(call.effective, "low");
172
173 // The worker's provider/model did not move.
174 assert_eq!(snapshot.member("implementer").unwrap().route, frozen);
175 }
176
177 /// One saved Router profile, referenced by two different Fleets.
178 #[test]
179 fn one_router_profile_serves_two_fleets() {
180 let tmp = tempfile::tempdir().expect("tmp");
181 std::fs::create_dir_all(tmp.path().join("fleets")).expect("fleets dir");
182 std::fs::create_dir_all(tmp.path().join(REASONING_ROUTER_DIR)).expect("routers dir");
183 std::fs::write(
184 tmp.path().join(REASONING_ROUTER_DIR).join("luna-low.toml"),
185 LUNA,
186 )
187 .expect("router");
188 std::fs::write(tmp.path().join("fleets/glm-pair.toml"), GLM_FLEET).expect("first");
189 std::fs::write(
190 tmp.path().join("fleets/glm-solo.toml"),
191 GLM_FLEET.replace("name = \"glm-pair\"", "name = \"glm-solo\""),
192 )
193 .expect("second");
194 let roots = vec![FleetSearchRoot::new("workspace", tmp.path())];
195
196 let mut snapshots = Vec::new();
197 for name in ["glm-pair", "glm-solo"] {
198 let (document, id) = FleetDocument::load_by_name(name, &roots).expect("fleet loads");
199 let reference = document
200 .exact()
201 .expect("exact")
202 .reasoning_router
203 .clone()
204 .expect("router reference");
205 let (profile, router_id) =
206 ReasoningRouterProfile::load_by_name(&reference, &roots).expect("router loads");
207 snapshots.push(
208 FleetSnapshot::capture(
209 id,
210 &document,
211 "2026-07-26T00:00:00Z",
212 Some(CapturedReasoningRouter::from_profile(
213 &profile,
214 router_id.origin,
215 )),
216 )
217 .expect("capture"),
218 );
219 }
220
221 assert_eq!(
222 snapshots[0].router(),
223 snapshots[1].router(),
224 "both fleets attach the identical captured router service"
225 );
226 assert_ne!(snapshots[0].fleet(), snapshots[1].fleet());
227 assert_eq!(
228 snapshots[0].router().expect("router").qualified(),
229 "workspace/luna-low"
230 );
231 }
232
233 /// A bare Router name defined in two origins is ambiguous; a qualified origin
234 /// resolves it. Shadowing would silently change which provider sees every
235 /// routing summary.
236 #[test]
237 fn a_router_defined_in_two_origins_is_ambiguous_until_qualified() {
238 let tmp = tempfile::tempdir().expect("tmp");
239 let home = tmp.path().join("home");
240 let workspace = tmp.path().join("workspace");
241 for root in [&home, &workspace] {
242 std::fs::create_dir_all(root.join(REASONING_ROUTER_DIR)).expect("routers dir");
243 }
244 std::fs::write(
245 home.join(REASONING_ROUTER_DIR).join("luna-low.toml"),
246 LUNA.replace("gpt-5.6-luna", "gpt-5.6-luna-mini"),
247 )
248 .expect("home");
249 std::fs::write(
250 workspace.join(REASONING_ROUTER_DIR).join("luna-low.toml"),
251 LUNA,
252 )
253 .expect("workspace");
254
255 let roots = vec![
256 FleetSearchRoot::new("codewhale_home", &home),
257 FleetSearchRoot::new("workspace", &workspace),
258 ];
259
260 let err = ReasoningRouterProfile::load_by_name("luna-low", &roots)
261 .expect_err("a bare name must not be resolved by shadowing");
262 assert!(
263 matches!(err, ReasoningRouterError::AmbiguousRouter { .. }),
264 "{err:?}"
265 );
266
267 assert_eq!(
268 ReasoningRouterProfile::load_by_name("workspace/luna-low", &roots)
269 .expect("qualified")
270 .0
271 .model,
272 "gpt-5.6-luna"
273 );
274 assert_eq!(
275 ReasoningRouterProfile::load_by_name("codewhale_home/luna-low", &roots)
276 .expect("qualified")
277 .0
278 .model,
279 "gpt-5.6-luna-mini"
280 );
281 }
282
283 /// A Router may only run at `off` or `low`. `medium`/`high`/`max` are rejected,
284 /// not silently clamped — the operator must see that their setting was refused.
285 #[test]
286 fn an_expensive_router_call_tier_is_rejected_rather_than_clamped() {
287 for value in ["medium", "high", "max"] {
288 let text = LUNA.replace("\"low\"", &format!("\"{value}\""));
289 let err = ReasoningRouterProfile::parse(&text).expect_err("expensive tier");
290 assert!(
291 matches!(err, ReasoningRouterError::CallReasoningTooExpensive { .. }),
292 "value={value} err={err:?}"
293 );
294 }
295
296 // And `low` is honored end to end, never forced to `off` behind the label.
297 let profile = ReasoningRouterProfile::parse(LUNA).expect("parse");
298 let plan = router_call_plan(profile.call_reasoning, &ReasoningCapability::tiered());
299 assert_eq!(plan.tier, ReasoningTier::Low);
300 assert_eq!(plan.disclosure.effective, "low");
301 assert_eq!(plan.disclosure.provider_effective, "low");
302 }
303
304 /// A manual tier consults no Router at all.
305 #[test]
306 fn a_non_auto_member_never_consults_the_router() {
307 let document = FleetDocument::parse(GLM_FLEET).expect("parse");
308 let exact = document.exact().expect("exact");
309 let auditor = exact.member("auditor").expect("auditor");
310
311 let resolved = resolve_exact_member_reasoning(
312 &auditor.id,
313 &auditor.frozen_route(),
314 auditor.reasoning,
315 &ReasoningCapability::tiered(),
316 // Deliberately absent — an explicit tier must not need a router.
317 &RouterAvailability::Absent,
318 None,
319 None,
320 )
321 .expect("explicit tier resolves");
322
323 assert_eq!(
324 resolved.effective(),
325 EffectiveReasoning::Tier(ReasoningTier::High)
326 );
327 assert_eq!(resolved.source(), EffectiveReasoningSource::MemberExplicit);
328 assert!(resolved.router().is_none(), "no router was involved");
329 }
330
331 #[test]
332 fn an_auto_member_in_a_router_less_fleet_fails_before_work_starts() {
333 let router_less = GLM_FLEET.replace("reasoning_router = \"luna-low\"\n", "");
334 let document = FleetDocument::parse(&router_less).expect("parse");
335 let exact = document.exact().expect("exact");
336 assert!(exact.router_ref().is_none());
337
338 let member = exact.member("implementer").expect("member");
339 let err = resolve_exact_member_reasoning(
340 &member.id,
341 &member.frozen_route(),
342 member.reasoning,
343 &ReasoningCapability::tiered(),
344 &RouterAvailability::Absent,
345 None,
346 None,
347 )
348 .expect_err("auto without a router must fail closed");
349
350 let message = err.to_string();
351 assert!(message.contains("implementer"), "{message}");
352 assert!(message.contains("reasoning_router"), "{message}");
353 }
354
355 /// A Fleet that references a Router profile which is not installed cannot be
356 /// resolved — decided locally, with no provider contacted.
357 #[test]
358 fn a_missing_router_profile_is_a_local_load_failure() {
359 let (_tmp, roots) = workspace_with(GLM_FLEET, None);
360 let (document, _id) = FleetDocument::load_by_name("glm-pair", &roots).expect("fleet loads");
361 let reference = document
362 .exact()
363 .expect("exact")
364 .reasoning_router
365 .clone()
366 .expect("reference");
367
368 assert!(matches!(
369 ReasoningRouterProfile::load_by_name(&reference, &roots).expect_err("missing"),
370 ReasoningRouterError::NotFound { .. }
371 ));
372 }
373
374 #[test]
375 fn member_ceilings_clamp_against_a_read_only_session_posture() {
376 let document = FleetDocument::parse(GLM_FLEET).expect("parse");
377 let snapshot = FleetSnapshot::capture(
378 fleet_id("glm-pair"),
379 &document,
380 "2026-07-26T00:00:00Z",
381 Some(luna()),
382 )
383 .expect("capture");
384
385 let session = PermissionCeiling {
386 write: false,
387 network_tool: false,
388 shell: ShellCeiling::ReadOnly,
389 delegation_depth: 0,
390 tools: true,
391 };
392
393 let implementer = snapshot.member("implementer").expect("member");
394 assert!(
395 implementer.permissions.write,
396 "the saved ceiling allows writes"
397 );
398
399 let effective = implementer.permissions.clamp_to(session);
400 assert!(
401 !effective.write,
402 "a saved fleet must never raise the active session posture"
403 );
404 assert_eq!(effective.shell, ShellCeiling::ReadOnly);
405 }
406
407 /// The bounded routing summary is transmitted exactly once, and the receipt's
408 /// count and hash describe exactly those bytes.
409 #[test]
410 fn the_routing_summary_is_transmitted_once_and_disclosed_without_content() {
411 let payload = bounded_routing_payload("refactor the parser in /Users/hunter/app");
412 let disclosure = payload.disclosure().clone();
413 let input = codewhale_workflow::RouterCallInput {
414 fleet: "workspace/glm-pair".to_string(),
415 member_id: "implementer".to_string(),
416 frozen: codewhale_workflow::FrozenRoute {
417 provider: "zai".to_string(),
418 model: "glm-5".to_string(),
419 },
420 payload,
421 };
422
423 let system = router_system_prompt(&input);
424 let user = router_user_message(&input);
425
426 assert!(!system.contains("refactor the parser"), "{system}");
427 assert!(!user.contains("/Users/"), "paths are redacted: {user}");
428 // The disclosed count and hash describe exactly the bytes that were sent —
429 // and the summary appears exactly once across the whole request.
430 assert_eq!(disclosure.transmitted_bytes, user.len());
431 assert_eq!(disclosure.transmitted_chars, user.chars().count());
432 assert_eq!(
433 format!("{system}\n{user}").matches(user.as_str()).count(),
434 1,
435 "the bounded summary must be transmitted once, not duplicated"
436 );
437 assert!(disclosure.redacted);
438 assert!(disclosure.redactions.contains(&"absolute_path".to_string()));
439 }
440
441 /// Legacy role-map fleets keep loading through the same store.
442 #[test]
443 fn legacy_fleet_files_still_load_through_the_same_store() {
444 let root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
445 .join("..")
446 .join("..");
447 let (document, id) =
448 FleetDocument::load_by_name("stopship", &[FleetSearchRoot::new("workspace", root)])
449 .expect("workspace legacy fleet loads");
450
451 assert!(document.is_legacy());
452 assert_eq!(document.schema_kind(), "legacy");
453 assert_eq!(id.qualified(), "workspace/stopship");
454 let legacy = document.legacy().expect("legacy body");
455 legacy.validate_stopship_roles().expect("required roles");
456 assert_eq!(legacy.resolve("release_lead").unwrap(), "manager");
457 }
458
459 /// A personal `~/.codewhale` Fleet must not silently shadow — or be shadowed
460 /// by — a project Fleet of the same name.
461 #[test]
462 fn an_exact_fleet_defined_in_two_origins_is_ambiguous_until_qualified() {
463 let tmp = tempfile::tempdir().expect("tmp");
464 let home = tmp.path().join("home");
465 let workspace = tmp.path().join("workspace");
466 for root in [&home, &workspace] {
467 std::fs::create_dir_all(root.join("fleets")).expect("fleets dir");
468 }
469 std::fs::write(
470 home.join("fleets/glm-pair.toml"),
471 GLM_FLEET.replace("model = \"glm-5\"", "model = \"glm-4\""),
472 )
473 .expect("home fleet");
474 std::fs::write(workspace.join("fleets/glm-pair.toml"), GLM_FLEET).expect("workspace fleet");
475
476 let roots = vec![
477 FleetSearchRoot::new("codewhale_home", &home),
478 FleetSearchRoot::new("workspace", &workspace),
479 ];
480
481 let err = FleetDocument::load_by_name("glm-pair", &roots)
482 .expect_err("an exact fleet must not be resolved by shadowing");
483 assert!(
484 matches!(err, NamedFleetError::AmbiguousFleet { .. }),
485 "{err:?}"
486 );
487
488 let (document, id) =
489 FleetDocument::load_by_name("workspace/glm-pair", &roots).expect("qualified load");
490 assert_eq!(id.qualified(), "workspace/glm-pair");
491 assert_eq!(
492 document
493 .exact()
494 .expect("exact")
495 .member("implementer")
496 .expect("member")
497 .model,
498 "glm-5"
499 );
500
501 let (home_document, home_id) =
502 FleetDocument::load_by_name("codewhale_home/glm-pair", &roots).expect("qualified load");
503 assert_eq!(home_id.qualified(), "codewhale_home/glm-pair");
504 assert_eq!(
505 home_document
506 .exact()
507 .expect("exact")
508 .member("implementer")
509 .expect("member")
510 .model,
511 "glm-4"
512 );
513 }
514
515 /// Legacy role maps keep their historic first-hit-wins behavior: a role map
516 /// resolves through the same profile store from either origin.
517 #[test]
518 fn legacy_fleets_in_two_origins_keep_first_hit_wins() {
519 let tmp = tempfile::tempdir().expect("tmp");
520 let home = tmp.path().join("home");
521 let workspace = tmp.path().join("workspace");
522 for root in [&home, &workspace] {
523 std::fs::create_dir_all(root.join("fleets")).expect("fleets dir");
524 }
525 std::fs::write(
526 home.join("fleets/pair.toml"),
527 "name = \"pair\"\n\n[roles]\nscout = \"home-scout\"\n",
528 )
529 .expect("home fleet");
530 std::fs::write(
531 workspace.join("fleets/pair.toml"),
532 "name = \"pair\"\n\n[roles]\nscout = \"workspace-scout\"\n",
533 )
534 .expect("workspace fleet");
535
536 let (document, id) = FleetDocument::load_by_name(
537 "pair",
538 &[
539 FleetSearchRoot::new("codewhale_home", &home),
540 FleetSearchRoot::new("workspace", &workspace),
541 ],
542 )
543 .expect("legacy collisions stay resolvable");
544
545 assert!(document.is_legacy());
546 assert_eq!(id.origin, "codewhale_home");
547 assert_eq!(
548 document.legacy().expect("legacy").resolve("scout").unwrap(),
549 "home-scout"
550 );
551 }
552
553 /// A broken file in a *shadowed* origin must not fail a legacy load that has
554 /// always worked.
555 #[test]
556 fn a_malformed_shadowed_sibling_does_not_regress_legacy_first_hit() {
557 let tmp = tempfile::tempdir().expect("tmp");
558 let home = tmp.path().join("home");
559 let workspace = tmp.path().join("workspace");
560 for root in [&home, &workspace] {
561 std::fs::create_dir_all(root.join("fleets")).expect("fleets dir");
562 }
563 std::fs::write(
564 home.join("fleets/pair.toml"),
565 "name = \"pair\"\n\n[roles]\nscout = \"home-scout\"\n",
566 )
567 .expect("home fleet");
568 std::fs::write(
569 workspace.join("fleets/pair.toml"),
570 "name = \"pair\"\n[roles\nscout = = = \"\"\"broken\n",
571 )
572 .expect("workspace fleet");
573
574 let (document, id) = FleetDocument::load_by_name(
575 "pair",
576 &[
577 FleetSearchRoot::new("codewhale_home", &home),
578 FleetSearchRoot::new("workspace", &workspace),
579 ],
580 )
581 .expect("a broken shadowed sibling must not break first-hit-wins");
582
583 assert_eq!(id.origin, "codewhale_home");
584 assert_eq!(
585 document.legacy().expect("legacy").resolve("scout").unwrap(),
586 "home-scout"
587 );
588 }
589
590 /// Roster invariants hold at the crate boundary, not just inside the parser.
591 #[test]
592 fn duplicate_roles_and_reserved_router_identities_are_rejected_at_load() {
593 let duplicate_role = GLM_FLEET.replace("role = \"reviewer\"", "role = \"builder\"");
594 assert!(
595 FleetDocument::parse(&duplicate_role).is_err(),
596 "two members must not share the role `builder`"
597 );
598
599 let worker_router = GLM_FLEET.replace("role = \"reviewer\"", "role = \"router\"");
600 assert!(
601 FleetDocument::parse(&worker_router).is_err(),
602 "a worker must not claim the reserved role `router`"
603 );
604 }
605
606 /// The legacy inline Router form still parses and normalizes into the same
607 /// captured service — one runtime representation, whichever way it was written.
608 #[test]
609 fn a_legacy_inline_router_still_works_and_normalizes() {
610 let inline = format!(
611 "{}\n[[members]]\nid = \"router\"\nkind = \"router\"\nprovider = \"zai\"\nmodel = \
612 \"glm-5-turbo\"\n",
613 GLM_FLEET.replace("reasoning_router = \"luna-low\"\n", "")
614 );
615 let document = FleetDocument::parse(&inline).expect("legacy inline parses");
616 let exact = document.exact().expect("exact");
617 let captured = codewhale_workflow::captured_legacy_inline_router(exact).expect("inline router");
618
619 assert!(captured.legacy_inline);
620 assert_eq!(captured.service_kind, REASONING_ROUTER_SERVICE_KIND);
621 assert_eq!(captured.route.model, "glm-5-turbo");
622 assert_eq!(captured.requested_call_reasoning, RouterCallReasoning::Off);
623 assert!(!captured.is_dispatchable());
624
625 let snapshot = FleetSnapshot::capture(
626 fleet_id("glm-pair"),
627 &document,
628 "2026-07-26T00:00:00Z",
629 Some(captured),
630 )
631 .expect("capture");
632 assert!(snapshot.member("router").is_none());
633 assert_eq!(snapshot.members().len(), 2);
634 }
635
636 /// The provider-effective control is reported separately from the selector
637 /// tier: a Z.AI GLM route expresses only thinking on/off, so `high` and `max`
638 /// must not be presented as two distinct provider-effective tiers.
639 #[test]
640 fn glm_receipts_do_not_invent_distinct_high_and_max_provider_tiers() {
641 let document = FleetDocument::parse(GLM_FLEET).expect("parse");
642 let exact = document.exact().expect("exact");
643 let auditor = exact.member("auditor").expect("auditor");
644 let glm = ReasoningCapability::enabled_disabled();
645
646 let high = resolve_exact_member_reasoning(
647 &auditor.id,
648 &auditor.frozen_route(),
649 RequestedReasoning::High,
650 &glm,
651 &RouterAvailability::Absent,
652 None,
653 None,
654 )
655 .expect("resolve");
656 let max = resolve_exact_member_reasoning(
657 &auditor.id,
658 &auditor.frozen_route(),
659 RequestedReasoning::Max,
660 &glm,
661 &RouterAvailability::Absent,
662 None,
663 None,
664 )
665 .expect("resolve");
666
667 assert_eq!(
668 high.provider_effective(),
669 ProviderEffectiveReasoning::Enabled
670 );
671 assert_eq!(
672 max.provider_effective(),
673 ProviderEffectiveReasoning::Enabled
674 );
675 assert_ne!(high.effective(), max.effective());
676 }
677
677 lines RUST