commit 2f9696c6ed7a3fb1b25fac1d6fa84557458acd2f
parent 856b0e22e424151eaa9868fa282d61aec6a3f29b
Author: triesap <tyson@radroots.org>
Date: Mon, 21 Sep 2026 13:57:01 +0000
core: compose normalized versioned preferences
Diffstat:
2 files changed, 99 insertions(+), 0 deletions(-)
diff --git a/src/hyf_application/match_ranking.mojo b/src/hyf_application/match_ranking.mojo
@@ -0,0 +1,70 @@
+from std.collections import List
+
+
+@fieldwise_init
+struct PreferenceComponent(Copyable, Movable):
+ var policy: String
+ var score: Float64
+ var weight: Float64
+
+
+def preference_component(
+ policy: String, score: Float64, weight: Float64
+) raises -> PreferenceComponent:
+ if String(policy).strip().byte_length() == 0:
+ raise Error("preference component requires a policy")
+ if score < 0.0 or score > 1.0:
+ raise Error("preference score must be within [0, 1]")
+ if weight < 0.0:
+ raise Error("preference weight must be non-negative")
+ return PreferenceComponent(policy=String(policy), score=score, weight=weight)
+
+
+def compose_preference(components: List[PreferenceComponent]) -> Int:
+ var weighted = 0.0
+ var total_weight = 0.0
+ for component in components:
+ weighted += component.score * component.weight
+ total_weight += component.weight
+ if total_weight <= 0.0:
+ return 0
+ return Int((weighted / total_weight) * 100.0)
+
+
+def preference_is_success_probability() -> Bool:
+ return False
+
+
+def rank_by_preference(
+ plan_ids: List[String], scores: List[Int]
+) raises -> List[String]:
+ if len(plan_ids) != len(scores):
+ raise Error("plan ids and scores must align")
+ var pairs = List[PreferenceComponent]()
+ _ = pairs
+ var order = List[Int]()
+ for index in range(len(plan_ids)):
+ order.append(index)
+ # insertion sort: deterministic desc by score, then asc by plan id
+ var ranked = List[Int]()
+ for index in order:
+ var inserted = False
+ var updated = List[Int]()
+ for existing in ranked:
+ if not inserted and (
+ scores[index] > scores[existing]
+ or (
+ scores[index] == scores[existing]
+ and plan_ids[index] < plan_ids[existing]
+ )
+ ):
+ updated.append(index)
+ inserted = True
+ updated.append(existing)
+ if not inserted:
+ updated.append(index)
+ ranked = updated^
+ var result = List[String]()
+ for index in ranked:
+ result.append(String(plan_ids[index]))
+ return result^
diff --git a/tests/test_application.mojo b/tests/test_application.mojo
@@ -642,3 +642,32 @@ def test_culinary_use_semantic_scoring_gated() raises:
with assert_raises():
_ = culinary_use_score(answer, 3, 0, 1)
assert_true(not culinary_score_affects_feasibility())
+
+
+from hyf_application.match_ranking import (
+ PreferenceComponent,
+ compose_preference,
+ preference_component,
+ preference_is_success_probability,
+ rank_by_preference,
+)
+
+
+def test_versioned_preference_composition_and_stable_ties() raises:
+ var components = List[PreferenceComponent]()
+ components.append(preference_component("culinary", 1.0, 1.0))
+ components.append(preference_component("distance", 0.5, 1.0))
+ assert_equal(compose_preference(components), 75)
+ assert_true(not preference_is_success_probability())
+ var ids = List[String]()
+ ids.append("plan-b")
+ ids.append("plan-a")
+ ids.append("plan-c")
+ var scores = List[Int]()
+ scores.append(50)
+ scores.append(50)
+ scores.append(70)
+ var ranked = rank_by_preference(ids, scores)
+ assert_equal(ranked[0], "plan-c")
+ assert_equal(ranked[1], "plan-a")
+ assert_equal(ranked[2], "plan-b")