@miller-tech/uap 1.213.0 → 1.215.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/bin/cli.js +2 -0
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/cli/deliver.d.ts +66 -0
  5. package/dist/cli/deliver.d.ts.map +1 -1
  6. package/dist/cli/deliver.js +227 -7
  7. package/dist/cli/deliver.js.map +1 -1
  8. package/dist/cli/verify.d.ts +5 -0
  9. package/dist/cli/verify.d.ts.map +1 -1
  10. package/dist/cli/verify.js +50 -1
  11. package/dist/cli/verify.js.map +1 -1
  12. package/dist/cli/wizard-config.d.ts.map +1 -1
  13. package/dist/cli/wizard-config.js +26 -1
  14. package/dist/cli/wizard-config.js.map +1 -1
  15. package/dist/delivery/await-run.d.ts +47 -0
  16. package/dist/delivery/await-run.d.ts.map +1 -1
  17. package/dist/delivery/await-run.js +392 -2
  18. package/dist/delivery/await-run.js.map +1 -1
  19. package/dist/delivery/capability-profile.d.ts +124 -0
  20. package/dist/delivery/capability-profile.d.ts.map +1 -0
  21. package/dist/delivery/capability-profile.js +392 -0
  22. package/dist/delivery/capability-profile.js.map +1 -0
  23. package/dist/delivery/convergence-loop.d.ts +38 -0
  24. package/dist/delivery/convergence-loop.d.ts.map +1 -1
  25. package/dist/delivery/convergence-loop.js +98 -1
  26. package/dist/delivery/convergence-loop.js.map +1 -1
  27. package/dist/delivery/epic-controller.d.ts +9 -0
  28. package/dist/delivery/epic-controller.d.ts.map +1 -1
  29. package/dist/delivery/epic-controller.js +1 -0
  30. package/dist/delivery/epic-controller.js.map +1 -1
  31. package/dist/delivery/epic-mission.d.ts +10 -2
  32. package/dist/delivery/epic-mission.d.ts.map +1 -1
  33. package/dist/delivery/epic-mission.js +1 -1
  34. package/dist/delivery/epic-mission.js.map +1 -1
  35. package/dist/delivery/escalation.d.ts +8 -0
  36. package/dist/delivery/escalation.d.ts.map +1 -1
  37. package/dist/delivery/escalation.js +8 -1
  38. package/dist/delivery/escalation.js.map +1 -1
  39. package/dist/delivery/execution-gate.d.ts +29 -0
  40. package/dist/delivery/execution-gate.d.ts.map +1 -1
  41. package/dist/delivery/execution-gate.js +237 -9
  42. package/dist/delivery/execution-gate.js.map +1 -1
  43. package/dist/delivery/mission-acceptance.d.ts +4 -0
  44. package/dist/delivery/mission-acceptance.d.ts.map +1 -1
  45. package/dist/delivery/mission-acceptance.js +35 -1
  46. package/dist/delivery/mission-acceptance.js.map +1 -1
  47. package/dist/delivery/run-state.d.ts +31 -0
  48. package/dist/delivery/run-state.d.ts.map +1 -1
  49. package/dist/delivery/run-state.js +49 -0
  50. package/dist/delivery/run-state.js.map +1 -1
  51. package/dist/mcp-router/tools/deliver.d.ts.map +1 -1
  52. package/dist/mcp-router/tools/deliver.js +5 -2
  53. package/dist/mcp-router/tools/deliver.js.map +1 -1
  54. package/package.json +1 -1
  55. package/scripts/lib/llama-upstream.sh +64 -16
  56. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  57. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  58. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
  59. package/tools/agents/scripts/confidence_escalation.py +57 -0
  60. package/tools/agents/tests/test_confidence_escalation.py +140 -2
@@ -1,6 +1,7 @@
1
1
  """Tests for the serving-layer recipe runtime (Confidence #1/#5, Fusion #3, selector #2)."""
2
2
  import asyncio
3
3
  import importlib.util
4
+ import os
4
5
  import sys
5
6
  import unittest
6
7
  from pathlib import Path
@@ -24,10 +25,16 @@ spec.loader.exec_module(ce)
24
25
 
25
26
 
26
27
  def S(enabled=True, recipe="auto", signal="heuristic", threshold=0.5, fusion_n=3,
27
- auto_chars=600, model="opus", endpoint="http://x/", key="k", remom_quorum=2):
28
+ auto_chars=600, model="opus", endpoint="http://x/", key="k", remom_quorum=2,
29
+ model_slots=None, force_multi_call=False):
30
+ # model_slots defaults to None = UNKNOWN width, which changes nothing. The
31
+ # selector reads this FIELD, never process env, so an ambient
32
+ # UAP_MODEL_SLOTS=1 (what proxy.env now carries on a one-slot box) cannot
33
+ # rewrite the expectations of tests that are not about slot width.
28
34
  return ce.Settings(enabled=enabled, recipe=recipe, signal=signal, threshold=threshold,
29
35
  fusion_n=fusion_n, remom_quorum=remom_quorum, auto_fusion_chars=auto_chars,
30
- model=model, endpoint=endpoint, api_key=key)
36
+ model=model, endpoint=endpoint, api_key=key,
37
+ model_slots=model_slots, force_multi_call=force_multi_call)
31
38
 
32
39
 
33
40
  def resp(text):
@@ -351,5 +358,136 @@ class AdaptationSignalTest(unittest.TestCase): # LLM-Self-Tuning real-time adap
351
358
  )
352
359
 
353
360
 
361
+ class SlotRightSizingTest(unittest.TestCase):
362
+ """A fan-out recipe assumes its N generations OVERLAP.
363
+
364
+ On a backend serving one request at a time they do not -- they queue, so
365
+ fusion N=3 costs 3x the wall clock of a single call for the same answer,
366
+ and the deliver run paying it has a fixed wall-clock budget to finish in.
367
+
368
+ Measured live (2026-08-20, ninfer --max-concurrency 1, qwen3.8-27b):
369
+ tool-carrying turns already bypass recipes via has_tools, but mission
370
+ PLANNING carries no tools -- so it ran under fusion N=3 and took ~20
371
+ minutes, 17% of a 120-minute run budget, before turn 1 existed.
372
+ """
373
+
374
+ def test_unknown_width_changes_nothing(self):
375
+ # Not every backend can be probed (ninfer serves no /slots), so silence
376
+ # is not evidence -- unknown width must leave behaviour identical.
377
+ self.assertEqual(ce.select_recipe(body(), S(recipe="fusion"), False), "fusion")
378
+
379
+ def test_single_slot_downgrades_explicit_fusion(self):
380
+ self.assertEqual(ce.select_recipe(body(), S(recipe="fusion", model_slots=1), False), "single")
381
+
382
+ def test_single_slot_downgrades_auto(self):
383
+ # auto can select fusion on its own; it must not be able to on one slot.
384
+ self.assertEqual(
385
+ ce.select_recipe(body("x" * 900), S(recipe="auto", model_slots=1), False), "single"
386
+ )
387
+
388
+ def test_single_slot_downgrades_other_multi_call_recipes(self):
389
+ for recipe in ("ratings", "remom"):
390
+ self.assertEqual(
391
+ ce.select_recipe(body(), S(recipe=recipe, model_slots=1), False), "single", recipe
392
+ )
393
+
394
+ def test_multi_slot_backend_keeps_fan_out(self):
395
+ # The cost being avoided is serialization. With real parallelism there
396
+ # is nothing to avoid.
397
+ self.assertEqual(ce.select_recipe(body(), S(recipe="fusion", model_slots=4), False), "fusion")
398
+
399
+ def test_operator_can_force_fan_out_on_one_slot(self):
400
+ self.assertEqual(
401
+ ce.select_recipe(body(), S(recipe="fusion", model_slots=1, force_multi_call=True), False),
402
+ "fusion",
403
+ )
404
+
405
+ def test_single_call_recipe_is_left_alone(self):
406
+ # `confidence` issues one generation and only escalates conditionally;
407
+ # downgrading it would remove quality for no latency win.
408
+ self.assertEqual(
409
+ ce.select_recipe(body(), S(recipe="confidence", model_slots=1), False), "confidence"
410
+ )
411
+
412
+ def test_zero_slots_counts_as_single(self):
413
+ self.assertEqual(ce.select_recipe(body(), S(recipe="fusion", model_slots=0), False), "single")
414
+
415
+
416
+ class SlotWidthResolutionTest(unittest.TestCase):
417
+ """Width comes from the environment ONCE, at Settings construction."""
418
+
419
+ def setUp(self):
420
+ self._saved = {k: os.environ.get(k) for k in ("UAP_MODEL_SLOTS", "PROXY_MODEL_SLOTS")}
421
+ for k in self._saved:
422
+ os.environ.pop(k, None)
423
+
424
+ def tearDown(self):
425
+ for k, v in self._saved.items():
426
+ if v is None:
427
+ os.environ.pop(k, None)
428
+ else:
429
+ os.environ[k] = v
430
+
431
+ def test_absent_is_unknown(self):
432
+ self.assertIsNone(ce.resolve_model_slots())
433
+
434
+ def test_reads_the_shared_variable(self):
435
+ os.environ["UAP_MODEL_SLOTS"] = "1"
436
+ self.assertEqual(ce.resolve_model_slots(), 1)
437
+
438
+ def test_proxy_local_alias_is_honoured(self):
439
+ os.environ["PROXY_MODEL_SLOTS"] = "2"
440
+ self.assertEqual(ce.resolve_model_slots(), 2)
441
+
442
+ def test_unparseable_width_is_unknown_not_single(self):
443
+ # A typo must not silently disable fan-out everywhere.
444
+ os.environ["UAP_MODEL_SLOTS"] = "lots"
445
+ self.assertIsNone(ce.resolve_model_slots())
446
+
447
+ def test_ambient_one_slot_env_does_not_move_an_explicit_setting(self):
448
+ # THE isolation property. proxy.env now carries UAP_MODEL_SLOTS on a
449
+ # one-slot box and the proxy env loader setdefaults it into every
450
+ # subprocess; when the selector read process env directly, that ambient
451
+ # value silently failed 15 unrelated tests in this file.
452
+ os.environ["UAP_MODEL_SLOTS"] = "1"
453
+ self.assertEqual(ce.select_recipe(body(), S(recipe="fusion"), False), "fusion")
454
+
455
+
456
+ class SlotDowngradeSkipsGenerationsTest(unittest.TestCase):
457
+ """The cost being avoided is upstream GENERATIONS, so assert on the calls."""
458
+
459
+ def test_one_slot_backend_issues_no_extra_generations(self):
460
+ primary = {"content": [{"type": "text", "text": "answer"}]}
461
+ calls = []
462
+
463
+ async def call_primary(**kw):
464
+ calls.append(kw)
465
+ return primary
466
+
467
+ async def call_judge(**kw):
468
+ raise AssertionError("judge must not be called on a downgraded turn")
469
+
470
+ out = run(
471
+ ce.apply_recipe(
472
+ primary, body(), {"model": "qwen"},
473
+ S(recipe="fusion", model_slots=1),
474
+ False, call_primary, call_judge,
475
+ )
476
+ )
477
+ self.assertEqual(len(calls), 0)
478
+ self.assertIs(out, primary)
479
+
480
+ def test_off_values_do_not_force_fan_out(self):
481
+ # The escape hatch is a negative-set membership test; a refactor to
482
+ # bool(os.environ.get(...)) would invert it and only "1" is otherwise covered.
483
+ for raw in ("0", "false", "off", "no", ""):
484
+ with self.subTest(raw=raw):
485
+ os.environ["PROXY_FORCE_MULTI_CALL"] = raw
486
+ try:
487
+ self.assertFalse(ce.Settings.from_env().force_multi_call)
488
+ finally:
489
+ os.environ.pop("PROXY_FORCE_MULTI_CALL", None)
490
+
491
+
354
492
  if __name__ == "__main__":
355
493
  unittest.main()