fix(cognition): decisions and cycle output no longer depend on map order

Formation summed its terms by ranging over a map, so the score could
differ in the last bit between runs of the same state; the volition hook
assessed commitments, metacognition raised repeated-failure candidates and
the forensic explanation listed commitments in map iteration order, so the
events a cycle emits and an explanation's order varied between runs. Each
now iterates in sorted order, as replay determinism (PLAN §1 R3) requires.
This commit is contained in:
Andy Dixon
2026-10-06 20:24:54 +01:00
parent 581e9009cd
commit c3308106bb
4 changed files with 36 additions and 10 deletions
+9 -2
View File
@@ -688,9 +688,16 @@ func Form(in FormationInput) Formation {
case w.CommitmentID != "":
f.Kind = IntentFulfilCommitment
}
// Summed in key order: floating-point addition is not associative, and a
// decision must not depend on map iteration order.
keys := make([]string, 0, len(t))
for k := range t {
keys = append(keys, k)
}
sort.Strings(keys)
score := 0.0
for _, v := range t {
score += v
for _, k := range keys {
score += t[k]
}
f.Score = round3(score)
t["score"] = f.Score