infosave commited on
Commit
40aa81d
·
verified ·
1 Parent(s): e916c10

Private CMF BANKING77 research release with measured evidence

Browse files
Files changed (38) hide show
  1. .gitattributes +1 -0
  2. ARTICLE_RU.md +16 -0
  3. README.md +21 -0
  4. SHA256SUMS +36 -5
  5. evidence/banking77/jev-primary-combined.jsonl +0 -0
  6. evidence/banking77/jev-probability-diagnostic.json +200 -0
  7. evidence/banking77/local-test-repeat.jsonl +3 -0
  8. evidence/release/build-cpu.txt +4 -0
  9. evidence/release/clippy.txt +11 -0
  10. evidence/release/fcd-incremental-console.txt +33 -0
  11. evidence/release/isolated-build.txt +242 -0
  12. evidence/release/isolated-infer.json +563 -0
  13. evidence/release/lifecycle-console.txt +38 -0
  14. evidence/release/live-release-status.json +31 -0
  15. evidence/release/metal-acceptance-console.txt +117 -0
  16. evidence/release/near-duplicate-console.txt +11 -0
  17. evidence/release/python-tests.txt +5 -0
  18. evidence/release/release-acceptance-console.txt +19 -0
  19. evidence/release/runtime-cpu-console-final.txt +35 -0
  20. evidence/release/runtime-cpu-console.txt +35 -0
  21. evidence/release/runtime-metal-console-final.txt +41 -0
  22. evidence/release/runtime-metal-console.txt +41 -0
  23. evidence/release/rust-tests.txt +40 -0
  24. evidence/release/vulkan-acceptance.json +44 -0
  25. evidence/release/vulkan-check-macos.txt +143 -0
  26. evidence/release/vulkan-environment.txt +9 -0
  27. evidence/release/vulkan-linux-tests.txt +114 -0
  28. evidence/release/vulkan-shader-test.txt +54 -0
  29. reproduce.sh +15 -0
  30. source/tools/cortiq-decision/decision_server.py +1 -1
  31. source/tools/cortiq-decision/src/main.rs +2 -0
  32. source/tools/cortiq-decision/src/vulkan.rs +12 -0
  33. source/tools/cortiq-decision/tests/contracts.rs +216 -0
  34. source/tools/cortiq-decision/tests/test_decisions_protocol.py +113 -0
  35. source/tools/cortiq-decision/tests/test_harness.py +27 -0
  36. source/tools/cortiq-decision/tests/test_server.py +66 -0
  37. source/tools/cortiq-decision/tests/test_support_gate.py +11 -0
  38. source/tools/cortiq-decision/tests/test_training.py +79 -0
.gitattributes CHANGED
@@ -35,3 +35,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  cortiq-banking77.cmf filter=lfs diff=lfs merge=lfs -text
37
  training/seed.json filter=lfs diff=lfs merge=lfs -text
 
 
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  cortiq-banking77.cmf filter=lfs diff=lfs merge=lfs -text
37
  training/seed.json filter=lfs diff=lfs merge=lfs -text
38
+ evidence/banking77/local-test-repeat.jsonl filter=lfs diff=lfs merge=lfs -text
ARTICLE_RU.md CHANGED
@@ -4,6 +4,8 @@
4
 
5
  Это не рассказ о «модели, победившей все LLM». Мы сравниваем обученного специалиста с универсальной моделью решений. Затем отдельно показываем, как добавлять навыки к другой, FCD-модели, не меняя её общее ядро. **Результат BANKING77 принадлежит affine-модели, а не FCD.**
6
 
 
 
7
  ## Зачем вообще отдельная модель решений
8
 
9
  Агенту часто нужен не абзац текста, а одно действие: выбрать обработчик, определить категорию обращения, ответить да/нет, выставить оценку или отказаться от автоматического решения. Генерация JSON токен за токеном — не единственный способ сделать это.
@@ -66,6 +68,14 @@ Apple M4, 24 GiB RAM; прогретый энкодер, без кэша отв
66
 
67
  Decision-веса BANKING77 занимают **3,70 MiB**, но полный автономный CMF с энкодером — **468,70 MiB**. Ранее измеренный peak RSS полного CPU-eval — 2,12 GiB. В резидентном сервере дополнительно устранено удержание копии encoder-mapping для каждой топологии. Серверные RAM/VRAM и энергопотребление Jev неизвестны: сравнительного ресурсного превосходства над ним мы не заявляем.
68
 
 
 
 
 
 
 
 
 
69
  ## Вторая часть: добавить навык и не сломать старые
70
 
71
  Это **отдельный FCD-эксперимент**, не подмена affine-результатов. Формула реконструкции:
@@ -76,6 +86,8 @@ Decision-веса BANKING77 занимают **3,70 MiB**, но полный а
76
 
77
  Общие `U/S/V` заморожены. Новый навык получает собственный центр и вектор в свободном ортогональном подпространстве. У текущего ядра ранг 125 и ёмкость 24 вектора; после двух добавлений используются 10. Мы не обещаем бесконечное число ортогональных навыков в конечном пространстве. При исчерпании ёмкости текущий тренер отказывает, а не тайно переписывает ядро.
78
 
 
 
79
  Важная неудача: первая новая топология перехватила **3 из 43** старых контрольных запросов, хотя старые ��еса не изменились. Заморозка весов сама по себе не доказывает отсутствие забывания.
80
 
81
  Исправление — индивидуальная граница допустимой ошибки реконструкции. Она выбирается **только по calibration**, без старых контролей и финального теста. Вне области поддержки новая топология исключается и из выбора, и из нормировки вероятностей. Поэтому она не понижает уверенность старого ответа одним своим присутствием.
@@ -113,3 +125,7 @@ Decision-веса BANKING77 занимают **3,70 MiB**, но полный а
113
  **Повторяемые решения исполняются локально; неизвестные не маскируются под уверенный ответ; новый навык допускается только после проверки того, что он не отнял старые.** Для конкретного приложения это может быть полезнее красивого, но недоказанного обещания заменить любую большую модель.
114
 
115
  Артефакты, протоколы, сырые результаты и ограничения должны публиковаться вместе. Linux/Vulkan-проверка и ссылка на закрытый HF-релиз приведены в сопровождающем отчёте; их показатели не подставляются задним числом в таблицу Apple M4.
 
 
 
 
 
4
 
5
  Это не рассказ о «модели, победившей все LLM». Мы сравниваем обученного специалиста с универсальной моделью решений. Затем отдельно показываем, как добавлять навыки к другой, FCD-модели, не меняя её общее ядро. **Результат BANKING77 принадлежит affine-модели, а не FCD.**
6
 
7
+ ![Результаты BANKING77 и пакетного энкодирования](figures/banking77-results.png)
8
+
9
  ## Зачем вообще отдельная модель решений
10
 
11
  Агенту часто нужен не абзац текста, а одно действие: выбрать обработчик, определить категорию обращения, ответить да/нет, выставить оценку или отказаться от автоматического решения. Генерация JSON токен за токеном — не единственный способ сделать это.
 
68
 
69
  Decision-веса BANKING77 занимают **3,70 MiB**, но полный автономный CMF с энкодером — **468,70 MiB**. Ранее измеренный peak RSS полного CPU-eval — 2,12 GiB. В резидентном сервере дополнительно устранено удержание копии encoder-mapping для каждой топологии. Серверные RAM/VRAM и энергопотребление Jev неизвестны: сравнительного ресурсного превосходства над ним мы не заявляем.
70
 
71
+ ### Проверка настоящего Vulkan на NVIDIA
72
+
73
+ На Linux-сервере с **RTX PRO 4000 Blackwell, 24 GiB** тот же affine scorer исполнен через Vulkan, без CPU/software fallback. Все 3080 предвычисленных embedding-векторов дали те же классы и те же решения порога: 2818 правильных, 2284 принятых, 2254 правильных среди принятых. Максимальное расхождение ошибки реконструкции с CPU — 1,43e-6.
74
+
75
+ При batch=128: **2,190 мс Vulkan против 114,625 мс CPU** того же сервера, примерно 52×. При batch=1 GPU, наоборот, медленнее: 1,408 против 0,930 мс. Время включает отправку входа, submit, ожидание и чтение результата. Резидентные буферы scorer — 4 178 756 байт, **без энкодера**.
76
+
77
+ На GPU одновременно работала чужая вычислительная задача; наблюдалась загрузка 94–100%. Мы её не останавливали. Эти цифры — воспроизводимый журнал работы под конкурирующей нагрузкой, а не предел производительности свободной карты. Энкодер на Vulkan **не портирован**, поэтому 52× нельзя переносить на обработку текста целиком.
78
+
79
  ## Вторая часть: добавить навык и не сломать старые
80
 
81
  Это **отдельный FCD-эксперимент**, не подмена affine-результатов. Формула реконструкции:
 
86
 
87
  Общие `U/S/V` заморожены. Новый навык получает собственный центр и вектор в свободном ортогональном подпространстве. У текущего ядра ранг 125 и ёмкость 24 вектора; после двух добавлений используются 10. Мы не обещаем бесконечное число ортогональных навыков в конечном пространстве. При исчерпании ёмкости текущий тренер отказывает, а не тайно переписывает ядро.
88
 
89
+ Обучаемая добавка одного навыка — **24 коэффициента вектора + 384 координаты центра = 1632 байта F32-параметров**, плюс статистика и метаданные. Это не размер полного CMF: общий энкодер и ядро значительно больше, а текущий экспорт сохраняет полную новую версию файла.
90
+
91
  Важная неудача: первая новая топология перехватила **3 из 43** старых контрольных запросов, хотя старые ��еса не изменились. Заморозка весов сама по себе не доказывает отсутствие забывания.
92
 
93
  Исправление — индивидуальная граница допустимой ошибки реконструкции. Она выбирается **только по calibration**, без старых контролей и финального теста. Вне области поддержки новая топология исключается и из выбора, и из нормировки вероятностей. Поэтому она не понижает уверенность старого ответа одним своим присутствием.
 
125
  **Повторяемые решения исполняются локально; неизвестные не маскируются под уверенный ответ; новый навык допускается только после проверки того, что он не отнял старые.** Для конкретного приложения это может быть полезнее красивого, но недоказанного обещания заменить любую большую модель.
126
 
127
  Артефакты, протоколы, сырые результаты и ограничения должны публиковаться вместе. Linux/Vulkan-проверка и ссылка на закрытый HF-релиз приведены в сопровождающем отчёте; их показатели не подставляются задним числом в таблицу Apple M4.
128
+
129
+ ## Артефакт
130
+
131
+ Закрытый исследовательский релиз BANKING77: [Hugging Face](https://huggingface.co/infosave/cortiq-decision-banking77-cmf-20260925). Репозиторий приватный; доступ имеет владелец и приглашённые им участники. Веса production-seed и производной FCD туда не загружены.
README.md CHANGED
@@ -99,3 +99,24 @@ The separate private-production seed and its derived FCD weights, request histor
99
  SQLite registry, keys, SSH/WireGuard configuration, and web assets are **not included**.
100
  No Jev responses were used as training labels. See `LICENSES.md` and the accompanying
101
  Russian article for the distinct FCD experiment and exact scopes of each result.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  SQLite registry, keys, SSH/WireGuard configuration, and web assets are **not included**.
100
  No Jev responses were used as training labels. See `LICENSES.md` and the accompanying
101
  Russian article for the distinct FCD experiment and exact scopes of each result.
102
+
103
+ ## Additional verified implementations
104
+
105
+ * F32 Metal encoder: 3,080/3,080 same winners and same .85 gate as CPU.
106
+ On the same DEV batch=128, 671 vs 135 texts/s; single-request worker p50
107
+ 6.14 vs 6.10 ms (no median single-request win). RSS after single-workload:
108
+ 0.89 vs 1.66 GiB; not peak memory. See runtime-{metal,cpu}.json.
109
+ * Linux / RTX PRO 4000 Blackwell / Vulkan scorer: all 3,080 winners and gates
110
+ agree, max reconstruction-error delta 1.43e-6. Batch=128 p50: 2.190 ms Vulkan
111
+ vs 114.625 ms CPU. This is scorer-only with precomputed embeddings, measured
112
+ under a pre-existing GPU job, not full-text speed or idle-card maximum.
113
+ * Included isolated source builds successfully; supplied CMF loads and infers
114
+ offline; HTTP package smoke succeeds and serves no web UI.
115
+ * The FCD experiment described in ARTICLE_RU.md is a different, local model:
116
+ its production-derived weights are deliberately not included in this repository.
117
+
118
+ The working notebook/workstation had unrelated background applications. All scopes,
119
+ client-validation incidents and limitations are retained in evidence, not removed
120
+ in favor of the headline metrics. Article: [Russian version](ARTICLE_RU.md).
121
+
122
+ Reproduce the full local test without paid API calls: `./reproduce.sh /path/to/new-output`. This evaluates the already-frozen model; it does not fit on test labels.
SHA256SUMS CHANGED
@@ -1,6 +1,6 @@
1
- 444d778aff686ab91b9679e6293e1b8d71e22426078e1aa2ae364b0405ef2f5b ARTICLE_RU.md
2
  3bcff101bcd473a82cf9c5f6e342e57940e5b8f7aa6323c8602e6e793095a8de LICENSES.md
3
- 11aae3a04fcfb7ea6ccbb0a0b08670c80ddf9015c86e8df52ffa103d118d8c73 README.md
4
  1d1708069621ea6f2f8c0bf8ee120a74dcdc8b3a8c3590c658de90e59a3317b1 contract.json
5
  4cdaf9ec19054f17cd34d420a56f4c8bb0eed12c2429732e9baf902ef52303df cortiq-banking77.cmf
6
  ceeb47cab7a611169bedbe38b62441b0c58794a05295eeff751550b7640708a8 evidence/banking77/HARNESS_INCIDENTS.md
@@ -13,23 +13,48 @@ f073ec51d07d50a1f83f10c57a0e33cb3f4274c4d9c1ce48e6892422192e6335 evidence/banki
13
  415863de9f46d3e315613a281895cbbe844c0be52fcaf719ad502ca015b4d6b3 evidence/banking77/data/train.jsonl
14
  f4a7d35e026ca65a7fae5e1687cc990d60568c6785d4af2391b17e0279fa4abf evidence/banking77/dataset-source.json
15
  707e285b0fec5dd3cfba0245f6400abb9577b0d6278ba1eb65d6a44a4eb87761 evidence/banking77/freeze.json
 
 
 
16
  b6add684980296431b2c66492655d7d7fb5599e0b52329fe36c5d9d3d81df09a evidence/banking77/selective-test.json
17
  6371f55dd882864bcf76771170a331cfbd1ba183cb3bb65a430b85fffa7a5fa2 evidence/release/banking-release-manifest.json
 
 
18
  ae9ef4a2695c27618f08ea72925dec58abc0789b476f657d7310652e25ce698a evidence/release/fcd-incremental-acceptance.json
 
19
  4e2ee635fd044eb0d68b1fb75fea954d77e82e2c05d68c2b7089ed3d0707ea1c evidence/release/fcd-incremental-protocol.json
20
  2caa042b7a049ed59b79c0e03a0baa94cdaf1b9a22196b256bf720174cf65f53 evidence/release/fcd-second-calibration.json
21
  c347d66ab4b4793c367d0a9a3d0ea7febed49af4693d63f780555d200105fcff evidence/release/fcd-support-calibration.json
 
 
 
 
22
  bb1d37c6e80790dcf80139da3a5595c9bc319edcc456de0896907103b125ef89 evidence/release/local-fcd-install.json
 
23
  f41f3899ab6e1a8d0c050a38474964b1cb83bdf531ad808d4fea6e3e8dc25bda evidence/release/metal-acceptance.json
24
  f223fd7fa446639056ff4e074318ab8a7db6d533ba835ed032aaa447fdc05931 evidence/release/near-duplicate-audit.json
 
 
 
25
  3e2cb2f6cb7976660f837f5584e5f2404f7735074358e098f4a7653735310b49 evidence/release/release-acceptance.json
 
 
26
  90c1a473501762deda5d0ed136903a01c77d31672c32f184e8497b0ec73dffe9 evidence/release/runtime-cpu.json
 
 
27
  d6bffcb3f85bf0b2b316cd3e5915de8ba8ee2821055ce3978b9a493296d7028b evidence/release/runtime-metal.json
 
 
 
 
 
 
28
  14b401166825d22d9a2a3771becb2632018c21d6fd4ed370246e83d45a8ea984 figures/banking77-results.png
29
  0bf59d136536dea5dcf80ce96c5988e46522ce69f3ae817666c7f5d10ded6618 licenses/Apache-2.0.txt
30
  7e7170e3cebf88a9f60c7b8421418323c09304da1af4d5e90f4da1dc1c8a2661 licenses/BANKING77-CC-BY-4.0.txt
31
  41ac81b48406cffd95db849913238063dacf58419b15c7c7c56b9d3a5755608b licenses/encoder-source.json
32
  50fdf7871d31dbc665f837cd6217c961378916e9d2ec40251da520b13cd211f6 policy.json
 
33
  9ff38954ec8573a74ad6a04f03d2dbd6cbe510255c2d9bc0b1e640c2f8b7a15a requirements-metal.txt
34
  5a81cde5d4f409222788b0a0da88fff0acdb160f45ab8839d9661cff6aa10424 requirements-training.txt
35
  61aa8a323944fa1ab678ba76e20375cf84b0b329ff826fc32751fba1d5afd975 source/Cargo.toml
@@ -47,7 +72,7 @@ b2523ec287c0411488aede69337ba1a160b511ec800608d9a7798ba0063fd9c2 source/crates/
47
  18b7aad159777c636d867861c989214a38e5b743d49c026444bbcd3bdbeb8675 source/tools/cortiq-decision/Cargo.toml
48
  0df7eb993c25ef4abe7cf41893c803c50dc6b24c34d6bf7ef1d05032627ef01f source/tools/cortiq-decision/README.md
49
  76d2a79c9bfc0a8965d1f146d8caa40862b7e3d88d97cd9988801a4fe88d796e source/tools/cortiq-decision/analyze_banking77.py
50
- 0243bb8070d373977ff87f08d17dea4b57920b5bee354f7fbc79d7404a24bcf8 source/tools/cortiq-decision/decision_server.py
51
  5dd0d8f2d406983ff54dacca15a275c2f388f49704e9def14acaa71d703df400 source/tools/cortiq-decision/decisions_protocol.py
52
  4f99186a22e3f1ef502e250cf6951b2d3863a28a6e01a6602c7e5972e4833092 source/tools/cortiq-decision/demo.py
53
  91acf11d529b8b432bb50679711b5d6e17020f09efa1562b5596aad56dbf38e1 source/tools/cortiq-decision/lifecycle.py
@@ -61,13 +86,19 @@ d8837fdb40a1d8d359056eba2ed3857707a4ea47b2b22aa446b6cc687c600410 source/tools/c
61
  8be3ba24299c1c5a6ebc931dd71025a9e0c255ccce1fc8b610914c64a6193f41 source/tools/cortiq-decision/src/encoder.rs
62
  d01420fc5f26e43ec2a073bc4c19e606bc4386203b99cfc2ad385515845b174d source/tools/cortiq-decision/src/fcd.rs
63
  040cf88f426a040970712829e7e52a9dfd576b3863d6ceb88e0047a9b98e0bde source/tools/cortiq-decision/src/lib.rs
64
- 95a782bb884f0e8f71b2a52b9f145ef8ff3f832d02a506f7c722d4e4556c4032 source/tools/cortiq-decision/src/main.rs
65
  6afd52189ca7f66500eef8c03f646dd617acbe92afa62cd793afe30299c30a93 source/tools/cortiq-decision/src/metal.rs
66
  f4db81c80be5e0eb80b19b24b4fd2de0d593a480c64fde5bc4883b3571aa84c0 source/tools/cortiq-decision/src/packed.rs
67
  44072e0dd4a534237316b966587cd115d679fe35beb3da7579c7171abf362433 source/tools/cortiq-decision/src/policy.rs
68
  66b024cb5fe6d66a413b4e0f3470b8895fa3010663615fc5f8dbdfaee570d4a0 source/tools/cortiq-decision/src/rpc.rs
69
  ab5fb6d464ba1cada047a00d65466166ee65f8d5190461c4ebcac1cf71b68009 source/tools/cortiq-decision/src/service.rs
70
- 8ccdf017d50fe4a7aec1a96ebaddf33d797343055de152d2211c9cad0d3621e8 source/tools/cortiq-decision/src/vulkan.rs
 
 
 
 
 
 
71
  20a7bf5a24176112cc71f61fd80f9c23ee74b43300cfbeae390ac0bbb8a46c89 source/tools/cortiq-decision/train.py
72
  362769573bd26a4189027f2b9ea27eaae680159848e5eba1c28b4c6226654d1e training/seed.json
73
  7c7f64dc00cc5454792e643e21c4b4ed1acac74687015452cc3c1faf45c69758 training/training.json
 
1
+ fe02cf4034aade2ac4498c23a5ea0b608851e97bdabfb712fc77ec4316a235b6 ARTICLE_RU.md
2
  3bcff101bcd473a82cf9c5f6e342e57940e5b8f7aa6323c8602e6e793095a8de LICENSES.md
3
+ e8362bcda89c2347289fa3e823443316380d5a2a8388fa01ff6837f6c4a16b27 README.md
4
  1d1708069621ea6f2f8c0bf8ee120a74dcdc8b3a8c3590c658de90e59a3317b1 contract.json
5
  4cdaf9ec19054f17cd34d420a56f4c8bb0eed12c2429732e9baf902ef52303df cortiq-banking77.cmf
6
  ceeb47cab7a611169bedbe38b62441b0c58794a05295eeff751550b7640708a8 evidence/banking77/HARNESS_INCIDENTS.md
 
13
  415863de9f46d3e315613a281895cbbe844c0be52fcaf719ad502ca015b4d6b3 evidence/banking77/data/train.jsonl
14
  f4a7d35e026ca65a7fae5e1687cc990d60568c6785d4af2391b17e0279fa4abf evidence/banking77/dataset-source.json
15
  707e285b0fec5dd3cfba0245f6400abb9577b0d6278ba1eb65d6a44a4eb87761 evidence/banking77/freeze.json
16
+ 89b41298347244c22bbab1175ff076f8ac28b9f42e802f106262151353eafa8a evidence/banking77/jev-primary-combined.jsonl
17
+ 178c6a08537a2990b07b8975fbeb1e6ac9b445ef645b8a0d60d3c371b48407a4 evidence/banking77/jev-probability-diagnostic.json
18
+ 00aa8ca8498067c5bd46ae5651f2cd46d901cf12ebdc08b1bf03cb3948669c4f evidence/banking77/local-test-repeat.jsonl
19
  b6add684980296431b2c66492655d7d7fb5599e0b52329fe36c5d9d3d81df09a evidence/banking77/selective-test.json
20
  6371f55dd882864bcf76771170a331cfbd1ba183cb3bb65a430b85fffa7a5fa2 evidence/release/banking-release-manifest.json
21
+ 2acd7929f2308170163e0ee72ef63873bdbeadbbcaca6dac2cfa4a6366c2fb5f evidence/release/build-cpu.txt
22
+ f1b6afa213c7eee891dce27267b16ddd6fcf878056108dfaa9516f916a9555f0 evidence/release/clippy.txt
23
  ae9ef4a2695c27618f08ea72925dec58abc0789b476f657d7310652e25ce698a evidence/release/fcd-incremental-acceptance.json
24
+ ae9ef4a2695c27618f08ea72925dec58abc0789b476f657d7310652e25ce698a evidence/release/fcd-incremental-console.txt
25
  4e2ee635fd044eb0d68b1fb75fea954d77e82e2c05d68c2b7089ed3d0707ea1c evidence/release/fcd-incremental-protocol.json
26
  2caa042b7a049ed59b79c0e03a0baa94cdaf1b9a22196b256bf720174cf65f53 evidence/release/fcd-second-calibration.json
27
  c347d66ab4b4793c367d0a9a3d0ea7febed49af4693d63f780555d200105fcff evidence/release/fcd-support-calibration.json
28
+ 371eeeabdf2aa68f3718605838efa25dcf9e12fdf0c80fbc46b39cd6494664b7 evidence/release/isolated-build.txt
29
+ 09857b047666c28321d6415071f006a8597b1b1bc2a467932f30f930bdb34dca evidence/release/isolated-infer.json
30
+ 261a5fd9564d61b41103af78f2bbd2badd93a17e5eab43c810c814a2daf6f494 evidence/release/lifecycle-console.txt
31
+ bff23271753c5aa8fd11c1fca76529a4a2f201b36947e479cfc40c8b2d07b317 evidence/release/live-release-status.json
32
  bb1d37c6e80790dcf80139da3a5595c9bc319edcc456de0896907103b125ef89 evidence/release/local-fcd-install.json
33
+ a55a14bb89e934fd5f7eed6b894002e64b36d66a99aaa424a0fba22ab237bad7 evidence/release/metal-acceptance-console.txt
34
  f41f3899ab6e1a8d0c050a38474964b1cb83bdf531ad808d4fea6e3e8dc25bda evidence/release/metal-acceptance.json
35
  f223fd7fa446639056ff4e074318ab8a7db6d533ba835ed032aaa447fdc05931 evidence/release/near-duplicate-audit.json
36
+ 7cf5774fd4f5a52e8806485b9ac38b8071e5aeb9f0a2ef104a584c0154546576 evidence/release/near-duplicate-console.txt
37
+ 98eb816bc72db0eb3af6b37bd18188d6f24beb170c157ca7952ea3b96b27b573 evidence/release/python-tests.txt
38
+ 3e2cb2f6cb7976660f837f5584e5f2404f7735074358e098f4a7653735310b49 evidence/release/release-acceptance-console.txt
39
  3e2cb2f6cb7976660f837f5584e5f2404f7735074358e098f4a7653735310b49 evidence/release/release-acceptance.json
40
+ 90c1a473501762deda5d0ed136903a01c77d31672c32f184e8497b0ec73dffe9 evidence/release/runtime-cpu-console-final.txt
41
+ 5fa0a31a8fdb7d737ababf42fa8668ef3ee4d992cc2cd3ddfcf894ab46780c6e evidence/release/runtime-cpu-console.txt
42
  90c1a473501762deda5d0ed136903a01c77d31672c32f184e8497b0ec73dffe9 evidence/release/runtime-cpu.json
43
+ d6bffcb3f85bf0b2b316cd3e5915de8ba8ee2821055ce3978b9a493296d7028b evidence/release/runtime-metal-console-final.txt
44
+ 2c3c2e12a6ad428ed6612648720c108fb9c089b2009d021ce8e1984bf9864b9c evidence/release/runtime-metal-console.txt
45
  d6bffcb3f85bf0b2b316cd3e5915de8ba8ee2821055ce3978b9a493296d7028b evidence/release/runtime-metal.json
46
+ e32b46c846623aa4f8c949bce53bef11ecb3c48d63e9ad72b6e9c9770073cdda evidence/release/rust-tests.txt
47
+ e33c6b7db7a23b489d146c6d96cf2215e0492934d84e9d4e0d197893d288d1b1 evidence/release/vulkan-acceptance.json
48
+ eb51be7c3acf817fdca4f86b7a901e540c7b375d6307e757e6b89d41a27aeabc evidence/release/vulkan-check-macos.txt
49
+ 5f4281c8a18d22a95823a1eea4ce6f3dd16d116f5cbe94524bf4df8d8a0f349a evidence/release/vulkan-environment.txt
50
+ 9448fca2db97cbd2f6e5a6b1a13c225cff511f959b3b4e20babeaef0201d8995 evidence/release/vulkan-linux-tests.txt
51
+ 3a6b20fc5c8943b30b43a0084f8d307c21d856c0684183e390b5d89f7f7382ae evidence/release/vulkan-shader-test.txt
52
  14b401166825d22d9a2a3771becb2632018c21d6fd4ed370246e83d45a8ea984 figures/banking77-results.png
53
  0bf59d136536dea5dcf80ce96c5988e46522ce69f3ae817666c7f5d10ded6618 licenses/Apache-2.0.txt
54
  7e7170e3cebf88a9f60c7b8421418323c09304da1af4d5e90f4da1dc1c8a2661 licenses/BANKING77-CC-BY-4.0.txt
55
  41ac81b48406cffd95db849913238063dacf58419b15c7c7c56b9d3a5755608b licenses/encoder-source.json
56
  50fdf7871d31dbc665f837cd6217c961378916e9d2ec40251da520b13cd211f6 policy.json
57
+ 4379fd02656334b6356cd042c773361b045320f9fbaf4199beaa3b6dc3a8f931 reproduce.sh
58
  9ff38954ec8573a74ad6a04f03d2dbd6cbe510255c2d9bc0b1e640c2f8b7a15a requirements-metal.txt
59
  5a81cde5d4f409222788b0a0da88fff0acdb160f45ab8839d9661cff6aa10424 requirements-training.txt
60
  61aa8a323944fa1ab678ba76e20375cf84b0b329ff826fc32751fba1d5afd975 source/Cargo.toml
 
72
  18b7aad159777c636d867861c989214a38e5b743d49c026444bbcd3bdbeb8675 source/tools/cortiq-decision/Cargo.toml
73
  0df7eb993c25ef4abe7cf41893c803c50dc6b24c34d6bf7ef1d05032627ef01f source/tools/cortiq-decision/README.md
74
  76d2a79c9bfc0a8965d1f146d8caa40862b7e3d88d97cd9988801a4fe88d796e source/tools/cortiq-decision/analyze_banking77.py
75
+ 8ac17986a6929ecf3c82251fd55f98b025d2d0416354f826c8cf6bff870531d5 source/tools/cortiq-decision/decision_server.py
76
  5dd0d8f2d406983ff54dacca15a275c2f388f49704e9def14acaa71d703df400 source/tools/cortiq-decision/decisions_protocol.py
77
  4f99186a22e3f1ef502e250cf6951b2d3863a28a6e01a6602c7e5972e4833092 source/tools/cortiq-decision/demo.py
78
  91acf11d529b8b432bb50679711b5d6e17020f09efa1562b5596aad56dbf38e1 source/tools/cortiq-decision/lifecycle.py
 
86
  8be3ba24299c1c5a6ebc931dd71025a9e0c255ccce1fc8b610914c64a6193f41 source/tools/cortiq-decision/src/encoder.rs
87
  d01420fc5f26e43ec2a073bc4c19e606bc4386203b99cfc2ad385515845b174d source/tools/cortiq-decision/src/fcd.rs
88
  040cf88f426a040970712829e7e52a9dfd576b3863d6ceb88e0047a9b98e0bde source/tools/cortiq-decision/src/lib.rs
89
+ 8f014af587ad6a3c19bcfd7b7dc0b842ea1a1849d1251c1e299f136403f19905 source/tools/cortiq-decision/src/main.rs
90
  6afd52189ca7f66500eef8c03f646dd617acbe92afa62cd793afe30299c30a93 source/tools/cortiq-decision/src/metal.rs
91
  f4db81c80be5e0eb80b19b24b4fd2de0d593a480c64fde5bc4883b3571aa84c0 source/tools/cortiq-decision/src/packed.rs
92
  44072e0dd4a534237316b966587cd115d679fe35beb3da7579c7171abf362433 source/tools/cortiq-decision/src/policy.rs
93
  66b024cb5fe6d66a413b4e0f3470b8895fa3010663615fc5f8dbdfaee570d4a0 source/tools/cortiq-decision/src/rpc.rs
94
  ab5fb6d464ba1cada047a00d65466166ee65f8d5190461c4ebcac1cf71b68009 source/tools/cortiq-decision/src/service.rs
95
+ 6761a362a318d2dc3327deb9c6982a9e6c30fa3fc383fe5d5350e8735ab3cbc5 source/tools/cortiq-decision/src/vulkan.rs
96
+ 1bd8074f6193b4439aa49d0a8c16fe0c7d6792aa0cfbdcf99712420a9efef836 source/tools/cortiq-decision/tests/contracts.rs
97
+ 0fd5efd944f72c3388b860bf4cec434e0eece11a12a96ce3c8188c3d36c83215 source/tools/cortiq-decision/tests/test_decisions_protocol.py
98
+ 7a894d7a95a008c7eae11be2e86be8cc3a806cdc40afec5006daa57036b8fc4b source/tools/cortiq-decision/tests/test_harness.py
99
+ 8ab49885f48745fe2314cb5d807fa7f78e9650ee938a4af25dc2d3c0fc1a58b3 source/tools/cortiq-decision/tests/test_server.py
100
+ c2aa55bac6e0aebb33fbfd0bd6a4f04885270669eaf83f9ac513030bd94d1969 source/tools/cortiq-decision/tests/test_support_gate.py
101
+ 9aa106c14aebc6e3378be2d63365cd4c91deee5f61fa30965a1f352e63bee09f source/tools/cortiq-decision/tests/test_training.py
102
  20a7bf5a24176112cc71f61fd80f9c23ee74b43300cfbeae390ac0bbb8a46c89 source/tools/cortiq-decision/train.py
103
  362769573bd26a4189027f2b9ea27eaae680159848e5eba1c28b4c6226654d1e training/seed.json
104
  7c7f64dc00cc5454792e643e21c4b4ed1acac74687015452cc3c1faf45c69758 training/training.json
evidence/banking77/jev-primary-combined.jsonl ADDED
The diff for this file is too large to render. See raw diff
 
evidence/banking77/jev-probability-diagnostic.json ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "index": 148,
4
+ "status": 200,
5
+ "model": "typesafe/jev-1.13-20260917",
6
+ "answer": {
7
+ "type": "choice",
8
+ "choice": "exchange_charge",
9
+ "probabilities": {
10
+ "card_linking": 0,
11
+ "lost_or_stolen_card": 0,
12
+ "get_disposable_virtual_card": 0,
13
+ "card_payment_not_recognised": 0,
14
+ "extra_charge_on_statement": 0.01,
15
+ "transfer_not_received_by_recipient": 0,
16
+ "request_refund": 0,
17
+ "Refund_not_showing_up": 0,
18
+ "terminate_account": 0,
19
+ "top_up_failed": 0,
20
+ "pending_cash_withdrawal": 0,
21
+ "declined_transfer": 0,
22
+ "change_pin": 0,
23
+ "verify_source_of_funds": 0,
24
+ "beneficiary_not_allowed": 0,
25
+ "age_limit": 0,
26
+ "top_up_limits": 0,
27
+ "automatic_top_up": 0,
28
+ "pending_card_payment": 0,
29
+ "cash_withdrawal_not_recognised": 0,
30
+ "direct_debit_payment_not_recognised": 0,
31
+ "exchange_rate": 0.05,
32
+ "country_support": 0,
33
+ "transfer_into_account": 0,
34
+ "order_physical_card": 0,
35
+ "contactless_not_working": 0,
36
+ "topping_up_by_card": 0,
37
+ "failed_transfer": 0,
38
+ "top_up_reverted": 0,
39
+ "card_about_to_expire": 0,
40
+ "reverted_card_payment?": 0,
41
+ "supported_cards_and_currencies": 0,
42
+ "transfer_timing": 0,
43
+ "pending_top_up": 0,
44
+ "verify_top_up": 0,
45
+ "card_acceptance": 0,
46
+ "fiat_currency_support": 0,
47
+ "balance_not_updated_after_bank_transfer": 0,
48
+ "card_payment_wrong_exchange_rate": 0.09,
49
+ "receiving_money": 0,
50
+ "getting_spare_card": 0,
51
+ "verify_my_identity": 0,
52
+ "exchange_via_app": 0.01,
53
+ "virtual_card_not_working": 0,
54
+ "transfer_fee_charged": 0,
55
+ "passcode_forgotten": 0,
56
+ "balance_not_updated_after_cheque_or_cash_deposit": 0,
57
+ "top_up_by_cash_or_cheque": 0,
58
+ "wrong_amount_of_cash_received": 0,
59
+ "apple_pay_or_google_pay": 0,
60
+ "lost_or_stolen_phone": 0,
61
+ "card_payment_fee_charged": 0,
62
+ "pending_transfer": 0,
63
+ "top_up_by_bank_transfer_charge": 0,
64
+ "wrong_exchange_rate_for_cash_withdrawal": 0.01,
65
+ "unable_to_verify_identity": 0,
66
+ "declined_card_payment": 0,
67
+ "exchange_charge": 0.83,
68
+ "activate_my_card": 0,
69
+ "card_arrival": 0,
70
+ "top_up_by_card_charge": 0,
71
+ "pin_blocked": 0,
72
+ "transaction_charged_twice": 0,
73
+ "compromised_card": 0,
74
+ "declined_cash_withdrawal": 0,
75
+ "card_delivery_estimate": 0,
76
+ "card_not_working": 0,
77
+ "getting_virtual_card": 0,
78
+ "get_physical_card": 0,
79
+ "card_swallowed": 0,
80
+ "edit_personal_details": 0,
81
+ "why_verify_identity": 0,
82
+ "cancel_transfer": 0,
83
+ "disposable_card_limits": 0,
84
+ "atm_support": 0,
85
+ "cash_withdrawal_charge": 0,
86
+ "visa_or_mastercard": 0
87
+ },
88
+ "confidence": 0.82
89
+ },
90
+ "usage": {
91
+ "input_tokens": 4387,
92
+ "output_tokens": 826,
93
+ "cost": 0.000184254
94
+ },
95
+ "probability_sum": 1.0,
96
+ "probability_min": 0,
97
+ "probability_max": 0.83,
98
+ "n_probabilities": 77,
99
+ "not_primary": "diagnostic retry, never replaces initial failure"
100
+ },
101
+ {
102
+ "index": 246,
103
+ "status": 200,
104
+ "model": "typesafe/jev-1.13-20260917",
105
+ "answer": {
106
+ "type": "choice",
107
+ "choice": "receiving_money",
108
+ "probabilities": {
109
+ "topping_up_by_card": 0,
110
+ "disposable_card_limits": 0,
111
+ "get_physical_card": 0,
112
+ "card_delivery_estimate": 0,
113
+ "getting_virtual_card": 0,
114
+ "transaction_charged_twice": 0,
115
+ "top_up_failed": 0,
116
+ "get_disposable_virtual_card": 0,
117
+ "verify_source_of_funds": 0,
118
+ "balance_not_updated_after_cheque_or_cash_deposit": 0,
119
+ "why_verify_identity": 0,
120
+ "country_support": 0,
121
+ "transfer_into_account": 0.06,
122
+ "beneficiary_not_allowed": 0,
123
+ "reverted_card_payment?": 0,
124
+ "cash_withdrawal_not_recognised": 0,
125
+ "lost_or_stolen_card": 0,
126
+ "card_payment_not_recognised": 0,
127
+ "cash_withdrawal_charge": 0,
128
+ "contactless_not_working": 0,
129
+ "pending_top_up": 0.01,
130
+ "card_acceptance": 0,
131
+ "pin_blocked": 0,
132
+ "declined_cash_withdrawal": 0,
133
+ "fiat_currency_support": 0,
134
+ "transfer_timing": 0,
135
+ "card_not_working": 0,
136
+ "lost_or_stolen_phone": 0,
137
+ "order_physical_card": 0,
138
+ "edit_personal_details": 0,
139
+ "failed_transfer": 0.01,
140
+ "atm_support": 0,
141
+ "change_pin": 0,
142
+ "receiving_money": 0.55,
143
+ "transfer_fee_charged": 0,
144
+ "Refund_not_showing_up": 0,
145
+ "apple_pay_or_google_pay": 0,
146
+ "card_linking": 0,
147
+ "wrong_amount_of_cash_received": 0,
148
+ "balance_not_updated_after_bank_transfer": 0,
149
+ "transfer_not_received_by_recipient": 0.01,
150
+ "activate_my_card": 0.01,
151
+ "pending_transfer": 0.24000000000000002,
152
+ "top_up_reverted": 0,
153
+ "pending_cash_withdrawal": 0,
154
+ "getting_spare_card": 0,
155
+ "direct_debit_payment_not_recognised": 0,
156
+ "unable_to_verify_identity": 0,
157
+ "verify_my_identity": 0,
158
+ "compromised_card": 0,
159
+ "extra_charge_on_statement": 0,
160
+ "automatic_top_up": 0,
161
+ "cancel_transfer": 0,
162
+ "age_limit": 0,
163
+ "virtual_card_not_working": 0,
164
+ "card_swallowed": 0,
165
+ "card_about_to_expire": 0,
166
+ "exchange_rate": 0,
167
+ "top_up_by_cash_or_cheque": 0,
168
+ "top_up_by_bank_transfer_charge": 0,
169
+ "card_arrival": 0,
170
+ "terminate_account": 0,
171
+ "card_payment_fee_charged": 0,
172
+ "supported_cards_and_currencies": 0,
173
+ "exchange_via_app": 0,
174
+ "top_up_by_card_charge": 0,
175
+ "wrong_exchange_rate_for_cash_withdrawal": 0,
176
+ "exchange_charge": 0,
177
+ "declined_transfer": 0.09999999999999999,
178
+ "request_refund": 0,
179
+ "pending_card_payment": 0,
180
+ "declined_card_payment": 0,
181
+ "visa_or_mastercard": 0,
182
+ "verify_top_up": 0,
183
+ "passcode_forgotten": 0,
184
+ "card_payment_wrong_exchange_rate": 0,
185
+ "top_up_limits": 0
186
+ },
187
+ "confidence": 0.53
188
+ },
189
+ "usage": {
190
+ "input_tokens": 4384,
191
+ "output_tokens": 827,
192
+ "cost": 0.000184128
193
+ },
194
+ "probability_sum": 0.99,
195
+ "probability_min": 0,
196
+ "probability_max": 0.55,
197
+ "n_probabilities": 77,
198
+ "not_primary": "diagnostic retry, never replaces initial failure"
199
+ }
200
+ ]
evidence/banking77/local-test-repeat.jsonl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:00aa8ca8498067c5bd46ae5651f2cd46d901cf12ebdc08b1bf03cb3948669c4f
3
+ size 38296470
evidence/release/build-cpu.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Compiling cortiq-decision v0.1.0 (/Users/oleg/dev/cmfpublic/tools/cortiq-decision)
2
+ Finished `release` profile [optimized] target(s) in 20.34s
3
+ warning: the following packages contain code that will be rejected by a future version of Rust: block v0.1.6
4
+ note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
evidence/release/clippy.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Checking naga v0.19.2
2
+ Checking metal v0.27.0
3
+ Checking metal v0.29.0
4
+ Checking cortiq-core v0.6.8 (/Users/oleg/dev/cmfpublic/crates/cortiq-core)
5
+ Checking wgpu-hal v0.19.5
6
+ Checking wgpu-core v0.19.4
7
+ Checking wgpu v0.19.4
8
+ Checking cortiq-decision v0.1.0 (/Users/oleg/dev/cmfpublic/tools/cortiq-decision)
9
+ Finished `dev` profile [unoptimized + debuginfo] target(s) in 8.24s
10
+ warning: the following packages contain code that will be rejected by a future version of Rust: block v0.1.6
11
+ note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
evidence/release/fcd-incremental-console.txt ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "pass": true,
3
+ "scope": "two incremental topologies; finite held-out tests, not universal no-forgetting theorem",
4
+ "core_and_all_old_tasks_unchanged": true,
5
+ "core_sha256": "3c49b40c29c39dbb6fa5862bfb0d63e7345a0bd38fda144160b162a56f65d3f8",
6
+ "old_controls": 43,
7
+ "old_winner_or_abstention_changes": [],
8
+ "max_old_confidence_delta": 0.0,
9
+ "independent_new_task_test_n": 3080,
10
+ "new_skills": {
11
+ "lost_or_stolen_card": {
12
+ "tp": 16,
13
+ "fp": 0,
14
+ "test_positives": 40,
15
+ "precision": 1.0,
16
+ "recall": 0.4
17
+ },
18
+ "change_pin": {
19
+ "tp": 25,
20
+ "fp": 2,
21
+ "test_positives": 40,
22
+ "precision": 0.9259259259259259,
23
+ "recall": 0.625
24
+ }
25
+ },
26
+ "first_skill_regressions_after_second": [],
27
+ "mean_roundtrip_score_ms": 0.36394813555194844,
28
+ "task_capacity": 24,
29
+ "active_tasks": 10,
30
+ "artifact_sha256": "4beef0e577d29ef52fc0941b7813286aadfe0afe49959d927350988368091e4f",
31
+ "source_embeddings": "Metal F32; same-representation validation reported separately",
32
+ "production_route_replaced": false
33
+ }
evidence/release/isolated-build.txt ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Compiling proc-macro2 v1.0.107
2
+ Compiling quote v1.0.47
3
+ Compiling unicode-ident v1.0.26
4
+ Compiling libc v0.2.189
5
+ Compiling version_check v0.9.5
6
+ Compiling autocfg v1.5.1
7
+ Compiling cfg-if v1.0.5
8
+ Compiling stable_deref_trait v1.2.1
9
+ Compiling find-msvc-tools v0.1.14
10
+ Compiling shlex v2.0.1
11
+ Compiling memchr v2.8.3
12
+ Compiling crossbeam-utils v0.8.23
13
+ Compiling crossbeam-epoch v0.9.21
14
+ Compiling cc v1.5.0
15
+ Compiling writeable v0.6.4
16
+ Compiling generic-array v0.14.7
17
+ Compiling num-traits v0.2.19
18
+ Compiling crossbeam-deque v0.8.8
19
+ Compiling litemap v0.8.3
20
+ Compiling serde_core v1.0.229
21
+ Compiling zerocopy v0.8.58
22
+ Compiling utf8_iter v1.0.4
23
+ Compiling icu_normalizer_data v2.3.0
24
+ Compiling rayon-core v1.13.0
25
+ Compiling icu_properties_data v2.3.0
26
+ Compiling syn v3.0.6
27
+ Compiling syn v2.0.119
28
+ Compiling zeroize v1.9.0
29
+ Compiling ring v0.17.14
30
+ Compiling num-integer v0.1.47
31
+ Compiling rustls-pki-types v1.15.1
32
+ Compiling typenum v1.20.1
33
+ Compiling either v1.18.0
34
+ Compiling serde v1.0.229
35
+ Compiling pkg-config v0.3.34
36
+ Compiling smallvec v1.16.2
37
+ Compiling simd-adler32 v0.3.10
38
+ Compiling paste v1.0.15
39
+ Compiling getrandom v0.2.17
40
+ Compiling thiserror v2.0.21
41
+ Compiling once_cell v1.21.4
42
+ Compiling rustix v1.1.5
43
+ Compiling untrusted v0.9.0
44
+ Compiling rayon v1.12.0
45
+ Compiling errno v0.3.14
46
+ Compiling ident_case v1.0.1
47
+ Compiling strsim v0.11.1
48
+ Compiling log v0.4.34
49
+ Compiling rustls v0.23.45
50
+ Compiling percent-encoding v2.3.2
51
+ Compiling bitflags v2.13.2
52
+ Compiling getrandom v0.3.4
53
+ Compiling fnv v1.0.7
54
+ Compiling crc32fast v1.5.2
55
+ Compiling adler2 v2.0.1
56
+ Compiling anyhow v1.0.104
57
+ Compiling form_urlencoded v1.2.2
58
+ Compiling crypto-common v0.1.7
59
+ Compiling block-buffer v0.10.4
60
+ Compiling webpki-roots v1.0.9
61
+ Compiling num-bigint v0.4.8
62
+ Compiling arrayvec v0.7.8
63
+ Compiling subtle v2.6.1
64
+ Compiling byteorder v1.5.0
65
+ Compiling darling_core v0.20.11
66
+ Compiling miniz_oxide v0.9.1
67
+ Compiling socks v0.3.4
68
+ Compiling synstructure v0.14.0
69
+ Compiling xattr v1.6.1
70
+ Compiling as-slice v0.2.1
71
+ Compiling webpki-roots v0.26.11
72
+ Compiling digest v0.10.7
73
+ Compiling itertools v0.14.0
74
+ Compiling filetime v0.2.29
75
+ Compiling num-rational v0.4.2
76
+ Compiling cpufeatures v0.2.17
77
+ Compiling base64 v0.22.1
78
+ Compiling zmij v1.0.23
79
+ Compiling av-scenechange v0.14.1
80
+ Compiling libm v0.2.16
81
+ Compiling built v0.8.1
82
+ Compiling rustversion v1.0.23
83
+ Compiling zerocopy-derive v0.8.58
84
+ Compiling equator-macro v0.4.2
85
+ Compiling zerofrom-derive v0.1.8
86
+ Compiling yoke-derive v0.8.3
87
+ Compiling zerovec-derive v0.11.6
88
+ Compiling displaydoc v0.2.7
89
+ Compiling bytemuck_derive v1.12.1
90
+ Compiling serde_derive v1.0.229
91
+ Compiling equator v0.4.2
92
+ Compiling thiserror-impl v2.0.21
93
+ Compiling rustls-webpki v0.103.15
94
+ Compiling darling_macro v0.20.11
95
+ Compiling rav1e v0.8.1
96
+ Compiling zerofrom v0.1.8
97
+ Compiling aligned-vec v0.6.4
98
+ Compiling v_frame v0.3.9
99
+ Compiling arg_enum_proc_macro v0.3.4
100
+ Compiling darling v0.20.11
101
+ Compiling profiling-procmacros v1.0.18
102
+ Compiling yoke v0.8.3
103
+ Compiling bytemuck v1.25.2
104
+ Compiling sha2 v0.10.9
105
+ Compiling tar v0.4.46
106
+ Compiling zerovec v0.11.8
107
+ Compiling zerotrie v0.2.5
108
+ Compiling flate2 v1.1.10
109
+ Compiling aligned v0.4.3
110
+ Compiling num-complex v0.4.6
111
+ Compiling onig_sys v69.9.3
112
+ Compiling no_std_io2 v0.9.4
113
+ Compiling nom v8.0.0
114
+ Compiling matrixmultiply v0.3.11
115
+ Compiling pulp v0.22.3
116
+ Compiling quick-error v2.0.1
117
+ Compiling tinystr v0.8.4
118
+ Compiling potential_utf v0.1.6
119
+ Compiling y4m v0.8.0
120
+ Compiling icu_collections v2.3.0
121
+ Compiling icu_locale_core v2.3.0
122
+ Compiling pastey v0.1.1
123
+ Compiling itoa v1.0.18
124
+ Compiling serde_json v1.0.151
125
+ Compiling icu_provider v2.3.1
126
+ Compiling bitstream-io v4.10.0
127
+ Compiling icu_properties v2.3.0
128
+ Compiling icu_normalizer v2.3.0
129
+ Compiling derive_builder_core v0.20.2
130
+ Compiling profiling v1.0.18
131
+ Compiling num-derive v0.4.2
132
+ Compiling tracing-attributes v0.1.31
133
+ Compiling idna_adapter v1.2.2
134
+ Compiling rand_core v0.9.5
135
+ Compiling idna v1.1.0
136
+ Compiling maybe-rayon v0.1.1
137
+ Compiling miniz_oxide v0.8.9
138
+ Compiling tracing-core v0.1.36
139
+ Compiling av1-grain v0.2.5
140
+ Compiling url v2.5.8
141
+ Compiling ppv-lite86 v0.2.21
142
+ Compiling half v2.7.1
143
+ Compiling simd_helpers v0.1.0
144
+ Compiling ureq v2.12.1
145
+ Compiling aho-corasick v1.1.5
146
+ Compiling ahash v0.8.12
147
+ Compiling pulp-wasm-simd-flag v0.1.1
148
+ Compiling reborrow v0.5.5
149
+ Compiling rawpointer v0.2.1
150
+ Compiling weezl v0.1.12
151
+ Compiling new_debug_unreachable v1.0.6
152
+ Compiling noop_proc_macro v0.3.0
153
+ Compiling regex-syntax v0.8.11
154
+ Compiling minimal-lexical v0.2.1
155
+ Compiling zune-core v0.5.3
156
+ Compiling esaxx-rs v0.1.10
157
+ Compiling pin-project-lite v0.2.17
158
+ Compiling utf8parse v0.2.2
159
+ Compiling imgref v1.12.3
160
+ Compiling zune-jpeg v0.5.15
161
+ Compiling loop9 v0.1.5
162
+ Compiling anstyle-parse v1.0.0
163
+ Compiling tracing v0.1.44
164
+ Compiling nom v7.1.3
165
+ Compiling ort-sys v2.0.0-rc.9
166
+ Compiling rand_chacha v0.9.0
167
+ Compiling derive_builder_macro v0.20.2
168
+ Compiling regex-automata v0.4.18
169
+ Compiling castaway v0.2.4
170
+ Compiling monostate-impl v0.1.18
171
+ Compiling avif-serialize v0.8.9
172
+ Compiling zune-inflate v0.2.54
173
+ Compiling fdeflate v0.3.7
174
+ Compiling pxfm v0.1.30
175
+ Compiling getrandom v0.4.3
176
+ Compiling rgb v0.8.53
177
+ Compiling colorchoice v1.0.5
178
+ Compiling ryu v1.0.23
179
+ Compiling bit_field v0.10.3
180
+ Compiling anstyle v1.0.14
181
+ Compiling anstyle-query v1.1.5
182
+ Compiling byteorder-lite v0.1.0
183
+ Compiling color_quant v1.1.0
184
+ Compiling core-foundation-sys v0.8.7
185
+ Compiling unicode-segmentation v1.13.3
186
+ Compiling lebe v0.5.3
187
+ Compiling fax v0.2.7
188
+ Compiling is_terminal_polyfill v1.70.2
189
+ Compiling macro_rules_attribute-proc_macro v0.2.3
190
+ Compiling static_assertions v1.1.0
191
+ Compiling base64 v0.13.1
192
+ Compiling pastey v0.2.3
193
+ Compiling spm_precompiled v0.1.4
194
+ Compiling regex v1.13.1
195
+ Compiling compact_str v0.9.1
196
+ Compiling macro_rules_attribute v0.2.3
197
+ Compiling anstream v1.0.0
198
+ Compiling moxcms v0.8.1
199
+ Compiling tiff v0.11.3
200
+ Compiling core-foundation v0.9.4
201
+ Compiling image-webp v0.2.4
202
+ Compiling gif v0.14.2
203
+ Compiling onig v6.5.3
204
+ Compiling exr v1.74.2
205
+ Compiling png v0.18.1
206
+ Compiling ravif v0.13.0
207
+ Compiling monostate v0.1.18
208
+ Compiling derive_builder v0.20.2
209
+ Compiling ndarray v0.16.1
210
+ Compiling rand v0.9.5
211
+ Compiling dary_heap v0.3.9
212
+ Compiling unicode-normalization-alignments v0.1.12
213
+ Compiling qoi v0.4.1
214
+ Compiling rayon-cond v0.4.0
215
+ Compiling foreign-types-macros v0.2.4
216
+ Compiling malloc_buf v0.0.6
217
+ Compiling bitflags v1.3.2
218
+ Compiling foreign-types-shared v0.3.1
219
+ Compiling unicode_categories v0.1.1
220
+ Compiling clap_lex v1.1.1
221
+ Compiling heck v0.5.0
222
+ Compiling clap_builder v4.6.7
223
+ Compiling tokenizers v0.21.4
224
+ Compiling foreign-types v0.5.0
225
+ Compiling clap_derive v4.6.7
226
+ Compiling core-graphics-types v0.1.3
227
+ Compiling objc v0.2.7
228
+ Compiling image v0.25.10
229
+ Compiling bincode v1.3.3
230
+ Compiling memmap2 v0.9.11
231
+ Compiling block v0.1.6
232
+ Compiling fastrand v2.5.0
233
+ Compiling metal v0.29.0
234
+ Compiling tempfile v3.27.0
235
+ Compiling cortiq-core v0.6.8 (/Users/oleg/dev/cmfpublic/artifacts/hf-private-cortiq-banking77-20260925/source/crates/cortiq-core)
236
+ Compiling clap v4.6.7
237
+ Compiling ort v2.0.0-rc.9
238
+ Compiling fastembed v4.9.1
239
+ Compiling cortiq-decision v0.1.0 (/Users/oleg/dev/cmfpublic/artifacts/hf-private-cortiq-banking77-20260925/source/tools/cortiq-decision)
240
+ Finished `release` profile [optimized] target(s) in 53.59s
241
+ warning: the following packages contain code that will be rejected by a future version of Rust: block v0.1.6
242
+ note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
evidence/release/isolated-infer.json ADDED
@@ -0,0 +1,563 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "decision": {
3
+ "action": "local",
4
+ "choice": "change_pin",
5
+ "confidence": 0.9896446466445923,
6
+ "kind": "choice",
7
+ "reason": "validated_in_domain_confidence_gate",
8
+ "source": "cmf"
9
+ },
10
+ "decision_us": 341.625,
11
+ "encode_us": 3129.75,
12
+ "prediction": {
13
+ "confidence": 0.9896446466445923,
14
+ "is_novel": false,
15
+ "margin": 0.08189558982849121,
16
+ "novelty_score": 0.2757600247859955,
17
+ "raw_confidence": 0.9915828108787537,
18
+ "scores": [
19
+ {
20
+ "probability": 0.9896446466445923,
21
+ "reconstruction_error": 0.008488600142300129,
22
+ "score": 0.9915828108787537,
23
+ "task_id": 23,
24
+ "task_label": "change_pin"
25
+ },
26
+ {
27
+ "probability": 0.010215039364993572,
28
+ "reconstruction_error": 0.09927887469530106,
29
+ "score": 0.9096872210502625,
30
+ "task_id": 51,
31
+ "task_label": "pin_blocked"
32
+ },
33
+ {
34
+ "probability": 0.00014025272685103118,
35
+ "reconstruction_error": 0.18440523743629456,
36
+ "score": 0.8443056344985962,
37
+ "task_id": 40,
38
+ "task_label": "get_physical_card"
39
+ },
40
+ {
41
+ "probability": 7.914153776766852e-10,
42
+ "reconstruction_error": 0.424312561750412,
43
+ "score": 0.7020930647850037,
44
+ "task_id": 28,
45
+ "task_label": "declined_cash_withdrawal"
46
+ },
47
+ {
48
+ "probability": 7.645493682595372e-10,
49
+ "reconstruction_error": 0.4249981939792633,
50
+ "score": 0.7017552852630615,
51
+ "task_id": 16,
52
+ "task_label": "card_not_working"
53
+ },
54
+ {
55
+ "probability": 3.1089619268766244e-13,
56
+ "reconstruction_error": 0.5799899697303772,
57
+ "score": 0.6329154372215271,
58
+ "task_id": 2,
59
+ "task_label": "activate_my_card"
60
+ },
61
+ {
62
+ "probability": 9.239073536174841e-14,
63
+ "reconstruction_error": 0.6040783524513245,
64
+ "score": 0.6234109401702881,
65
+ "task_id": 70,
66
+ "task_label": "verify_my_identity"
67
+ },
68
+ {
69
+ "probability": 9.1371842817628e-14,
70
+ "reconstruction_error": 0.60429847240448,
71
+ "score": 0.6233254075050354,
72
+ "task_id": 11,
73
+ "task_label": "card_about_to_expire"
74
+ },
75
+ {
76
+ "probability": 7.583969801987223e-14,
77
+ "reconstruction_error": 0.6079971194267273,
78
+ "score": 0.6218916177749634,
79
+ "task_id": 44,
80
+ "task_label": "lost_or_stolen_phone"
81
+ },
82
+ {
83
+ "probability": 3.0816024238671316e-14,
84
+ "reconstruction_error": 0.6258750557899475,
85
+ "score": 0.6150534152984619,
86
+ "task_id": 15,
87
+ "task_label": "card_linking"
88
+ },
89
+ {
90
+ "probability": 2.236265405979824e-14,
91
+ "reconstruction_error": 0.6322402954101562,
92
+ "score": 0.6126548647880554,
93
+ "task_id": 46,
94
+ "task_label": "passcode_forgotten"
95
+ },
96
+ {
97
+ "probability": 9.084127662606096e-15,
98
+ "reconstruction_error": 0.650123655796051,
99
+ "score": 0.6060152053833008,
100
+ "task_id": 63,
101
+ "task_label": "topping_up_by_card"
102
+ },
103
+ {
104
+ "probability": 5.97310397283256e-15,
105
+ "reconstruction_error": 0.6584466099739075,
106
+ "score": 0.6029739379882812,
107
+ "task_id": 5,
108
+ "task_label": "atm_support"
109
+ },
110
+ {
111
+ "probability": 3.598285745428677e-15,
112
+ "reconstruction_error": 0.6685075163841248,
113
+ "score": 0.5993379950523376,
114
+ "task_id": 10,
115
+ "task_label": "cancel_transfer"
116
+ },
117
+ {
118
+ "probability": 3.241863810344724e-15,
119
+ "reconstruction_error": 0.6705782413482666,
120
+ "score": 0.598595142364502,
121
+ "task_id": 22,
122
+ "task_label": "cash_withdrawal_not_recognised"
123
+ },
124
+ {
125
+ "probability": 2.1305966058538395e-15,
126
+ "reconstruction_error": 0.6789107918739319,
127
+ "score": 0.5956242680549622,
128
+ "task_id": 74,
129
+ "task_label": "visa_or_mastercard"
130
+ },
131
+ {
132
+ "probability": 2.1219987979227348e-15,
133
+ "reconstruction_error": 0.6789910793304443,
134
+ "score": 0.5955957770347595,
135
+ "task_id": 32,
136
+ "task_label": "edit_personal_details"
137
+ },
138
+ {
139
+ "probability": 1.3099213122148433e-15,
140
+ "reconstruction_error": 0.6885672211647034,
141
+ "score": 0.5922181010246277,
142
+ "task_id": 58,
143
+ "task_label": "top_up_by_card_charge"
144
+ },
145
+ {
146
+ "probability": 9.428964304553978e-16,
147
+ "reconstruction_error": 0.6950936913490295,
148
+ "score": 0.5899379253387451,
149
+ "task_id": 30,
150
+ "task_label": "direct_debit_payment_not_recognised"
151
+ },
152
+ {
153
+ "probability": 8.49311624701092e-16,
154
+ "reconstruction_error": 0.69716876745224,
155
+ "score": 0.5892165899276733,
156
+ "task_id": 4,
157
+ "task_label": "apple_pay_or_google_pay"
158
+ },
159
+ {
160
+ "probability": 7.881772334912497e-16,
161
+ "reconstruction_error": 0.6986517310142517,
162
+ "score": 0.5887022018432617,
163
+ "task_id": 66,
164
+ "task_label": "transfer_into_account"
165
+ },
166
+ {
167
+ "probability": 7.268400308300992e-16,
168
+ "reconstruction_error": 0.7002600431442261,
169
+ "score": 0.5881453156471252,
170
+ "task_id": 57,
171
+ "task_label": "top_up_by_bank_transfer_charge"
172
+ },
173
+ {
174
+ "probability": 6.790677431818711e-16,
175
+ "reconstruction_error": 0.7016096711158752,
176
+ "score": 0.587678849697113,
177
+ "task_id": 20,
178
+ "task_label": "card_swallowed"
179
+ },
180
+ {
181
+ "probability": 6.648165197234359e-16,
182
+ "reconstruction_error": 0.7020307183265686,
183
+ "score": 0.5875334739685059,
184
+ "task_id": 64,
185
+ "task_label": "transaction_charged_twice"
186
+ },
187
+ {
188
+ "probability": 6.24594524948355e-16,
189
+ "reconstruction_error": 0.7032696008682251,
190
+ "score": 0.5871061086654663,
191
+ "task_id": 13,
192
+ "task_label": "card_arrival"
193
+ },
194
+ {
195
+ "probability": 6.086752289189801e-16,
196
+ "reconstruction_error": 0.7037821412086487,
197
+ "score": 0.5869295001029968,
198
+ "task_id": 72,
199
+ "task_label": "verify_top_up"
200
+ },
201
+ {
202
+ "probability": 5.222506573656109e-16,
203
+ "reconstruction_error": 0.7068220973014832,
204
+ "score": 0.5858840942382812,
205
+ "task_id": 25,
206
+ "task_label": "contactless_not_working"
207
+ },
208
+ {
209
+ "probability": 5.214762045540244e-16,
210
+ "reconstruction_error": 0.7068515419960022,
211
+ "score": 0.585874080657959,
212
+ "task_id": 24,
213
+ "task_label": "compromised_card"
214
+ },
215
+ {
216
+ "probability": 3.9380663418352797e-16,
217
+ "reconstruction_error": 0.712425947189331,
218
+ "score": 0.583966851234436,
219
+ "task_id": 49,
220
+ "task_label": "pending_top_up"
221
+ },
222
+ {
223
+ "probability": 3.234709770072214e-16,
224
+ "reconstruction_error": 0.7163317203521729,
225
+ "score": 0.5826379656791687,
226
+ "task_id": 60,
227
+ "task_label": "top_up_failed"
228
+ },
229
+ {
230
+ "probability": 3.193745403858424e-16,
231
+ "reconstruction_error": 0.7165846824645996,
232
+ "score": 0.5825520753860474,
233
+ "task_id": 55,
234
+ "task_label": "supported_cards_and_currencies"
235
+ },
236
+ {
237
+ "probability": 3.038462030011845e-16,
238
+ "reconstruction_error": 0.7175741791725159,
239
+ "score": 0.5822165012359619,
240
+ "task_id": 26,
241
+ "task_label": "country_support"
242
+ },
243
+ {
244
+ "probability": 1.8706714699177342e-16,
245
+ "reconstruction_error": 0.7272031903266907,
246
+ "score": 0.5789706707000732,
247
+ "task_id": 9,
248
+ "task_label": "beneficiary_not_allowed"
249
+ },
250
+ {
251
+ "probability": 1.7863763391937624e-16,
252
+ "reconstruction_error": 0.7281184792518616,
253
+ "score": 0.5786640644073486,
254
+ "task_id": 29,
255
+ "task_label": "declined_transfer"
256
+ },
257
+ {
258
+ "probability": 1.26695283957807e-16,
259
+ "reconstruction_error": 0.73493891954422,
260
+ "score": 0.5763891935348511,
261
+ "task_id": 59,
262
+ "task_label": "top_up_by_cash_or_cheque"
263
+ },
264
+ {
265
+ "probability": 1.2314581886211745e-16,
266
+ "reconstruction_error": 0.735503077507019,
267
+ "score": 0.5762017965316772,
268
+ "task_id": 45,
269
+ "task_label": "order_physical_card"
270
+ },
271
+ {
272
+ "probability": 9.471752041535631e-17,
273
+ "reconstruction_error": 0.7407134771347046,
274
+ "score": 0.5744770765304565,
275
+ "task_id": 35,
276
+ "task_label": "exchange_via_app"
277
+ },
278
+ {
279
+ "probability": 8.866139366116567e-17,
280
+ "reconstruction_error": 0.7420251369476318,
281
+ "score": 0.5740445256233215,
282
+ "task_id": 38,
283
+ "task_label": "fiat_currency_support"
284
+ },
285
+ {
286
+ "probability": 8.101340083150859e-17,
287
+ "reconstruction_error": 0.7438158988952637,
288
+ "score": 0.5734550356864929,
289
+ "task_id": 12,
290
+ "task_label": "card_acceptance"
291
+ },
292
+ {
293
+ "probability": 7.162347151093323e-17,
294
+ "reconstruction_error": 0.746261477470398,
295
+ "score": 0.5726519227027893,
296
+ "task_id": 41,
297
+ "task_label": "getting_spare_card"
298
+ },
299
+ {
300
+ "probability": 6.075173745847528e-17,
301
+ "reconstruction_error": 0.7495295405387878,
302
+ "score": 0.5715821981430054,
303
+ "task_id": 54,
304
+ "task_label": "reverted_card_payment?"
305
+ },
306
+ {
307
+ "probability": 5.729981350061799e-17,
308
+ "reconstruction_error": 0.7506908178329468,
309
+ "score": 0.5712031126022339,
310
+ "task_id": 53,
311
+ "task_label": "request_refund"
312
+ },
313
+ {
314
+ "probability": 4.684637806648321e-17,
315
+ "reconstruction_error": 0.7546893954277039,
316
+ "score": 0.5699014067649841,
317
+ "task_id": 52,
318
+ "task_label": "receiving_money"
319
+ },
320
+ {
321
+ "probability": 4.108285487345463e-17,
322
+ "reconstruction_error": 0.757295548915863,
323
+ "score": 0.5690562129020691,
324
+ "task_id": 36,
325
+ "task_label": "extra_charge_on_statement"
326
+ },
327
+ {
328
+ "probability": 3.7374270006411935e-17,
329
+ "reconstruction_error": 0.7591736316680908,
330
+ "score": 0.5684487223625183,
331
+ "task_id": 18,
332
+ "task_label": "card_payment_not_recognised"
333
+ },
334
+ {
335
+ "probability": 3.4640395068532325e-17,
336
+ "reconstruction_error": 0.7606815695762634,
337
+ "score": 0.5679618716239929,
338
+ "task_id": 75,
339
+ "task_label": "why_verify_identity"
340
+ },
341
+ {
342
+ "probability": 3.1090205362626185e-17,
343
+ "reconstruction_error": 0.7628280520439148,
344
+ "score": 0.5672702789306641,
345
+ "task_id": 65,
346
+ "task_label": "transfer_fee_charged"
347
+ },
348
+ {
349
+ "probability": 2.6817489935267226e-17,
350
+ "reconstruction_error": 0.7657629251480103,
351
+ "score": 0.5663274526596069,
352
+ "task_id": 43,
353
+ "task_label": "lost_or_stolen_card"
354
+ },
355
+ {
356
+ "probability": 2.41980273109935e-17,
357
+ "reconstruction_error": 0.7678033113479614,
358
+ "score": 0.5656737685203552,
359
+ "task_id": 71,
360
+ "task_label": "verify_source_of_funds"
361
+ },
362
+ {
363
+ "probability": 2.2321369568069945e-17,
364
+ "reconstruction_error": 0.7694058418273926,
365
+ "score": 0.5651614665985107,
366
+ "task_id": 14,
367
+ "task_label": "card_delivery_estimate"
368
+ },
369
+ {
370
+ "probability": 1.9210611290776476e-17,
371
+ "reconstruction_error": 0.7723851799964905,
372
+ "score": 0.5642114877700806,
373
+ "task_id": 27,
374
+ "task_label": "declined_card_payment"
375
+ },
376
+ {
377
+ "probability": 1.79934944287435e-17,
378
+ "reconstruction_error": 0.7736845016479492,
379
+ "score": 0.5637981295585632,
380
+ "task_id": 6,
381
+ "task_label": "automatic_top_up"
382
+ },
383
+ {
384
+ "probability": 1.0062334514352361e-17,
385
+ "reconstruction_error": 0.7852223515510559,
386
+ "score": 0.5601543188095093,
387
+ "task_id": 69,
388
+ "task_label": "unable_to_verify_identity"
389
+ },
390
+ {
391
+ "probability": 9.012251060592832e-18,
392
+ "reconstruction_error": 0.787410318851471,
393
+ "score": 0.5594686269760132,
394
+ "task_id": 31,
395
+ "task_label": "disposable_card_limits"
396
+ },
397
+ {
398
+ "probability": 5.8391593474695095e-18,
399
+ "reconstruction_error": 0.7960257530212402,
400
+ "score": 0.5567848682403564,
401
+ "task_id": 68,
402
+ "task_label": "transfer_timing"
403
+ },
404
+ {
405
+ "probability": 5.441096462061535e-18,
406
+ "reconstruction_error": 0.7974274158477783,
407
+ "score": 0.5563507080078125,
408
+ "task_id": 1,
409
+ "task_label": "Refund_not_showing_up"
410
+ },
411
+ {
412
+ "probability": 5.384089655786218e-18,
413
+ "reconstruction_error": 0.7976365089416504,
414
+ "score": 0.5562859773635864,
415
+ "task_id": 21,
416
+ "task_label": "cash_withdrawal_charge"
417
+ },
418
+ {
419
+ "probability": 3.9270064572806905e-18,
420
+ "reconstruction_error": 0.8039010167121887,
421
+ "score": 0.5543541312217712,
422
+ "task_id": 77,
423
+ "task_label": "wrong_exchange_rate_for_cash_withdrawal"
424
+ },
425
+ {
426
+ "probability": 3.763549777975924e-18,
427
+ "reconstruction_error": 0.8047450184822083,
428
+ "score": 0.5540949106216431,
429
+ "task_id": 62,
430
+ "task_label": "top_up_reverted"
431
+ },
432
+ {
433
+ "probability": 3.416622164060212e-18,
434
+ "reconstruction_error": 0.8066648244857788,
435
+ "score": 0.553506076335907,
436
+ "task_id": 67,
437
+ "task_label": "transfer_not_received_by_recipient"
438
+ },
439
+ {
440
+ "probability": 2.2661367683199148e-18,
441
+ "reconstruction_error": 0.8148153424263,
442
+ "score": 0.5510202646255493,
443
+ "task_id": 17,
444
+ "task_label": "card_payment_fee_charged"
445
+ },
446
+ {
447
+ "probability": 2.0517483039535742e-18,
448
+ "reconstruction_error": 0.8167883157730103,
449
+ "score": 0.5504218339920044,
450
+ "task_id": 76,
451
+ "task_label": "wrong_amount_of_cash_received"
452
+ },
453
+ {
454
+ "probability": 1.8268895941886905e-18,
455
+ "reconstruction_error": 0.8190926313400269,
456
+ "score": 0.5497246384620667,
457
+ "task_id": 39,
458
+ "task_label": "get_disposable_virtual_card"
459
+ },
460
+ {
461
+ "probability": 1.237229758627202e-18,
462
+ "reconstruction_error": 0.8268294930458069,
463
+ "score": 0.5473964810371399,
464
+ "task_id": 48,
465
+ "task_label": "pending_cash_withdrawal"
466
+ },
467
+ {
468
+ "probability": 1.2356354713940826e-18,
469
+ "reconstruction_error": 0.8268551230430603,
470
+ "score": 0.5473887920379639,
471
+ "task_id": 3,
472
+ "task_label": "age_limit"
473
+ },
474
+ {
475
+ "probability": 1.1729103655441865e-18,
476
+ "reconstruction_error": 0.8278892636299133,
477
+ "score": 0.5470790863037109,
478
+ "task_id": 7,
479
+ "task_label": "balance_not_updated_after_bank_transfer"
480
+ },
481
+ {
482
+ "probability": 8.206558118812094e-19,
483
+ "reconstruction_error": 0.8349790573120117,
484
+ "score": 0.5449653267860413,
485
+ "task_id": 8,
486
+ "task_label": "balance_not_updated_after_cheque_or_cash_deposit"
487
+ },
488
+ {
489
+ "probability": 5.197417222011962e-19,
490
+ "reconstruction_error": 0.8440465927124023,
491
+ "score": 0.5422856211662292,
492
+ "task_id": 56,
493
+ "task_label": "terminate_account"
494
+ },
495
+ {
496
+ "probability": 3.4778196224150877e-19,
497
+ "reconstruction_error": 0.8520220518112183,
498
+ "score": 0.5399503707885742,
499
+ "task_id": 19,
500
+ "task_label": "card_payment_wrong_exchange_rate"
501
+ },
502
+ {
503
+ "probability": 1.4447798950201726e-19,
504
+ "reconstruction_error": 0.8694605231285095,
505
+ "score": 0.5349136590957642,
506
+ "task_id": 73,
507
+ "task_label": "virtual_card_not_working"
508
+ },
509
+ {
510
+ "probability": 1.3004934883028408e-19,
511
+ "reconstruction_error": 0.8715491890907288,
512
+ "score": 0.5343167185783386,
513
+ "task_id": 61,
514
+ "task_label": "top_up_limits"
515
+ },
516
+ {
517
+ "probability": 9.606922809335173e-20,
518
+ "reconstruction_error": 0.8775610327720642,
519
+ "score": 0.5326058268547058,
520
+ "task_id": 47,
521
+ "task_label": "pending_card_payment"
522
+ },
523
+ {
524
+ "probability": 7.423343060545055e-20,
525
+ "reconstruction_error": 0.88267982006073,
526
+ "score": 0.5311577916145325,
527
+ "task_id": 37,
528
+ "task_label": "failed_transfer"
529
+ },
530
+ {
531
+ "probability": 3.906830901755063e-20,
532
+ "reconstruction_error": 0.8954225182533264,
533
+ "score": 0.5275868773460388,
534
+ "task_id": 33,
535
+ "task_label": "exchange_charge"
536
+ },
537
+ {
538
+ "probability": 2.227829226359017e-20,
539
+ "reconstruction_error": 0.9065731167793274,
540
+ "score": 0.5245012640953064,
541
+ "task_id": 50,
542
+ "task_label": "pending_transfer"
543
+ },
544
+ {
545
+ "probability": 1.988301066197745e-21,
546
+ "reconstruction_error": 0.9545407891273499,
547
+ "score": 0.5116291642189026,
548
+ "task_id": 34,
549
+ "task_label": "exchange_rate"
550
+ },
551
+ {
552
+ "probability": 1.2283238770365118e-24,
553
+ "reconstruction_error": 1.1012307405471802,
554
+ "score": 0.47591158747673035,
555
+ "task_id": 42,
556
+ "task_label": "getting_virtual_card"
557
+ }
558
+ ],
559
+ "task_id": 23,
560
+ "task_label": "change_pin"
561
+ },
562
+ "representation_id": "e5991f3eff5987b1ad5228b158682be638c7944fcd891bc30b461c4079f387d2"
563
+ }
evidence/release/lifecycle-console.txt ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "job_status": "accepted_candidate",
3
+ "result": {
4
+ "baseline_generation": "33122a0fb5964d529e40feea484addb3",
5
+ "contract_id": "17876d9ff9eafc7bae3d9b4ca90f91e4b261c80c5851ef2f6f08ec664ee4061e",
6
+ "entry": {
7
+ "artifact_sha256": "e0238e945abc6a7d18d8138636ca05669590b23ecef88a600751e6b06ab957e3",
8
+ "backend": "affine",
9
+ "contract": {
10
+ "criteria": {
11
+ "false": "A request to solve arithmetic",
12
+ "true": "A request to translate text"
13
+ },
14
+ "input_template": "text-v1",
15
+ "instructions": "Functional fixture: is the text a request to translate rather than calculate?",
16
+ "type": "binary"
17
+ },
18
+ "legacy_adapter": false,
19
+ "max_novelty": 1.0,
20
+ "min_confidence": 0.0,
21
+ "min_margin": 0.0,
22
+ "model": "/Users/oleg/dev/cmfpublic/tmp/decision-lifecycle-fixture-6e4eb06d/candidates/13008a306bc649ca9a6be0573874fa88/model.cmf",
23
+ "name": "SYNTHETIC binary lifecycle fixture",
24
+ "policy_file": "/Users/oleg/dev/cmfpublic/tmp/decision-lifecycle-fixture-6e4eb06d/candidates/13008a306bc649ca9a6be0573874fa88/trained/policy.json",
25
+ "tenant": "default"
26
+ },
27
+ "metrics": {
28
+ "accuracy": 1.0,
29
+ "coverage": 1.0,
30
+ "old_controls_checked": 0,
31
+ "route_controls_n": 43,
32
+ "selective_accuracy": 1.0
33
+ },
34
+ "passed": true,
35
+ "report_path": "/Users/oleg/dev/cmfpublic/tmp/decision-lifecycle-fixture-6e4eb06d/candidates/13008a306bc649ca9a6be0573874fa88/acceptance.json",
36
+ "report_sha256": "b43e607837aadf6bc70e45dbe5692b396ea44a152f60b8f50044e93bf765c477"
37
+ }
38
+ }
evidence/release/live-release-status.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "models": [
3
+ {
4
+ "name": "task-routing",
5
+ "backend": "affine",
6
+ "type": "choice"
7
+ },
8
+ {
9
+ "name": "agent-tool-selection",
10
+ "backend": "affine",
11
+ "type": "choice"
12
+ },
13
+ {
14
+ "name": "banking-support-intent",
15
+ "backend": "affine",
16
+ "type": "choice"
17
+ },
18
+ {
19
+ "name": "fcd-incremental-skills",
20
+ "backend": "fcd",
21
+ "type": "choice"
22
+ }
23
+ ],
24
+ "generation": "b38a26d1be634f908cfbd6b48ed9ddf8",
25
+ "oracle_configured": true,
26
+ "oracle_model": "typesafe/jev-1.13",
27
+ "persisted_controls": 123,
28
+ "ui_file_absent": true,
29
+ "isolation_build_passed": true,
30
+ "current_article": "/Users/oleg/dev/cmfpublic/docs/decision/ARTICLE_RU.md"
31
+ }
evidence/release/metal-acceptance-console.txt ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...
2
+ To disable this warning, you can either:
3
+ - Avoid using `tokenizers` before the fork if possible
4
+ - Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
5
+ test 0
6
+ test 500
7
+ test 1000
8
+ test 1500
9
+ test 2000
10
+ test 2500
11
+ test 3000
12
+ huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...
13
+ To disable this warning, you can either:
14
+ - Avoid using `tokenizers` before the fork if possible
15
+ - Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
16
+ huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...
17
+ To disable this warning, you can either:
18
+ - Avoid using `tokenizers` before the fork if possible
19
+ - Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
20
+ {
21
+ "backend": "mlx-metal-f32 (encoder); Rust packed CPU (decision)",
22
+ "test_n": 3080,
23
+ "correct": 2818,
24
+ "accuracy": 0.9149350649350649,
25
+ "winner_changes": [],
26
+ "gate_changes_at_085": [],
27
+ "novelty_changes": [],
28
+ "max_confidence_delta": 3.337860107421875e-06,
29
+ "probe_max_abs_embedding_delta": 1.993030309677124e-07,
30
+ "accepted": 2284,
31
+ "accepted_correct": 2254,
32
+ "selective_accuracy": 0.9868651488616462,
33
+ "warm_wall_ms": {
34
+ "p50": 7.799104000241641,
35
+ "p95": 11.332041650030076,
36
+ "p99": 12.547094820120039
37
+ },
38
+ "batch_encoder_dev": [
39
+ {
40
+ "batch": 1,
41
+ "median_ms": 4.802416499842366,
42
+ "texts_per_second": 208.22850330304004
43
+ },
44
+ {
45
+ "batch": 8,
46
+ "median_ms": 12.841916500292427,
47
+ "texts_per_second": 622.9599764036644
48
+ },
49
+ {
50
+ "batch": 32,
51
+ "median_ms": 43.0315840003459,
52
+ "texts_per_second": 743.639834400304
53
+ },
54
+ {
55
+ "batch": 128,
56
+ "median_ms": 173.48837500003356,
57
+ "texts_per_second": 737.8015962163184
58
+ }
59
+ ],
60
+ "memory_samples": [
61
+ {
62
+ "index": 0,
63
+ "python_rss": 1545519104,
64
+ "rust_rss": 895680512,
65
+ "metal_active": 470025172,
66
+ "metal_cache": 380062036
67
+ },
68
+ {
69
+ "index": 500,
70
+ "python_rss": 1551564800,
71
+ "rust_rss": 895680512,
72
+ "metal_active": 470025708,
73
+ "metal_cache": 389108908
74
+ },
75
+ {
76
+ "index": 1000,
77
+ "python_rss": 1556037632,
78
+ "rust_rss": 895680512,
79
+ "metal_active": 470026088,
80
+ "metal_cache": 412656268
81
+ },
82
+ {
83
+ "index": 1500,
84
+ "python_rss": 1556578304,
85
+ "rust_rss": 895680512,
86
+ "metal_active": 470026112,
87
+ "metal_cache": 412656268
88
+ },
89
+ {
90
+ "index": 2000,
91
+ "python_rss": 1558413312,
92
+ "rust_rss": 895680512,
93
+ "metal_active": 470026208,
94
+ "metal_cache": 413737612
95
+ },
96
+ {
97
+ "index": 2500,
98
+ "python_rss": 1027850240,
99
+ "rust_rss": 895680512,
100
+ "metal_active": 470026256,
101
+ "metal_cache": 431434444
102
+ },
103
+ {
104
+ "index": 3000,
105
+ "python_rss": 1028276224,
106
+ "rust_rss": 895680512,
107
+ "metal_active": 470026280,
108
+ "metal_cache": 431434444
109
+ }
110
+ ],
111
+ "python_peak_rss_bytes": 1559003136,
112
+ "no_result_cache": true,
113
+ "compiler_warmed_on_dev_only": true,
114
+ "artifact_sha256": "bc0393616aed93b26862a04fd61f78cb79245ad122dcbe3b3e3fd2620f64f9d3",
115
+ "platform": "macOS-27.2-arm64-arm-64bit",
116
+ "pass": true
117
+ }
evidence/release/near-duplicate-console.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "audit": "post-hoc character 4-gram Jaccard vs fitted TRAIN only",
3
+ "threshold": 0.8,
4
+ "test_n": 3080,
5
+ "train_n": 6996,
6
+ "flagged": 95,
7
+ "posthoc_unflagged_n": 2985,
8
+ "posthoc_unflagged_cmf_accuracy": 0.91356783919598,
9
+ "no_retraining_no_test_change": true,
10
+ "semantic_duplicates_and_encoder_pretraining_contamination_not_ruled_out": true
11
+ }
evidence/release/python-tests.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ .................................
2
+ ----------------------------------------------------------------------
3
+ Ran 33 tests in 0.042s
4
+
5
+ OK
evidence/release/release-acceptance-console.txt ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "passed": true,
3
+ "test_n": 3080,
4
+ "old_controls_n": 43,
5
+ "old_changes": [],
6
+ "release_prediction_mismatches": {
7
+ "banking": 0,
8
+ "fcd": 0
9
+ },
10
+ "artifact_sha256": {
11
+ "banking": "4cdaf9ec19054f17cd34d420a56f4c8bb0eed12c2429732e9baf902ef52303df",
12
+ "fcd": "62270619d5c54474ee841abd411349ffd2d0a882b95ef61bb8594b2495759c74"
13
+ },
14
+ "input_artifact_sha256": {
15
+ "banking": "bc0393616aed93b26862a04fd61f78cb79245ad122dcbe3b3e3fd2620f64f9d3",
16
+ "fcd": "4beef0e577d29ef52fc0941b7813286aadfe0afe49959d927350988368091e4f"
17
+ },
18
+ "scope": "contract-bound export is decision-identical to evaluated models; packaging is not retraining"
19
+ }
evidence/release/runtime-cpu-console-final.txt ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "mode": "cpu",
3
+ "dataset": "first 128 DEV, 3 passes, not quality evaluation",
4
+ "scope": "Python Worker roundtrip includes JSON IPC, encoding, decision, no HTTP",
5
+ "p50_ms": 6.097750499975518,
6
+ "p95_ms": 12.997524949696526,
7
+ "p99_ms": 19.843087499630208,
8
+ "memory_after_single_workload": {
9
+ "python_rss": 50249728,
10
+ "rust_rss": 1736048640
11
+ },
12
+ "batch_encoder": [
13
+ {
14
+ "batch": 1,
15
+ "p50_ms": 4.170291500486201,
16
+ "texts_per_sec": 239.7913910534583
17
+ },
18
+ {
19
+ "batch": 8,
20
+ "p50_ms": 73.517583499779,
21
+ "texts_per_sec": 108.81750486295635
22
+ },
23
+ {
24
+ "batch": 32,
25
+ "p50_ms": 275.66524950088933,
26
+ "texts_per_sec": 116.08282167570331
27
+ },
28
+ {
29
+ "batch": 128,
30
+ "p50_ms": 945.4263545003414,
31
+ "texts_per_sec": 135.38865231617973
32
+ }
33
+ ],
34
+ "discard_duplicate_cmf_encoder_mappings": true
35
+ }
evidence/release/runtime-cpu-console.txt ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "mode": "cpu",
3
+ "dataset": "first 128 DEV, 3 passes, not quality evaluation",
4
+ "scope": "Python Worker roundtrip includes JSON IPC, encoding, decision, no HTTP",
5
+ "p50_ms": 6.574583499059372,
6
+ "p95_ms": 12.957724899570163,
7
+ "p99_ms": 16.551455000044378,
8
+ "memory_after_single_workload": {
9
+ "python_rss": 529547264,
10
+ "rust_rss": 1730215936
11
+ },
12
+ "batch_encoder": [
13
+ {
14
+ "batch": 1,
15
+ "p50_ms": 5.3011249992778176,
16
+ "texts_per_sec": 188.63920396825804
17
+ },
18
+ {
19
+ "batch": 8,
20
+ "p50_ms": 77.20885399976396,
21
+ "texts_per_sec": 103.6150594855929
22
+ },
23
+ {
24
+ "batch": 32,
25
+ "p50_ms": 296.38806250022753,
26
+ "texts_per_sec": 107.96656157491307
27
+ },
28
+ {
29
+ "batch": 128,
30
+ "p50_ms": 1050.3822495002169,
31
+ "texts_per_sec": 121.86039897466257
32
+ }
33
+ ],
34
+ "discard_duplicate_cmf_encoder_mappings": true
35
+ }
evidence/release/runtime-metal-console-final.txt ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "mode": "metal",
3
+ "dataset": "first 128 DEV, 3 passes, not quality evaluation",
4
+ "scope": "Python Worker roundtrip includes JSON IPC, encoding, decision, no HTTP",
5
+ "p50_ms": 6.139041500318854,
6
+ "p95_ms": 11.730420550338748,
7
+ "p99_ms": 12.415499999715397,
8
+ "memory_after_single_workload": {
9
+ "python_rss": 934805504,
10
+ "rust_rss": 18153472
11
+ },
12
+ "batch_encoder": [
13
+ {
14
+ "batch": 1,
15
+ "p50_ms": 4.852812000535778,
16
+ "texts_per_sec": 206.0660911425364
17
+ },
18
+ {
19
+ "batch": 8,
20
+ "p50_ms": 16.870395499609003,
21
+ "texts_per_sec": 474.2034648912298
22
+ },
23
+ {
24
+ "batch": 32,
25
+ "p50_ms": 48.76266700011911,
26
+ "texts_per_sec": 656.2397417664181
27
+ },
28
+ {
29
+ "batch": 128,
30
+ "p50_ms": 190.6259585002772,
31
+ "texts_per_sec": 671.4720335416116
32
+ }
33
+ ],
34
+ "discard_duplicate_cmf_encoder_mappings": true,
35
+ "metal": {
36
+ "active": 470025164,
37
+ "cache": 71008256,
38
+ "peak": 2090107852,
39
+ "cache_limit": 67108864
40
+ }
41
+ }
evidence/release/runtime-metal-console.txt ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "mode": "metal",
3
+ "dataset": "first 128 DEV, 3 passes, not quality evaluation",
4
+ "scope": "Python Worker roundtrip includes JSON IPC, encoding, decision, no HTTP",
5
+ "p50_ms": 6.0803545002272585,
6
+ "p95_ms": 11.632976849159604,
7
+ "p99_ms": 14.136444029682028,
8
+ "memory_after_single_workload": {
9
+ "python_rss": 1426259968,
10
+ "rust_rss": 18186240
11
+ },
12
+ "batch_encoder": [
13
+ {
14
+ "batch": 1,
15
+ "p50_ms": 2.4183749992516823,
16
+ "texts_per_sec": 413.5008012857518
17
+ },
18
+ {
19
+ "batch": 8,
20
+ "p50_ms": 12.943416500093008,
21
+ "texts_per_sec": 618.07483363782
22
+ },
23
+ {
24
+ "batch": 32,
25
+ "p50_ms": 54.572499499954574,
26
+ "texts_per_sec": 586.3759273116423
27
+ },
28
+ {
29
+ "batch": 128,
30
+ "p50_ms": 213.30472950012336,
31
+ "texts_per_sec": 600.0804590688927
32
+ }
33
+ ],
34
+ "discard_duplicate_cmf_encoder_mappings": true,
35
+ "metal": {
36
+ "active": 470025016,
37
+ "cache": 71008256,
38
+ "peak": 2090107704,
39
+ "cache_limit": 67108864
40
+ }
41
+ }
evidence/release/rust-tests.txt ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Compiling cortiq-decision v0.1.0 (/Users/oleg/dev/cmfpublic/tools/cortiq-decision)
2
+ Finished `release` profile [optimized] target(s) in 8.33s
3
+ warning: the following packages contain code that will be rejected by a future version of Rust: block v0.1.6
4
+ note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
5
+ Running unittests src/lib.rs (tools/cortiq-decision/target/release/deps/cortiq_decision-1874dc25976d455a)
6
+
7
+ running 4 tests
8
+ test fcd::tests::support_bound_rejects_invalid_calibration ... ok
9
+ test fcd::tests::reconstruct_and_select_without_materializing_dense_matrix ... ok
10
+ test fcd::tests::unsupported_task_does_not_dilute_old_confidence ... ok
11
+ test fcd::tests::core_and_orthogonality_fail_closed ... ok
12
+
13
+ test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
14
+
15
+ Running unittests src/main.rs (tools/cortiq-decision/target/release/deps/cortiq_decision-e59f30d0f1db229c)
16
+
17
+ running 0 tests
18
+
19
+ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
20
+
21
+ Running tests/contracts.rs (tools/cortiq-decision/target/release/deps/contracts-ef6555562fe91b1e)
22
+
23
+ running 8 tests
24
+ test empty_active_set_abstains_and_stable_ties ... ok
25
+ test rejects_invalid_shapes_numbers_and_calibration ... ok
26
+ test packed_exact_nonorthogonal_variable_rank_and_tail ... ok
27
+ test roundtrip_f32_flags_identity_and_legacy_reader ... ok
28
+ test policy_binds_model_and_abstains_without_gate ... ok
29
+ test exporter_does_not_overwrite ... ok
30
+ test corrupted_payload_and_missing_feature_refused ... ok
31
+ test metal_handles_dimension_tail_variable_rank_and_batch ... ok
32
+
33
+ test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s
34
+
35
+ Doc-tests cortiq_decision
36
+
37
+ running 0 tests
38
+
39
+ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
40
+
evidence/release/vulkan-acceptance.json ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "accepted": 2284,
3
+ "accepted_correct": 2254,
4
+ "adapter": "NVIDIA RTX PRO 4000 Blackwell / NVIDIA 595.91.07 / Vulkan",
5
+ "correct": 2818,
6
+ "gate_changes": 0,
7
+ "max_abs_error": 1.430511474609375e-6,
8
+ "model_sha256": "4cdaf9ec19054f17cd34d420a56f4c8bb0eed12c2429732e9baf902ef52303df",
9
+ "pass": true,
10
+ "resident_buffer_bytes": 4178756,
11
+ "scope": "resident decision scorer only; precomputed same-representation embeddings; upload/submit/wait/readback included; encoder NOT measured",
12
+ "test_n": 3080,
13
+ "timing": [
14
+ {
15
+ "batch": 1,
16
+ "cpu_p50_us": 929.503,
17
+ "cpu_p95_us": 1018.4110000000001,
18
+ "vulkan_p50_us": 1407.564,
19
+ "vulkan_p95_us": 3020.487
20
+ },
21
+ {
22
+ "batch": 8,
23
+ "cpu_p50_us": 7172.128,
24
+ "cpu_p95_us": 7534.2339999999995,
25
+ "vulkan_p50_us": 1303.231,
26
+ "vulkan_p95_us": 3771.9860000000003
27
+ },
28
+ {
29
+ "batch": 32,
30
+ "cpu_p50_us": 28570.895999999997,
31
+ "cpu_p95_us": 29261.018,
32
+ "vulkan_p50_us": 1501.221,
33
+ "vulkan_p95_us": 2035.341
34
+ },
35
+ {
36
+ "batch": 128,
37
+ "cpu_p50_us": 114625.38799999999,
38
+ "cpu_p95_us": 116469.27,
39
+ "vulkan_p50_us": 2189.832,
40
+ "vulkan_p95_us": 3748.502
41
+ }
42
+ ],
43
+ "winner_changes": 0
44
+ }
evidence/release/vulkan-check-macos.txt ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Updating crates.io index
2
+ Locking 72 packages to latest Rust 1.96.0 compatible versions
3
+ Adding allocator-api2 v0.2.21
4
+ Adding android_system_properties v0.1.6
5
+ Adding ash v0.37.3+1.3.251
6
+ Adding bit-set v0.5.3
7
+ Adding bit-vec v0.6.3
8
+ Adding cfg_aliases v0.1.1
9
+ Adding codespan-reporting v0.11.1
10
+ Adding com v0.6.0
11
+ Adding com_macros v0.6.0
12
+ Adding com_macros_support v0.6.0
13
+ Adding d3d12 v0.19.0
14
+ Adding equivalent v1.0.2
15
+ Adding futures-core v0.3.34
16
+ Adding futures-task v0.3.34
17
+ Adding futures-util v0.3.34
18
+ Adding gl_generator v0.14.0
19
+ Adding glow v0.13.1
20
+ Adding glutin_wgl_sys v0.5.0
21
+ Adding gpu-alloc v0.6.2
22
+ Adding gpu-alloc-types v0.3.1
23
+ Adding gpu-allocator v0.25.0
24
+ Adding gpu-descriptor v0.2.4
25
+ Adding gpu-descriptor-types v0.1.2
26
+ Adding hashbrown v0.14.5
27
+ Adding hashbrown v0.17.1
28
+ Adding hassle-rs v0.11.0
29
+ Adding hexf-parse v0.2.1
30
+ Adding indexmap v2.14.2
31
+ Adding jni-sys v0.3.1
32
+ Adding jni-sys v0.4.1
33
+ Adding jni-sys-macros v0.4.1
34
+ Adding js-sys v0.3.106
35
+ Adding khronos-egl v6.0.0
36
+ Adding khronos_api v3.1.0
37
+ Adding libloading v0.7.4
38
+ Adding libloading v0.8.9
39
+ Adding lock_api v0.4.14
40
+ Adding metal v0.27.0
41
+ Adding naga v0.19.2
42
+ Adding ndk-sys v0.5.0+25.2.9519653
43
+ Adding objc_exception v0.1.2
44
+ Adding parking_lot v0.12.5
45
+ Adding parking_lot_core v0.9.12
46
+ Adding pollster v0.3.0 (available: v1.0.1)
47
+ Adding presser v0.3.1
48
+ Adding range-alloc v0.1.5
49
+ Adding raw-window-handle v0.6.2
50
+ Adding redox_syscall v0.5.18
51
+ Adding renderdoc-sys v1.1.0
52
+ Adding rustc-hash v1.1.0
53
+ Adding scopeguard v1.2.0
54
+ Adding slab v0.4.12
55
+ Adding slotmap v1.1.1
56
+ Adding spirv v0.3.0+sdk-1.3.268.0
57
+ Adding syn v1.0.109
58
+ Adding termcolor v1.4.1
59
+ Adding thiserror v1.0.69
60
+ Adding thiserror-impl v1.0.69
61
+ Adding tokio v1.53.1
62
+ Adding unicode-width v0.1.14
63
+ Adding unicode-xid v0.2.6
64
+ Adding wasm-bindgen-futures v0.4.79
65
+ Adding web-sys v0.3.106
66
+ Adding wgpu v0.19.4 (available: v30.0.1)
67
+ Adding wgpu-core v0.19.4
68
+ Adding wgpu-hal v0.19.5
69
+ Adding wgpu-types v0.19.2
70
+ Adding widestring v1.2.1
71
+ Adding winapi-util v0.1.11
72
+ Adding windows v0.52.0
73
+ Adding windows-core v0.52.0
74
+ Adding xml-rs v0.8.29
75
+ Downloading crates ...
76
+ Downloaded pollster v0.3.0
77
+ Compiling cfg_aliases v0.1.1
78
+ Compiling objc_exception v0.1.2
79
+ Compiling num-traits v0.2.19
80
+ Compiling parking_lot_core v0.9.12
81
+ Compiling thiserror v1.0.69
82
+ Compiling syn v3.0.6
83
+ Compiling serde_core v1.0.229
84
+ Compiling thiserror-impl v1.0.69
85
+ Checking bit-vec v0.6.3
86
+ Checking scopeguard v1.2.0
87
+ Checking hashbrown v0.17.1
88
+ Checking termcolor v1.4.1
89
+ Checking unicode-width v0.1.14
90
+ Checking equivalent v1.0.2
91
+ Checking bit-set v0.5.3
92
+ Checking codespan-reporting v0.11.1
93
+ Checking lock_api v0.4.14
94
+ Checking indexmap v2.14.2
95
+ Compiling wgpu-hal v0.19.5
96
+ Checking unicode-xid v0.2.6
97
+ Checking hexf-parse v0.2.1
98
+ Checking rustc-hash v1.1.0
99
+ Compiling serde v1.0.229
100
+ Compiling wgpu-core v0.19.4
101
+ Checking libloading v0.8.9
102
+ Checking wgpu-types v0.19.2
103
+ Checking profiling v1.0.18
104
+ Checking raw-window-handle v0.6.2
105
+ Compiling wgpu v0.19.4
106
+ Checking parking_lot v0.12.5
107
+ Checking pollster v0.3.0
108
+ Checking naga v0.19.2
109
+ Checking objc v0.2.7
110
+ Compiling foreign-types-macros v0.2.4
111
+ Compiling serde_derive v1.0.229
112
+ Compiling thiserror-impl v2.0.21
113
+ Compiling bytemuck_derive v1.12.1
114
+ Compiling clap_derive v4.6.7
115
+ Checking foreign-types v0.5.0
116
+ Checking serde_json v1.0.151
117
+ Checking bytemuck v1.25.2
118
+ Checking metal v0.27.0
119
+ Checking thiserror v2.0.21
120
+ Checking metal v0.29.0
121
+ Checking clap v4.6.7
122
+ Checking bincode v1.3.3
123
+ Checking cortiq-core v0.6.8 (/Users/oleg/dev/cmfpublic/crates/cortiq-core)
124
+ Checking cortiq-decision v0.1.0 (/Users/oleg/dev/cmfpublic/tools/cortiq-decision)
125
+ error[E0596]: cannot borrow `packed` as mutable, as it is not declared as mutable
126
+ --> src/vulkan.rs:57:63
127
+ |
128
+ 57 | ...count();let packed=Packed::new(&m.seed)?;let mut gpu=VulkanScorer::new(&m.seed,128)?;
129
+ | ^^^^^^ not mutable
130
+ ...
131
+ 62 | ...tual.chunks_exact(nt)).zip(batch){let mut expected=vec![0.;nt];packed.errors_into(x,&mut expected)?;for(a,b)in e.iter().zip(&expe...
132
+ | ------ cannot borrow as mutable
133
+ ...
134
+ 67 | ...let start=Instant::now();for(x,o)in xs.chunks_exact(d).zip(out.chunks_exact_mut(nt)){packed.errors_into(x,o)?;}std::hint::black_b...
135
+ | ------ cannot borrow as mutable
136
+ |
137
+ help: consider changing this to be mutable
138
+ |
139
+ 57 | let d=m.seed.input_dim;let nt=m.seed.active().count();let mut packed=Packed::new(&m.seed)?;let mut gpu=VulkanScorer::new(&m.seed,128)?;
140
+ | +++
141
+
142
+ For more information about this error, try `rustc --explain E0596`.
143
+ error: could not compile `cortiq-decision` (lib) due to 1 previous error
evidence/release/vulkan-environment.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ GPU workload at acceptance: pre-existing unrelated job, NOT stopped
2
+ name, utilization.gpu [%], memory.used [MiB], memory.total [MiB], driver_version
3
+ NVIDIA RTX PRO 4000 Blackwell, 88 %, 12516 MiB, 24467 MiB, 595.91.07
4
+ Architecture: x86_64
5
+ CPU(s): 28
6
+ Model name: Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz
7
+ 4cdaf9ec19054f17cd34d420a56f4c8bb0eed12c2429732e9baf902ef52303df /data/cmf-decision-release-20260925/cortiq-banking77.cmf
8
+ Filesystem Size Used Avail Use% Mounted on
9
+ /dev/nvme1n1p1 938G 557G 334G 63% /data
evidence/release/vulkan-linux-tests.txt ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Compiling proc-macro2 v1.0.107
2
+ Compiling quote v1.0.47
3
+ Compiling unicode-ident v1.0.26
4
+ Compiling cfg-if v1.0.5
5
+ Compiling version_check v0.9.5
6
+ Compiling bitflags v2.13.2
7
+ Compiling libc v0.2.189
8
+ Compiling once_cell v1.21.4
9
+ Compiling cfg_aliases v0.1.1
10
+ Compiling zerocopy v0.8.58
11
+ Compiling autocfg v1.5.1
12
+ Compiling parking_lot_core v0.9.12
13
+ Compiling thiserror v1.0.69
14
+ Compiling serde_core v1.0.229
15
+ Compiling typenum v1.20.1
16
+ Compiling equivalent v1.0.2
17
+ Compiling termcolor v1.4.1
18
+ Compiling allocator-api2 v0.2.21
19
+ Compiling khronos-egl v6.0.0
20
+ Compiling ash v0.37.3+1.3.251
21
+ Compiling hashbrown v0.17.1
22
+ Compiling unicode-width v0.1.14
23
+ Compiling scopeguard v1.2.0
24
+ Compiling smallvec v1.16.2
25
+ Compiling bit-vec v0.6.3
26
+ Compiling rustc-hash v1.1.0
27
+ Compiling log v0.4.34
28
+ Compiling unicode-xid v0.2.6
29
+ Compiling libloading v0.8.9
30
+ Compiling wgpu-hal v0.19.5
31
+ Compiling libloading v0.7.4
32
+ Compiling hexf-parse v0.2.1
33
+ Compiling lock_api v0.4.14
34
+ Compiling zmij v1.0.23
35
+ Compiling utf8parse v0.2.2
36
+ Compiling serde v1.0.229
37
+ Compiling wgpu-core v0.19.4
38
+ Compiling spirv v0.3.0+sdk-1.3.268.0
39
+ Compiling gpu-alloc-types v0.3.1
40
+ Compiling gpu-descriptor-types v0.1.2
41
+ Compiling anstyle-parse v1.0.0
42
+ Compiling bit-set v0.5.3
43
+ Compiling wgpu-types v0.19.2
44
+ Compiling getrandom v0.4.3
45
+ Compiling anstyle v1.0.14
46
+ Compiling rustix v1.1.5
47
+ Compiling colorchoice v1.0.5
48
+ Compiling thiserror v2.0.21
49
+ Compiling codespan-reporting v0.11.1
50
+ Compiling ahash v0.8.12
51
+ Compiling generic-array v0.14.7
52
+ Compiling arrayvec v0.7.8
53
+ Compiling profiling v1.0.18
54
+ Compiling is_terminal_polyfill v1.70.2
55
+ Compiling glow v0.13.1
56
+ Compiling anstyle-query v1.1.5
57
+ Compiling raw-window-handle v0.6.2
58
+ Compiling renderdoc-sys v1.1.0
59
+ Compiling serde_json v1.0.151
60
+ Compiling gpu-alloc v0.6.2
61
+ Compiling anstream v1.0.0
62
+ Compiling tracing-core v0.1.36
63
+ Compiling wgpu v0.19.4
64
+ Compiling anyhow v1.0.104
65
+ Compiling strsim v0.11.1
66
+ Compiling heck v0.5.0
67
+ Compiling num-traits v0.2.19
68
+ Compiling memchr v2.8.3
69
+ Compiling clap_lex v1.1.1
70
+ Compiling linux-raw-sys v0.12.1
71
+ Compiling pin-project-lite v0.2.17
72
+ Compiling itoa v1.0.18
73
+ Compiling cpufeatures v0.2.17
74
+ Compiling fastrand v2.5.0
75
+ Compiling static_assertions v1.1.0
76
+ Compiling pollster v0.3.0
77
+ Compiling clap_builder v4.6.7
78
+ Compiling indexmap v2.14.2
79
+ Compiling syn v3.0.6
80
+ Compiling syn v2.0.119
81
+ Compiling crypto-common v0.1.7
82
+ Compiling block-buffer v0.10.4
83
+ Compiling digest v0.10.7
84
+ Compiling memmap2 v0.9.11
85
+ Compiling sha2 v0.10.9
86
+ Compiling parking_lot v0.12.5
87
+ Compiling tempfile v3.27.0
88
+ Compiling serde_derive v1.0.229
89
+ Compiling thiserror-impl v2.0.21
90
+ Compiling bytemuck_derive v1.12.1
91
+ Compiling clap_derive v4.6.7
92
+ Compiling hashbrown v0.14.5
93
+ Compiling bytemuck v1.25.2
94
+ Compiling thiserror-impl v1.0.69
95
+ Compiling tracing-attributes v0.1.31
96
+ Compiling clap v4.6.7
97
+ Compiling gpu-descriptor v0.2.4
98
+ Compiling tracing v0.1.44
99
+ Compiling naga v0.19.2
100
+ Compiling bincode v1.3.3
101
+ Compiling cortiq-core v0.6.8 (/data/cmf-decision-release-20260925/source/crates/cortiq-core)
102
+ Compiling cortiq-decision v0.1.0 (/data/cmf-decision-release-20260925/source/tools/cortiq-decision)
103
+ Finished `test` profile [unoptimized + debuginfo] target(s) in 31.45s
104
+ Running unittests src/lib.rs (/data/cmf-decision-release-20260925/target/debug/deps/cortiq_decision-98c66b2e57c892e3)
105
+
106
+ running 5 tests
107
+ test fcd::tests::unsupported_task_does_not_dilute_old_confidence ... ok
108
+ test fcd::tests::reconstruct_and_select_without_materializing_dense_matrix ... ok
109
+ test fcd::tests::support_bound_rejects_invalid_calibration ... ok
110
+ test fcd::tests::core_and_orthogonality_fail_closed ... ok
111
+ test vulkan::tests::shader_parses_and_has_valid_uniform_barriers ... ok
112
+
113
+ test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
114
+
evidence/release/vulkan-shader-test.txt ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Compiling objc_exception v0.1.2
2
+ Compiling equivalent v1.0.2
3
+ Compiling scopeguard v1.2.0
4
+ Compiling foreign-types v0.5.0
5
+ Compiling bit-vec v0.6.3
6
+ Compiling termcolor v1.4.1
7
+ Compiling unicode-width v0.1.14
8
+ Compiling hashbrown v0.17.1
9
+ Compiling num-traits v0.2.19
10
+ Compiling parking_lot_core v0.9.12
11
+ Compiling objc v0.2.7
12
+ Compiling lock_api v0.4.14
13
+ Compiling thiserror v1.0.69
14
+ Compiling serde_core v1.0.229
15
+ Compiling hexf-parse v0.2.1
16
+ Compiling bit-set v0.5.3
17
+ Compiling rustc-hash v1.1.0
18
+ Compiling unicode-xid v0.2.6
19
+ Compiling codespan-reporting v0.11.1
20
+ Compiling parking_lot v0.12.5
21
+ Compiling wgpu-types v0.19.2
22
+ Compiling libloading v0.8.9
23
+ Compiling metal v0.27.0
24
+ Compiling raw-window-handle v0.6.2
25
+ Compiling profiling v1.0.18
26
+ Compiling bytemuck v1.25.2
27
+ Compiling thiserror v2.0.21
28
+ Compiling clap v4.6.7
29
+ Compiling metal v0.29.0
30
+ Compiling pollster v0.3.0
31
+ Compiling indexmap v2.14.2
32
+ Compiling naga v0.19.2
33
+ Compiling serde v1.0.229
34
+ Compiling serde_json v1.0.151
35
+ Compiling bincode v1.3.3
36
+ Compiling cortiq-core v0.6.8 (/Users/oleg/dev/cmfpublic/crates/cortiq-core)
37
+ Compiling wgpu-hal v0.19.5
38
+ Compiling wgpu-core v0.19.4
39
+ Compiling wgpu v0.19.4
40
+ Compiling cortiq-decision v0.1.0 (/Users/oleg/dev/cmfpublic/tools/cortiq-decision)
41
+ Finished `test` profile [unoptimized + debuginfo] target(s) in 17.13s
42
+ warning: the following packages contain code that will be rejected by a future version of Rust: block v0.1.6
43
+ note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
44
+ Running unittests src/lib.rs (tools/cortiq-decision/target/debug/deps/cortiq_decision-ae9ff32075835df0)
45
+
46
+ running 5 tests
47
+ test fcd::tests::core_and_orthogonality_fail_closed ... ok
48
+ test fcd::tests::reconstruct_and_select_without_materializing_dense_matrix ... ok
49
+ test fcd::tests::support_bound_rejects_invalid_calibration ... ok
50
+ test fcd::tests::unsupported_task_does_not_dilute_old_confidence ... ok
51
+ test vulkan::tests::shader_parses_and_has_valid_uniform_barriers ... ok
52
+
53
+ test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
54
+
reproduce.sh ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ # Offline evaluation only. No API calls, credentials, or test-based fitting.
3
+ set -eu
4
+ HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
+ cd "$HERE"
6
+ OUT=${1:?Usage: ./reproduce.sh /path/to/new-output-directory}
7
+ if [ -e "$OUT" ]; then echo 'Refusing to overwrite an existing experiment' >&2; exit 1; fi
8
+ mkdir -p "$OUT"
9
+ OUT=$(CDPATH= cd -- "$OUT" && pwd)
10
+ # Build artifacts stay outside the release payload.
11
+ export CARGO_TARGET_DIR="$OUT/build"
12
+ cargo build --release --locked --manifest-path source/tools/cortiq-decision/Cargo.toml
13
+ "$CARGO_TARGET_DIR/release/cortiq-decision" eval cortiq-banking77.cmf evidence/banking77/data/test.jsonl -o "$OUT/local-test.jsonl" > "$OUT/eval-summary.json"
14
+ python3 -m unittest discover -s source/tools/cortiq-decision/tests -p 'test_*.py'
15
+ printf 'Saved independent offline run to %s\n' "$OUT"
source/tools/cortiq-decision/decision_server.py CHANGED
@@ -77,7 +77,7 @@ def execute(c, label, probabilities):
77
  def accepts(entry, prediction):
78
  """One gate shared by serving and regression acceptance (including abstention)."""
79
  p=prediction;threshold=entry['min_confidence']
80
- return (threshold is not None and p['confidence']>=threshold
81
  and p['margin']>=entry.get('min_margin',0.)
82
  and p['novelty_score']<=entry.get('max_novelty',1.)
83
  and (not p['is_novel'] or entry.get('ignore_legacy_novelty',False)))
 
77
  def accepts(entry, prediction):
78
  """One gate shared by serving and regression acceptance (including abstention)."""
79
  p=prediction;threshold=entry['min_confidence']
80
+ return (threshold is not None and p['confidence']>0. and p['confidence']>=threshold
81
  and p['margin']>=entry.get('min_margin',0.)
82
  and p['novelty_score']<=entry.get('max_novelty',1.)
83
  and (not p['is_novel'] or entry.get('ignore_legacy_novelty',False)))
source/tools/cortiq-decision/src/main.rs CHANGED
@@ -374,6 +374,8 @@ fn bench(m: &DecisionModel, n: usize) -> Result<()> {
374
  },
375
  n,
376
  )?;
 
 
377
  let mut row = json!({"batch":batch,"reference":reference_times,"packed_cpu":packed_times,"cpu_bit_exact":exact});
378
  #[cfg(target_os = "macos")]
379
  {
 
374
  },
375
  n,
376
  )?;
377
+ // Only the macOS branch appends a Metal measurement.
378
+ #[allow(unused_mut)]
379
  let mut row = json!({"batch":batch,"reference":reference_times,"packed_cpu":packed_times,"cpu_bit_exact":exact});
380
  #[cfg(target_os = "macos")]
381
  {
source/tools/cortiq-decision/src/vulkan.rs CHANGED
@@ -289,3 +289,15 @@ pub fn evaluate(model: &Path, embeddings: &Path, output: &Path) -> Result<()> {
289
  );
290
  Ok(())
291
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  );
290
  Ok(())
291
  }
292
+
293
+ #[cfg(test)]
294
+ mod tests {
295
+ #[test]
296
+ fn shader_parses_and_has_valid_uniform_barriers() {
297
+ let module = wgpu::naga::front::wgsl::parse_str(include_str!("affine.wgsl")).unwrap();
298
+ wgpu::naga::valid::Validator::new(
299
+ wgpu::naga::valid::ValidationFlags::all(),
300
+ wgpu::naga::valid::Capabilities::empty(),
301
+ ).validate(&module).unwrap();
302
+ }
303
+ }
source/tools/cortiq-decision/tests/contracts.rs ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use cortiq_core::format::{check_required_features, features};
2
+ use cortiq_decision::{DecisionModel, ENCODER_FILES, Seed, Task, packed::Packed};
3
+ use std::sync::atomic::{AtomicU64, Ordering};
4
+ static ID: AtomicU64 = AtomicU64::new(0);
5
+ fn seed(d: usize) -> Seed {
6
+ let tasks = (0..7)
7
+ .map(|i| Task {
8
+ id: i * 3,
9
+ label: format!("t{i}"),
10
+ mean: (0..d).map(|j| (i + j) as f32 * 0.001).collect(),
11
+ // Deliberately NOT orthonormal, with variable ranks, to catch energy shortcuts.
12
+ basis: (0..1 + i % 3)
13
+ .map(|k| (0..d).map(|j| ((i + j + k) % 7) as f32 * 0.009).collect())
14
+ .collect(),
15
+ err_mean: 0.1,
16
+ err_std: 0.02,
17
+ n_train: 7,
18
+ frozen: i % 2 == 0,
19
+ active: i != 2,
20
+ })
21
+ .collect();
22
+ Seed {
23
+ taxonomy_id: "test".into(),
24
+ taxonomy_version: 1,
25
+ model_version: "fixture".into(),
26
+ input_dim: d,
27
+ k: 3,
28
+ temperature: 0.12,
29
+ novelty_theta: 0.7,
30
+ tasks,
31
+ }
32
+ }
33
+ struct Temp(std::path::PathBuf);
34
+ impl Temp {
35
+ fn new() -> Self {
36
+ let p = std::env::temp_dir().join(format!(
37
+ "cmf-decision-test-{}-{}",
38
+ std::process::id(),
39
+ ID.fetch_add(1, Ordering::Relaxed)
40
+ ));
41
+ std::fs::create_dir(&p).unwrap();
42
+ Self(p)
43
+ }
44
+ }
45
+ impl Drop for Temp {
46
+ fn drop(&mut self) {
47
+ std::fs::remove_dir_all(&self.0).unwrap();
48
+ }
49
+ }
50
+ fn package() -> (Temp, DecisionModel) {
51
+ let t = Temp::new();
52
+ for name in ENCODER_FILES {
53
+ std::fs::write(t.0.join(name), format!("fixture-{name}")).unwrap();
54
+ }
55
+ std::fs::write(
56
+ t.0.join("seed.json"),
57
+ serde_json::to_vec(&seed(37)).unwrap(),
58
+ )
59
+ .unwrap();
60
+ cortiq_decision::export(
61
+ &t.0.join("seed.json"),
62
+ &t.0,
63
+ "fixture",
64
+ "mean",
65
+ &t.0.join("model.cmf"),
66
+ )
67
+ .unwrap();
68
+ let m = DecisionModel::open(&t.0.join("model.cmf")).unwrap();
69
+ (t, m)
70
+ }
71
+ #[test]
72
+ fn policy_binds_model_and_abstains_without_gate() {
73
+ use cortiq_decision::policy::Policy;
74
+ let (_temp, m) = package();
75
+ let mut labels: Vec<_> = m.seed.active().map(|t| t.label.clone()).collect();
76
+ labels.sort();
77
+ let mut p: Policy = serde_json::from_value(serde_json::json!({
78
+ "schema":1,"model_version":m.seed.model_version,"seed_sha256":m.manifest.source_sha256,
79
+ "representation_id":m.manifest.representation_id,"taxonomy_id":m.seed.taxonomy_id,
80
+ "labels":labels,"min_confidence":null,"target_selective_accuracy":0.95,
81
+ "calibration_gate":null,"fallback":"abstain_or_explicit_oracle",
82
+ "oracle_model":"typesafe/jev-1.13","auto_train_from_oracle":false,"scope":"test"
83
+ }))
84
+ .unwrap();
85
+ p.validate(&m).unwrap();
86
+ let mut prediction = m.seed.predict(&[0.; 37]).unwrap();
87
+ prediction.is_novel = false;
88
+ assert_eq!(p.decide(&prediction).action, "abstain");
89
+ p.min_confidence = Some(0.);
90
+ assert_eq!(p.decide(&prediction).action, "local");
91
+ prediction.is_novel = true;
92
+ assert_eq!(p.decide(&prediction).action, "abstain");
93
+ p.representation_id = "different".into();
94
+ assert!(p.validate(&m).is_err());
95
+ p.representation_id = m.manifest.representation_id.clone();
96
+ p.auto_train_from_oracle = true;
97
+ assert!(p.validate(&m).is_err());
98
+ }
99
+ #[test]
100
+ fn packed_exact_nonorthogonal_variable_rank_and_tail() {
101
+ for d in [3, 17, 37, 384] {
102
+ let s = seed(d);
103
+ let mut packed = Packed::new(&s).unwrap();
104
+ for n in 0..100 {
105
+ let x: Vec<_> = (0..d).map(|i| ((i + n) % 19) as f32 * 0.13 - 1.0).collect();
106
+ let expected = s.errors(&x).unwrap();
107
+ let mut out = vec![0.; expected.len()];
108
+ packed.errors_into(&x, &mut out).unwrap();
109
+ assert_eq!(out, expected);
110
+ }
111
+ }
112
+ }
113
+ #[test]
114
+ fn rejects_invalid_shapes_numbers_and_calibration() {
115
+ let mut s = seed(17);
116
+ s.validate().unwrap();
117
+ assert!(s.predict(&[1.]).is_err());
118
+ assert!(s.predict(&[f32::NAN; 17]).is_err());
119
+ s.tasks[0].err_std = 0.;
120
+ assert!(s.validate().is_err());
121
+ s.tasks[0].err_std = 1.;
122
+ s.tasks[0].basis[0].pop();
123
+ assert!(s.validate().is_err());
124
+ let mut s = seed(17);
125
+ s.tasks[1].id = s.tasks[0].id;
126
+ assert!(s.validate().is_err());
127
+ let mut s = seed(17);
128
+ s.temperature = f32::INFINITY;
129
+ assert!(s.validate().is_err());
130
+ }
131
+ #[test]
132
+ fn empty_active_set_abstains_and_stable_ties() {
133
+ let mut s = seed(17);
134
+ for t in &mut s.tasks {
135
+ t.active = false;
136
+ }
137
+ assert!(s.predict(&[0.; 17]).unwrap().is_novel);
138
+ s.tasks[0].active = true;
139
+ s.tasks[1] = s.tasks[0].clone();
140
+ s.tasks[1].id = 99;
141
+ s.tasks[1].label = "second".into();
142
+ assert_eq!(s.predict(&[0.; 17]).unwrap().task_id, 0);
143
+ }
144
+ #[test]
145
+ fn roundtrip_f32_flags_identity_and_legacy_reader() {
146
+ let (_t, m) = package();
147
+ let s = seed(37);
148
+ assert_eq!(
149
+ serde_json::to_vec(&s).unwrap(),
150
+ serde_json::to_vec(&m.seed).unwrap()
151
+ );
152
+ assert_ne!(m.container.required_features & features::DECISION, 0);
153
+ assert!(
154
+ check_required_features(
155
+ m.container.required_features,
156
+ features::SUPPORTED & !features::DECISION
157
+ )
158
+ .is_err()
159
+ );
160
+ assert!(m.predict_vector(&[0.; 37], "wrong").is_err());
161
+ assert!(
162
+ m.predict_vector(&[0.; 37], &m.manifest.representation_id)
163
+ .is_ok()
164
+ );
165
+ }
166
+ #[test]
167
+ fn corrupted_payload_and_missing_feature_refused() {
168
+ let (t, m) = package();
169
+ let original = std::fs::read(t.0.join("model.cmf")).unwrap();
170
+ let e = m.container.tensor("decision.task.0.mean").unwrap();
171
+ let off = m.container.entry_abs_offset(e).unwrap();
172
+ let mut corrupt = original.clone();
173
+ corrupt[off] ^= 1;
174
+ std::fs::write(t.0.join("corrupt.cmf"), corrupt).unwrap();
175
+ assert!(DecisionModel::open(&t.0.join("corrupt.cmf")).is_err());
176
+ let mut corrupt = original;
177
+ let f = u32::from_le_bytes(corrupt[12..16].try_into().unwrap()) & !features::DECISION;
178
+ corrupt[12..16].copy_from_slice(&f.to_le_bytes());
179
+ std::fs::write(t.0.join("missing.cmf"), corrupt).unwrap();
180
+ assert!(DecisionModel::open(&t.0.join("missing.cmf")).is_err());
181
+ }
182
+ #[test]
183
+ fn exporter_does_not_overwrite() {
184
+ let (t, _) = package();
185
+ assert!(
186
+ cortiq_decision::export(
187
+ &t.0.join("seed.json"),
188
+ &t.0,
189
+ "fixture",
190
+ "mean",
191
+ &t.0.join("model.cmf")
192
+ )
193
+ .is_err()
194
+ );
195
+ }
196
+ #[cfg(target_os = "macos")]
197
+ #[test]
198
+ fn metal_handles_dimension_tail_variable_rank_and_batch() {
199
+ let s = seed(37);
200
+ let mut gpu = cortiq_decision::metal::MetalScorer::new(&s, 8).unwrap();
201
+ let xs: Vec<_> = (0..37 * 8).map(|i| (i % 17) as f32 * 0.02 - 0.12).collect();
202
+ let nt = s.active().count();
203
+ let mut out = vec![0.; 8 * nt];
204
+ gpu.errors_into(&xs, &mut out).unwrap();
205
+ for (x, got) in xs.chunks_exact(37).zip(out.chunks_exact(nt)) {
206
+ let expected = s.errors(x).unwrap();
207
+ for (a, b) in got.iter().zip(expected) {
208
+ assert!((a - b).abs() < 2e-5, "{a} vs {b}");
209
+ }
210
+ }
211
+ assert!(gpu.errors_into(&xs[..2], &mut out).is_err());
212
+ assert!(
213
+ gpu.errors_into(&vec![0.; 37 * 9], &mut vec![0.; 9 * nt])
214
+ .is_err()
215
+ );
216
+ }
source/tools/cortiq-decision/tests/test_decisions_protocol.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import json
3
+ from pathlib import Path
4
+ import sys
5
+ import tempfile
6
+ import unittest
7
+ from unittest.mock import patch
8
+
9
+ sys.path.insert(0,str(Path(__file__).resolve().parents[1]))
10
+ from decisions_protocol import (MODEL, ProtocolError, compile_question, concentration,
11
+ evaluate, local_answer, validate_request, validate_oracle_response)
12
+ from decision_server import Engine, contract_id
13
+
14
+ CHOICE={'type':'choice','instructions':'Pick the kind','criteria':{'a':'Alpha','b':'Beta'}}
15
+ NOUL={'type':'noul','instructions':'Is the proposition true?'}
16
+ SCORE={'type':'score','instructions':'How severe?','criteria':['low','medium','high']}
17
+
18
+
19
+ def prediction(p):
20
+ return {'task_label':max(p,key=p.get),'confidence':max(p.values()),'margin':.2,
21
+ 'is_novel':False,'novelty_score':.1,
22
+ 'scores':[{'task_label':k,'probability':v} for k,v in p.items()]}
23
+
24
+
25
+ class WorkerStub:
26
+ rep='fixture'
27
+ def __init__(self,*args):self.embeds=0;self.predictions=0
28
+ def load(self,entry):return 'fixture-slot'
29
+ def call(self,**r):
30
+ if r['op']=='inspect':return {'metadata':{'model_version':'fixture'}}
31
+ if r['op']=='embed':self.embeds+=1;return {'vectors':[[1.,0.]]}
32
+ self.predictions+=1;return {'prediction':prediction({'a':.97,'b':.03}),'model_version':'fixture'}
33
+
34
+
35
+ class NativeProtocol(unittest.TestCase):
36
+ def test_noul_without_criteria(self):
37
+ c=compile_question(NOUL,'text')
38
+ self.assertEqual(c['type'],'binary')
39
+ self.assertEqual(local_answer(NOUL,c,prediction({'true':.7,'false':.3})),{'type':'noul','noul':.7})
40
+
41
+ def test_fractional_score_and_legend(self):
42
+ c=compile_question(SCORE,'text');a=local_answer(SCORE,c,prediction({'0':0.,'1':.85,'2':.15}))
43
+ self.assertAlmostEqual(a['score'],1.15)
44
+ self.assertEqual(a['legend'],{'0':'low','1':'medium','2':'high'})
45
+ self.assertNotEqual(a['confidence'],.85)
46
+
47
+ def test_concentration_not_probability(self):
48
+ self.assertEqual(concentration({'a':.5,'b':.5}),0.)
49
+ self.assertEqual(concentration({'a':1.,'b':0.}),1.)
50
+
51
+ def test_structured_state_and_rubrics(self):
52
+ q={'type':'choice','instructions':{'question':'Pick','policy':['one','two']},'criteria':{'a':None,'b':{'meaning':'B'}}}
53
+ c=compile_question(q,{'message':'text'})
54
+ self.assertEqual(c['input_template'],'json-state-v1');self.assertEqual(c['criteria']['a'],'a')
55
+ self.assertIn('policy',c['instructions'])
56
+
57
+ def test_strict_limits_and_model_identity(self):
58
+ for state in [None,2,False,float('nan')]:
59
+ with self.assertRaises(ProtocolError):validate_request({'model':MODEL,'state':state,'questions':{'q':NOUL}})
60
+ with self.assertRaises(ProtocolError):compile_question({**SCORE,'criteria':['x']*11},'text')
61
+ with self.assertRaises(ProtocolError):validate_request({'model':'typesafe/jev-1.13','state':'text','questions':{'q':NOUL}})
62
+
63
+ def test_ids_not_part_of_inference_shared_encoder(self):
64
+ with tempfile.TemporaryDirectory() as d,patch('decision_server.Worker',WorkerStub):
65
+ c=compile_question(CHOICE,'text');cid=contract_id(c)
66
+ cfg={'state_dir':d,'binary':'unused','seed_model':'unused','families':{cid:{'name':'fixture','model':'unused','artifact_sha256':'fixture','contract':c,'legacy_adapter':True,'min_confidence':.8}},'oracle':{'enabled':False,'budget_usd':1,'max_calls':10}}
67
+ e=Engine(cfg)
68
+ result=evaluate(e,{'model':MODEL,'state':'text','questions':{'untrusted_name':CHOICE,'different_id':CHOICE}})
69
+ self.assertEqual(result['answers']['untrusted_name'],result['answers']['different_id'])
70
+ self.assertEqual(e.worker.embeds,1);self.assertEqual(e.worker.predictions,1)
71
+ self.assertEqual(result['usage']['cost'],0.);self.assertEqual(result['provider'],'Cortiq');e.db.close()
72
+
73
+ def test_unknown_not_fabricated_and_no_implicit_oracle(self):
74
+ with tempfile.TemporaryDirectory() as d,patch('decision_server.Worker',WorkerStub):
75
+ e=Engine({'state_dir':d,'binary':'unused','seed_model':'unused','families':{},'oracle':{'enabled':True,'budget_usd':1,'max_calls':10}},key='fixture')
76
+ with patch('decision_server.JevNativeClient') as client:
77
+ with self.assertRaises(ProtocolError) as ctx:evaluate(e,{'model':MODEL,'state':'text','questions':{'q':NOUL}})
78
+ self.assertEqual(ctx.exception.status,409);self.assertEqual(ctx.exception.body['error']['code'],'CMF_ABSTAIN');client.assert_not_called()
79
+ self.assertEqual(e.status()['oracle']['attempts'],0);e.db.close()
80
+
81
+ def test_batch_oracle_preserves_three_types_and_budget(self):
82
+ questions={'choice':CHOICE,'score':SCORE,'yes':NOUL}
83
+ response={'model':'typesafe/jev-1.13-20260917','answers':{
84
+ 'choice':{'type':'choice','choice':'a','probabilities':{'a':.9,'b':.1},'confidence':.74},
85
+ 'score':{'type':'score','score':1.15,'legend':{'0':'low','1':'medium','2':'high'},'probabilities':{'0':0.,'1':.85,'2':.15},'confidence':.77},
86
+ 'yes':{'type':'noul','noul':.91}},'usage':{'input_tokens':300,'output_tokens':25,'cost':.0000126}}
87
+ self.assertIs(validate_oracle_response(response,questions),response)
88
+ with tempfile.TemporaryDirectory() as d,patch('decision_server.Worker',WorkerStub):
89
+ cfg={'state_dir':d,'binary':'unused','seed_model':'unused','families':{},'oracle':{'enabled':True,'budget_usd':1,'max_calls':1}}
90
+ e=Engine(cfg,key='fixture')
91
+ request={'model':MODEL,'state':{'message':'public fixture'},'questions':questions,'cmf':{'allow_oracle':True,'approved_for_external':True,'consent_store':True}}
92
+ with patch('decision_server.JevNativeClient.call',return_value={'response':response,'usage':response['usage']}) as call:
93
+ result=evaluate(e,request);self.assertEqual(call.call_count,1)
94
+ wire=json.loads(call.call_args.args[0]);self.assertEqual(wire['questions'],questions);self.assertEqual(wire['state'],request['state'])
95
+ self.assertEqual(result['answers'],response['answers'])
96
+ self.assertEqual(e.status()['review_queue'],3)
97
+ with self.assertRaises(ProtocolError) as ctx:evaluate(e,request)
98
+ self.assertEqual(ctx.exception.body['error']['details']['oracle_reason'],'oracle_budget_exhausted');self.assertEqual(call.call_count,1)
99
+ self.assertAlmostEqual(e.status()['oracle']['spent_usd'],.0000126);e.db.close()
100
+
101
+ def test_invalid_oracle_replies(self):
102
+ good={'model':'typesafe/jev-1.13','answers':{'q':{'type':'noul','noul':.5}},'usage':{'cost':0.,'input_tokens':1,'output_tokens':1}}
103
+ for bad in [{**good,'model':'different/model'}, {**good,'answers':{'q':{'type':'noul','noul':float('nan')}}}, {**good,'usage':{'cost':-1}}, {**good,'answers':{}}]:
104
+ with self.assertRaises(ValueError):validate_oracle_response(bad,{'q':NOUL})
105
+
106
+ def test_invalid_later_question_precedes_side_effects(self):
107
+ with tempfile.TemporaryDirectory() as d,patch('decision_server.Worker',WorkerStub):
108
+ e=Engine({'state_dir':d,'binary':'unused','seed_model':'unused','families':{},'oracle':{'enabled':False,'budget_usd':1,'max_calls':1}})
109
+ with self.assertRaises(ProtocolError):evaluate(e,{'model':MODEL,'state':'text','questions':{'one':NOUL,'two':{}},'cmf':{'consent_store':True}})
110
+ self.assertEqual(e.status()['review_queue'],0);self.assertEqual(e.worker.embeds,0);e.db.close()
111
+
112
+
113
+ if __name__=='__main__':unittest.main()
source/tools/cortiq-decision/tests/test_harness.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib.util, math, pathlib, unittest
2
+ ROOT=pathlib.Path(__file__).resolve().parents[1]
3
+ def module(name):
4
+ spec=importlib.util.spec_from_file_location(name,ROOT/(name+'.py'));m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m);return m
5
+ bench=module('openrouter_bench');summary=module('summarize')
6
+ class HarnessTests(unittest.TestCase):
7
+ def test_only_pinned_jev_native_request(self):
8
+ r=bench.request_for('test')
9
+ self.assertEqual(r['model'],'typesafe/jev-1.13')
10
+ self.assertNotIn('models',r);self.assertNotIn('route',r)
11
+ self.assertEqual(set(r['questions']),{'task'})
12
+ self.assertEqual(r['questions']['task']['type'],'choice')
13
+ self.assertEqual(bench.ENDPOINT,'/api/alpha/decisions')
14
+ def test_metrics_known_example(self):
15
+ r=summary.metrics([{'truth':'a','choice':'a','probabilities':{'a':0.8,'b':0.2}}, {'truth':'b','choice':'a','probabilities':{'a':0.6,'b':0.4}}],['a','b'])
16
+ self.assertEqual(r['accuracy'],0.5)
17
+ self.assertAlmostEqual(r['macro_f1'],1/3)
18
+ self.assertAlmostEqual(r['brier_multiclass_sum'],0.4)
19
+ self.assertAlmostEqual(r['ece_10_bins_on_max_probability'],0.4)
20
+ self.assertLess(r['accuracy_wilson95'][0],0.5);self.assertGreater(r['accuracy_wilson95'][1],0.5)
21
+ def test_perfect_predictions(self):
22
+ r=summary.metrics([{'truth':'a','choice':'a','probabilities':{'a':1.}}],['a'])
23
+ self.assertEqual(r['accuracy'],1.);self.assertEqual(r['macro_f1'],1.)
24
+ self.assertEqual(r['brier_multiclass_sum'],0.);self.assertEqual(r['ece_10_bins_on_max_probability'],0.)
25
+ def test_percentiles(self):
26
+ self.assertEqual(summary.percentiles([1000.,3000.,2000.]),{'p50_ms':2.,'p95_ms':3.,'p99_ms':3.})
27
+ if __name__=='__main__':unittest.main()
source/tools/cortiq-decision/tests/test_server.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys,unittest,tempfile,json
2
+ from pathlib import Path
3
+ from unittest.mock import patch
4
+ sys.path.insert(0,str(Path(__file__).resolve().parents[1]))
5
+ from decision_server import contract,contract_id,state_text,execute,Engine,accepts
6
+ from lifecycle import classification_metrics,old_decision_regresses
7
+ class Stub:
8
+ rep='fixture-rep'
9
+ def __init__(self,*args):pass
10
+ def call(self,**args):return {'metadata':{'model_version':'fixture'},'representation':{}}
11
+ def load(self,*args):return 'fixture'
12
+ def close(self):pass
13
+ class ServerContracts(unittest.TestCase):
14
+ def test_choice_order_and_criteria_changes(self):
15
+ a={'type':'choice','instructions':'Choose','criteria':{'a':'Alpha','b':'Beta'}}
16
+ b={'type':'choice','instructions':'Choose','criteria':{'b':'Beta','a':'Alpha'}}
17
+ self.assertEqual(contract_id(contract(a)),contract_id(contract(b)))
18
+ b['criteria']['a']='NOT Alpha';self.assertNotEqual(contract_id(contract(a)),contract_id(contract(b)))
19
+ def test_score_order_is_semantic(self):
20
+ a=contract({'type':'score','instructions':'severity','criteria':['low','high']});b=contract({'type':'score','instructions':'severity','criteria':['high','low']})
21
+ self.assertNotEqual(contract_id(a),contract_id(b));self.assertEqual(contract(a),a)
22
+ self.assertEqual(execute(a,'1',{'0':.1,'1':.9})['score'],1)
23
+ def test_pair_cannot_silently_become_plain_text(self):
24
+ c=contract({'type':'binary','instructions':'relevant?','criteria':{'false':'no','true':'yes'},'input_template':'qa-pair-v1'})
25
+ with self.assertRaises(ValueError):state_text('plain text',c)
26
+ self.assertIn('[DOCUMENT]',state_text({'query':'q','document':'d'},c))
27
+ with self.assertRaises(ValueError):execute(c,'other',{'false':.1,'true':.9})
28
+ def test_review_transaction_and_durable_holdout(self):
29
+ with tempfile.TemporaryDirectory() as d,patch('decision_server.Worker',Stub):
30
+ cfg={'state_dir':d,'binary':'unused','seed_model':'unused','families':{},'oracle':{'enabled':False,'budget_usd':1,'max_calls':10}}
31
+ e=Engine(cfg);q={'type':'binary','instructions':'yes?','criteria':{'false':'no','true':'yes'}}
32
+ r=e.decide({'state':'test','questions':{'q':q},'options':{'consent_store':True}})['answers']['q']
33
+ with self.assertRaises(ValueError):e.review({'request_id':r['request_id'],'label':'true','split':'test','human_verified':True,'training_allowed':True,'label_source':'oracle_verified'})
34
+ e.review({'request_id':r['request_id'],'label':'true','split':'test','human_verified':True,'training_allowed':True,'label_source':'human_independent'})
35
+ self.assertEqual(e.status()['persisted_controls'],1);e.db.close()
36
+ e=Engine(cfg);self.assertEqual(e.status()['persisted_controls'],1)
37
+ r2=e.decide({'state':'TEST','questions':{'q':q},'options':{'consent_store':True}})['answers']['q']
38
+ with self.assertRaises(ValueError):e.review({'request_id':r2['request_id'],'label':'true','split':'train','human_verified':True,'training_allowed':True,'label_source':'human_independent'})
39
+ with self.assertRaises(ValueError):e.promote('unaccepted-job')
40
+ e.db.close()
41
+ def test_invalid_settings_never_partially_apply(self):
42
+ with tempfile.TemporaryDirectory() as d,patch('decision_server.Worker',Stub):
43
+ cfg={'state_dir':d,'binary':'unused','seed_model':'unused','families':{},'oracle':{'enabled':False,'budget_usd':1,'max_calls':10}}
44
+ e=Engine(cfg,key='original-test-value')
45
+ with self.assertRaises(ValueError):e.configure_oracle({'api_key':'changed-test-value','enabled':True,'budget_usd':20})
46
+ self.assertEqual(e.key,'original-test-value');self.assertFalse(e.config['oracle']['enabled'])
47
+ with self.assertRaises(ValueError):e.configure_oracle({'enabled':'true'})
48
+ e.db.close()
49
+ def test_invalid_second_question_cannot_store_or_bill_first(self):
50
+ with tempfile.TemporaryDirectory() as d,patch('decision_server.Worker',Stub):
51
+ cfg={'state_dir':d,'binary':'unused','seed_model':'unused','families':{},'oracle':{'enabled':False,'budget_usd':1,'max_calls':10}}
52
+ e=Engine(cfg)
53
+ with self.assertRaises(ValueError):e.decide({'state':'text','questions':{'valid':{'type':'binary','instructions':'yes?','criteria':{'false':'no','true':'yes'}},'invalid':{}},'options':{'consent_store':True}})
54
+ self.assertEqual(e.status()['review_queue'],0);e.db.close()
55
+ def test_old_correct_abstention_regression_is_rejected(self):
56
+ entry={'min_confidence':.8};before={'task_label':'true','confidence':.95,'margin':.1,'novelty_score':.1,'is_novel':False}
57
+ self.assertTrue(accepts(entry,before))
58
+ after={**before,'confidence':.7}
59
+ self.assertTrue(old_decision_regresses(before,after,'true',entry,entry))
60
+ self.assertTrue(old_decision_regresses(before,{**before,'task_label':'false'},'true',entry,entry))
61
+ self.assertFalse(old_decision_regresses(before,before,'true',entry,entry))
62
+ def test_imbalanced_accuracy_cannot_hide_missing_class(self):
63
+ rows=[{'truth':'major','prediction':'major'}]*99+[{'truth':'rare','prediction':'major'}]
64
+ result=classification_metrics(rows,{'major','rare'})
65
+ self.assertEqual(result['minimum_class_recall'],0.);self.assertLess(result['macro_f1'],.5)
66
+ if __name__=='__main__':unittest.main()
source/tools/cortiq-decision/tests/test_support_gate.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys,unittest
2
+ from pathlib import Path
3
+ sys.path.insert(0,str(Path(__file__).resolve().parents[1]))
4
+ from decision_server import accepts
5
+ class SupportGate(unittest.TestCase):
6
+ def test_zero_support_cannot_be_forced_local_by_ignoring_legacy_novelty(self):
7
+ entry={'min_confidence':0.,'ignore_legacy_novelty':True}
8
+ p={'confidence':0.,'margin':0.,'novelty_score':.5,'is_novel':True}
9
+ self.assertFalse(accepts(entry,p))
10
+ p['confidence']=.9
11
+ self.assertTrue(accepts(entry,p))
source/tools/cortiq-decision/tests/test_training.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib.util
2
+ import json
3
+ from pathlib import Path
4
+ import tempfile
5
+ import sys
6
+ import unittest
7
+ import numpy as np
8
+
9
+ ROOT = Path(__file__).resolve().parents[1]
10
+ def module(name):
11
+ spec = importlib.util.spec_from_file_location(name, ROOT / (name+'.py'))
12
+ m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)
13
+ return m
14
+ train = module('train')
15
+ bench = module('openrouter_bench')
16
+ sys.path.insert(0, str(ROOT))
17
+ oracle = module('oracle')
18
+
19
+ class TrainingTests(unittest.TestCase):
20
+ def test_projection_nonorthogonal(self):
21
+ x = np.array([[2., 3.]], dtype=np.float32)
22
+ means = [np.array([1., 1.], dtype=np.float32)]
23
+ basis = [np.array([[.5, .5], [1., 0.]], dtype=np.float32)]
24
+ r = x[0]-means[0]
25
+ for b in basis[0]:
26
+ r = r-(r@b)*b
27
+ self.assertAlmostEqual(float(train.errors(x, means, basis, 2)[0, 0]), float(r@r))
28
+ def test_gate_all_correct_and_all_wrong(self):
29
+ p = np.array([[.999, .001]]*500)
30
+ best, _ = train.select_gate(p, np.zeros(500, dtype=int), .95, 100)
31
+ self.assertIsNotNone(best)
32
+ best, _ = train.select_gate(p, np.ones(500, dtype=int), .95, 100)
33
+ self.assertIsNone(best)
34
+ def test_softmax_temperature(self):
35
+ p = train.probabilities(np.array([[0., 1.]]), .2)
36
+ self.assertAlmostEqual(float(p.sum()), 1.)
37
+ self.assertGreater(p[0, 0], .99)
38
+ def test_reject_duplicate_embeddings(self):
39
+ with tempfile.TemporaryDirectory() as d:
40
+ p = Path(d)/'input.jsonl'
41
+ meta = {'record_type':'representation','rows':2,'representation':{'input_dim':1}}
42
+ row = {'text_sha256':'same','label':'a','vector':[1.]}
43
+ p.write_text('\n'.join(map(json.dumps,[meta,row,row])))
44
+ with self.assertRaises(ValueError): train.read_embeddings(p)
45
+ def test_custom_taxonomy_does_not_change_model(self):
46
+ q = {'instructions':'Test intent', 'criteria':{'a':'Class A', 'b':'Class B'}}
47
+ r = bench.request_for('state', q)
48
+ self.assertEqual(r['model'], 'typesafe/jev-1.13')
49
+ self.assertEqual(r['questions']['task']['criteria'], q['criteria'])
50
+ def test_refuse_substituted_models_and_invalid_cost(self):
51
+ r = {'model':'typesafe/jev-1.13-20260917','answers':{'task':{'type':'choice','choice':'a','probabilities':{'a':.9,'b':.1}}},'usage':{'cost':.001}}
52
+ bench.validate_result(r, {'a','b'})
53
+ r['model'] = 'some/other-model'
54
+ with self.assertRaises(ValueError): bench.validate_result(r, {'a','b'})
55
+ r['model'] = 'typesafe/jev-1.13'; r['usage']['cost'] = float('nan')
56
+ with self.assertRaises(ValueError): bench.validate_result(r, {'a','b'})
57
+ def test_reservation_and_request_cap(self):
58
+ self.assertGreater(bench.reservation(b'123', .042), 0)
59
+ with self.assertRaises(ValueError): bench.reservation(b'x'*32769, .042)
60
+ def test_oracle_requires_exact_question_binding(self):
61
+ q = json.dumps({'instructions':'Choose', 'criteria':{'a':'A','b':'B'}}).encode()
62
+ policy = {'question_sha256':bench.digest(q),'labels':['a','b'],'oracle_model':'typesafe/jev-1.13','auto_train_from_oracle':False}
63
+ oracle.validate_binding(policy, q)
64
+ with self.assertRaises(ValueError): oracle.validate_binding(policy, q+b' ')
65
+ policy['auto_train_from_oracle'] = True
66
+ with self.assertRaises(ValueError): oracle.validate_binding(policy, q)
67
+ def test_failures_do_not_get_fake_calibration(self):
68
+ summary = module('summarize')
69
+ m = summary.metrics([{'truth':'a','choice':None,'probabilities':None}], ['a','b'])
70
+ self.assertEqual(m['accuracy'], 0.)
71
+ self.assertIsNone(m['brier_multiclass_sum'])
72
+ self.assertIsNone(m['ece_10_bins_on_max_probability'])
73
+ def test_rounded_probability_sum(self):
74
+ r = {'model':'typesafe/jev-1.13','answers':{'task':{'type':'choice','choice':'a','probabilities':{'a':.55,'b':.24,'c':.10,'d':.10}}},'usage':{'cost':.001}}
75
+ bench.validate_result(r, {'a','b','c','d'})
76
+ r['answers']['task']['probabilities'] = dict.fromkeys(['a','b','c','d'],0.)
77
+ with self.assertRaises(ValueError): bench.validate_result(r, {'a','b','c','d'})
78
+
79
+ if __name__ == '__main__': unittest.main()