open-multi-agent-kit 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/README.md +2 -2
  3. package/dist/cli/help.d.ts.map +1 -1
  4. package/dist/cli/help.js +1 -0
  5. package/dist/cli/help.js.map +1 -1
  6. package/dist/coordination/awareness.d.ts +32 -0
  7. package/dist/coordination/awareness.d.ts.map +1 -0
  8. package/dist/coordination/awareness.js +55 -0
  9. package/dist/coordination/awareness.js.map +1 -0
  10. package/dist/coordination/broker.d.ts +79 -0
  11. package/dist/coordination/broker.d.ts.map +1 -0
  12. package/dist/coordination/broker.js +195 -0
  13. package/dist/coordination/broker.js.map +1 -0
  14. package/dist/coordination/index.d.ts +16 -0
  15. package/dist/coordination/index.d.ts.map +1 -0
  16. package/dist/coordination/index.js +16 -0
  17. package/dist/coordination/index.js.map +1 -0
  18. package/dist/coordination/integration.d.ts +59 -0
  19. package/dist/coordination/integration.d.ts.map +1 -0
  20. package/dist/coordination/integration.js +126 -0
  21. package/dist/coordination/integration.js.map +1 -0
  22. package/dist/coordination/operation.d.ts +106 -0
  23. package/dist/coordination/operation.d.ts.map +1 -0
  24. package/dist/coordination/operation.js +179 -0
  25. package/dist/coordination/operation.js.map +1 -0
  26. package/dist/coordination/resource.d.ts +33 -0
  27. package/dist/coordination/resource.d.ts.map +1 -0
  28. package/dist/coordination/resource.js +89 -0
  29. package/dist/coordination/resource.js.map +1 -0
  30. package/dist/coordination/session.d.ts +74 -0
  31. package/dist/coordination/session.d.ts.map +1 -0
  32. package/dist/coordination/session.js +143 -0
  33. package/dist/coordination/session.js.map +1 -0
  34. package/dist/coordination/types.d.ts +68 -0
  35. package/dist/coordination/types.d.ts.map +1 -0
  36. package/dist/coordination/types.js +26 -0
  37. package/dist/coordination/types.js.map +1 -0
  38. package/dist/core/agent-session.d.ts.map +1 -1
  39. package/dist/core/agent-session.js +28 -7
  40. package/dist/core/agent-session.js.map +1 -1
  41. package/dist/core/compaction/control-state.d.ts +41 -0
  42. package/dist/core/compaction/control-state.d.ts.map +1 -0
  43. package/dist/core/compaction/control-state.js +85 -0
  44. package/dist/core/compaction/control-state.js.map +1 -0
  45. package/dist/core/compaction/fallback.d.ts +60 -0
  46. package/dist/core/compaction/fallback.d.ts.map +1 -0
  47. package/dist/core/compaction/fallback.js +117 -0
  48. package/dist/core/compaction/fallback.js.map +1 -0
  49. package/dist/core/compaction/index.d.ts +2 -0
  50. package/dist/core/compaction/index.d.ts.map +1 -1
  51. package/dist/core/compaction/index.js +2 -0
  52. package/dist/core/compaction/index.js.map +1 -1
  53. package/dist/core/context-budget-headroom-candidates.d.ts +16 -1
  54. package/dist/core/context-budget-headroom-candidates.d.ts.map +1 -1
  55. package/dist/core/context-budget-headroom-candidates.js +31 -13
  56. package/dist/core/context-budget-headroom-candidates.js.map +1 -1
  57. package/dist/core/context-budget-headroom-types.d.ts +7 -1
  58. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  59. package/dist/core/context-budget-headroom-types.js +0 -1
  60. package/dist/core/context-budget-headroom-types.js.map +1 -1
  61. package/dist/core/context-budget-headroom.d.ts +10 -0
  62. package/dist/core/context-budget-headroom.d.ts.map +1 -1
  63. package/dist/core/context-budget-headroom.js +11 -2
  64. package/dist/core/context-budget-headroom.js.map +1 -1
  65. package/dist/core/context-budget-v2-global-pass.d.ts +21 -0
  66. package/dist/core/context-budget-v2-global-pass.d.ts.map +1 -0
  67. package/dist/core/context-budget-v2-global-pass.js +203 -0
  68. package/dist/core/context-budget-v2-global-pass.js.map +1 -0
  69. package/dist/core/context-budget-v2-planned-items.d.ts +12 -0
  70. package/dist/core/context-budget-v2-planned-items.d.ts.map +1 -1
  71. package/dist/core/context-budget-v2-planned-items.js +21 -2
  72. package/dist/core/context-budget-v2-planned-items.js.map +1 -1
  73. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  74. package/dist/core/context-budget-v2-planner.js +18 -19
  75. package/dist/core/context-budget-v2-planner.js.map +1 -1
  76. package/dist/core/context-budget-v2-scoring.d.ts +7 -1
  77. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  78. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  79. package/dist/core/context-budget-v2-selection.d.ts +3 -0
  80. package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
  81. package/dist/core/context-budget-v2-selection.js +6 -2
  82. package/dist/core/context-budget-v2-selection.js.map +1 -1
  83. package/dist/core/context-budget-v2-types.d.ts +6 -1
  84. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  85. package/dist/core/context-budget-v2-types.js +6 -1
  86. package/dist/core/context-budget-v2-types.js.map +1 -1
  87. package/dist/core/provider-default-models.d.ts +1 -0
  88. package/dist/core/provider-default-models.d.ts.map +1 -1
  89. package/dist/core/provider-default-models.js +1 -0
  90. package/dist/core/provider-default-models.js.map +1 -1
  91. package/dist/core/provider-display-names.d.ts.map +1 -1
  92. package/dist/core/provider-display-names.js +1 -0
  93. package/dist/core/provider-display-names.js.map +1 -1
  94. package/dist/core/reasoning-router-resolver.d.ts +7 -0
  95. package/dist/core/reasoning-router-resolver.d.ts.map +1 -1
  96. package/dist/core/reasoning-router-resolver.js +21 -3
  97. package/dist/core/reasoning-router-resolver.js.map +1 -1
  98. package/dist/core/reasoning-router-v4.d.ts +8 -5
  99. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  100. package/dist/core/reasoning-router-v4.js +8 -5
  101. package/dist/core/reasoning-router-v4.js.map +1 -1
  102. package/dist/core/session-compaction-service.d.ts +15 -0
  103. package/dist/core/session-compaction-service.d.ts.map +1 -1
  104. package/dist/core/session-compaction-service.js +17 -4
  105. package/dist/core/session-compaction-service.js.map +1 -1
  106. package/dist/core/todo-runtime-state.d.ts +12 -0
  107. package/dist/core/todo-runtime-state.d.ts.map +1 -1
  108. package/dist/core/todo-runtime-state.js +23 -0
  109. package/dist/core/todo-runtime-state.js.map +1 -1
  110. package/dist/index.d.ts +2 -0
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.js +2 -0
  113. package/dist/index.js.map +1 -1
  114. package/dist/metacognition/calibration-selective.d.ts +78 -0
  115. package/dist/metacognition/calibration-selective.d.ts.map +1 -0
  116. package/dist/metacognition/calibration-selective.js +161 -0
  117. package/dist/metacognition/calibration-selective.js.map +1 -0
  118. package/dist/metacognition/calibration.d.ts +62 -0
  119. package/dist/metacognition/calibration.d.ts.map +1 -0
  120. package/dist/metacognition/calibration.js +122 -0
  121. package/dist/metacognition/calibration.js.map +1 -0
  122. package/dist/metacognition/checkpoint.d.ts +60 -0
  123. package/dist/metacognition/checkpoint.d.ts.map +1 -0
  124. package/dist/metacognition/checkpoint.js +57 -0
  125. package/dist/metacognition/checkpoint.js.map +1 -0
  126. package/dist/metacognition/context7.d.ts +48 -0
  127. package/dist/metacognition/context7.d.ts.map +1 -0
  128. package/dist/metacognition/context7.js +154 -0
  129. package/dist/metacognition/context7.js.map +1 -0
  130. package/dist/metacognition/decision.d.ts +44 -0
  131. package/dist/metacognition/decision.d.ts.map +1 -0
  132. package/dist/metacognition/decision.js +111 -0
  133. package/dist/metacognition/decision.js.map +1 -0
  134. package/dist/metacognition/evaluation.d.ts +73 -0
  135. package/dist/metacognition/evaluation.d.ts.map +1 -0
  136. package/dist/metacognition/evaluation.js +97 -0
  137. package/dist/metacognition/evaluation.js.map +1 -0
  138. package/dist/metacognition/index.d.ts +31 -0
  139. package/dist/metacognition/index.d.ts.map +1 -0
  140. package/dist/metacognition/index.js +31 -0
  141. package/dist/metacognition/index.js.map +1 -0
  142. package/dist/metacognition/knowledge-action.d.ts +43 -0
  143. package/dist/metacognition/knowledge-action.d.ts.map +1 -0
  144. package/dist/metacognition/knowledge-action.js +60 -0
  145. package/dist/metacognition/knowledge-action.js.map +1 -0
  146. package/dist/metacognition/knowledge.d.ts +84 -0
  147. package/dist/metacognition/knowledge.d.ts.map +1 -0
  148. package/dist/metacognition/knowledge.js +165 -0
  149. package/dist/metacognition/knowledge.js.map +1 -0
  150. package/dist/metacognition/obligations.d.ts +82 -0
  151. package/dist/metacognition/obligations.d.ts.map +1 -0
  152. package/dist/metacognition/obligations.js +139 -0
  153. package/dist/metacognition/obligations.js.map +1 -0
  154. package/dist/metacognition/observation-validity.d.ts +83 -0
  155. package/dist/metacognition/observation-validity.d.ts.map +1 -0
  156. package/dist/metacognition/observation-validity.js +118 -0
  157. package/dist/metacognition/observation-validity.js.map +1 -0
  158. package/dist/metacognition/observe.d.ts +45 -0
  159. package/dist/metacognition/observe.d.ts.map +1 -0
  160. package/dist/metacognition/observe.js +59 -0
  161. package/dist/metacognition/observe.js.map +1 -0
  162. package/dist/metacognition/policy.d.ts +53 -0
  163. package/dist/metacognition/policy.d.ts.map +1 -0
  164. package/dist/metacognition/policy.js +155 -0
  165. package/dist/metacognition/policy.js.map +1 -0
  166. package/dist/metacognition/predictions.d.ts +78 -0
  167. package/dist/metacognition/predictions.d.ts.map +1 -0
  168. package/dist/metacognition/predictions.js +181 -0
  169. package/dist/metacognition/predictions.js.map +1 -0
  170. package/dist/metacognition/retrieval.d.ts +53 -0
  171. package/dist/metacognition/retrieval.d.ts.map +1 -0
  172. package/dist/metacognition/retrieval.js +170 -0
  173. package/dist/metacognition/retrieval.js.map +1 -0
  174. package/dist/metacognition/risk.d.ts +48 -0
  175. package/dist/metacognition/risk.d.ts.map +1 -0
  176. package/dist/metacognition/risk.js +165 -0
  177. package/dist/metacognition/risk.js.map +1 -0
  178. package/dist/metacognition/route-economics.d.ts +95 -0
  179. package/dist/metacognition/route-economics.d.ts.map +1 -0
  180. package/dist/metacognition/route-economics.js +110 -0
  181. package/dist/metacognition/route-economics.js.map +1 -0
  182. package/dist/metacognition/runtime-bridge.d.ts +54 -0
  183. package/dist/metacognition/runtime-bridge.d.ts.map +1 -0
  184. package/dist/metacognition/runtime-bridge.js +140 -0
  185. package/dist/metacognition/runtime-bridge.js.map +1 -0
  186. package/dist/metacognition/skills.d.ts +42 -0
  187. package/dist/metacognition/skills.d.ts.map +1 -0
  188. package/dist/metacognition/skills.js +220 -0
  189. package/dist/metacognition/skills.js.map +1 -0
  190. package/dist/metacognition/state.d.ts +110 -0
  191. package/dist/metacognition/state.d.ts.map +1 -0
  192. package/dist/metacognition/state.js +52 -0
  193. package/dist/metacognition/state.js.map +1 -0
  194. package/dist/metacognition/validation.d.ts +19 -0
  195. package/dist/metacognition/validation.d.ts.map +1 -0
  196. package/dist/metacognition/validation.js +58 -0
  197. package/dist/metacognition/validation.js.map +1 -0
  198. package/dist/metacognition/verification.d.ts +93 -0
  199. package/dist/metacognition/verification.d.ts.map +1 -0
  200. package/dist/metacognition/verification.js +132 -0
  201. package/dist/metacognition/verification.js.map +1 -0
  202. package/dist/metacognition/verifier.d.ts +49 -0
  203. package/dist/metacognition/verifier.d.ts.map +1 -0
  204. package/dist/metacognition/verifier.js +88 -0
  205. package/dist/metacognition/verifier.js.map +1 -0
  206. package/dist/observation/identity.d.ts +14 -0
  207. package/dist/observation/identity.d.ts.map +1 -0
  208. package/dist/observation/identity.js +29 -0
  209. package/dist/observation/identity.js.map +1 -0
  210. package/dist/observation/index.d.ts +13 -0
  211. package/dist/observation/index.d.ts.map +1 -0
  212. package/dist/observation/index.js +13 -0
  213. package/dist/observation/index.js.map +1 -0
  214. package/dist/observation/observe-mode.d.ts +46 -0
  215. package/dist/observation/observe-mode.d.ts.map +1 -0
  216. package/dist/observation/observe-mode.js +83 -0
  217. package/dist/observation/observe-mode.js.map +1 -0
  218. package/dist/observation/store.d.ts +53 -0
  219. package/dist/observation/store.d.ts.map +1 -0
  220. package/dist/observation/store.js +126 -0
  221. package/dist/observation/store.js.map +1 -0
  222. package/dist/observation/types.d.ts +72 -0
  223. package/dist/observation/types.d.ts.map +1 -0
  224. package/dist/observation/types.js +9 -0
  225. package/dist/observation/types.js.map +1 -0
  226. package/dist/observation/view.d.ts +39 -0
  227. package/dist/observation/view.d.ts.map +1 -0
  228. package/dist/observation/view.js +173 -0
  229. package/dist/observation/view.js.map +1 -0
  230. package/docs/metacognition.md +51 -0
  231. package/docs/model-catalog-refresh.md +59 -0
  232. package/docs/providers.md +53 -0
  233. package/docs/runtime-algorithms.md +107 -3
  234. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  235. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  236. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  237. package/examples/extensions/gondolin/package-lock.json +2 -2
  238. package/examples/extensions/gondolin/package.json +1 -1
  239. package/examples/extensions/sandbox/package-lock.json +2 -2
  240. package/examples/extensions/sandbox/package.json +1 -1
  241. package/examples/extensions/with-deps/package-lock.json +2 -2
  242. package/examples/extensions/with-deps/package.json +1 -1
  243. package/npm-shrinkwrap.json +18 -18
  244. package/package.json +6 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge.js","sourceRoot":"","sources":["../../src/metacognition/knowledge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAyF5F,MAAM,UAAU,gBAAgB,CAAC,KAAqB,EAAmB;IACxE,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;IAChE,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,CAAC,OAAO,KAAK,CAAC,kBAAkB,KAAK,SAAS,EAAE,oCAAoC,CAAC,CAAC;IAC5F,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,IAAI,IAAI,EAAE,2BAA2B,CAAC,CAAC;IACrG,MAAM,CACL,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC7B,WAAW,EACX,GAAG,CACH,CAAC;IACF,MAAM,CACL,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC9B,YAAY,EACZ,GAAG,CACH,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,oBAAoB,CAAC,CAAC;IACrD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC3B,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC,EAAE,aAAa,CAAC,CAAC;QAClE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACxF,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,oBAAoB,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,SAAS,EAAE,gBAAgB,CAAC,CAAC;QAC9F,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,4CAA4C,CAAC,CAAC;QACnG,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;YAAE,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI;YAAE,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,GAAG,CAAC,CAAC;QACpE,MAAM,CAAC,CAAC,CAAC,gBAAgB,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAC7C,MAAM,CACL,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,iBAAiB,EACxE,iCAAiC,CACjC,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,CACtB,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC;QAChF,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAU,CAAC;IAAA,CAC1B,CAAC,CACF,CAAC;IACF,MAAM,YAAY,GAAG,IAAI,GAAG,EAAuB,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,YAAY,EAAE,uCAAuC,CAAC,CAAC;QACrF,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACzE,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;YAC3C,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC7B,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI;gBAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,CAAC,CAAC;YACxE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;QACrD,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAClC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,eAAe,CAAC,CAAC;YAClE,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC7E,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,CAAC,GAAG,CAAC,EAAE,4BAA4B,CAAC,CAAC;YAC5F,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC7B,MAAM,CAAC,OAAO,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC,GAAG,CAAC,EAAE,4BAA4B,CAAC,CAAC;QACvG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,cAAc,IAAI,CAAC,CAAC,KAAK,KAAK,cAAc,CAAC,CAAC;IAChH,MAAM,oBAAoB,GAAqC,EAAE,CAAC;IAClE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,MAA0B,CAAC;QAC/B,IAAI,CAAC,CAAC;YAAE,MAAM,GAAG,2BAA2B,CAAC;aACxC,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO;YAAE,MAAM,GAAG,eAAe,CAAC;aACxD,IAAI,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK;YAAE,MAAM,GAAG,mBAAmB,CAAC;aACnG,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC;gBAAE,MAAM,GAAG,qBAAqB,CAAC;iBACvG,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC;gBAAE,MAAM,GAAG,kBAAkB,CAAC;QAC9G,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,MAAM,GAAG,kBAAkB,CAAC;aAC1G,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACnF,MAAM,GAAG,0BAA0B,CAAC;QACrC,CAAC;QACD,IAAI,MAAM;YAAE,oBAAoB,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;;YACzD,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,MAAM,iBAAiB,GAAa,EAAE,CAAC;IACvC,IAAI,KAAK,CAAC,kBAAkB,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvF,IAAI,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,OAAO;YAChB,OAAO,EAAE,YAAY;YACrB,MAAM,EAAE,iBAAiB;YACzB,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,IAAI;SACb,CAAC,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,CAAC,MAAiB,EAAE,OAAO,GAAkB,IAAI,EAAQ,EAAE,CAAC;YACvE,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAAA,CAC1G,CAAC;QACF,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;YAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACpE,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAA+B,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YAC7F,MAAM,OAAO,GAAG,IAAI,GAAG,CACtB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAE,CAAC,MAAM,CAAC,CACtF,CAAC;YACF,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC;gBAAE,GAAG,CAAC,yBAAyB,CAAC,CAAC;iBACvE,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,iBAAiB;gBAAE,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC3E,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;YAC1C,MAAM,OAAO,GAAG,QAAQ;iBACtB,MAAM,CAAC,CAAC,GAAG,EAA2B,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,OAAO,KAAK,OAAO,CAAC;iBACzF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC,MAAM;gBAAE,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;iBACtC,IAAI,MAAM,CAAC,OAAO,KAAK,MAAM;gBAAE,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;iBAC5D,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;gBAAE,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;YACzB,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAA8B,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;YAChG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAAE,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC5G,CAAC;QACD,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM;YAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,CAAC,IAAI,CACR,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACR,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QACvC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QACnB,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC;QAC7B,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAC5B,CAAC;IACF,OAAO;QACN,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW;QAC1D,IAAI;QACJ,iBAAiB,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC;QAClD,oBAAoB;KACpB,CAAC;AAAA,CACF","sourcesContent":["/**\n * Claim/evidence gap inspection and the bounded next-action selector.\n *\n * Ported from docs/OMK_skill_knowledge_control_2026-09-19.zip\n * (src/knowledge.ts). Host-owned observations only; a model's JSON is never\n * runner truth. See OMK_metacognitive_control_algorithms_2026-09-19.md §13.\n */\nimport { canonical, ensure, integer, lexical, member, text, unique } from \"./validation.ts\";\n\nexport type Stage = \"before-change\" | \"after-change\";\nexport interface Claim {\n\treadonly id: string;\n\t/** Hash/fingerprint computed by the host over the relevant subject and environment. */\n\treadonly binding: string;\n\treadonly phase: \"precondition\" | \"postcondition\";\n\treadonly statement: string;\n\treadonly required: boolean;\n\treadonly impact: number;\n\treadonly needsReference: boolean;\n\treadonly requiresVersion: boolean;\n\treadonly version: string | null;\n\treadonly minSourceFamilies: number;\n\treadonly requiredCheckIds: readonly string[];\n\treadonly needsUserDecision: boolean;\n\t/** Only explicit, host-approved public text can leave the repository. */\n\treadonly publicQuery: string | null;\n}\nexport interface SourceIdentity {\n\treadonly id: string;\n\treadonly family: string;\n\treadonly kind: \"repository\" | \"official\" | \"community\" | \"model\";\n}\ninterface ObservationBase {\n\treadonly id: string;\n\treadonly claimId: string;\n\treadonly binding: string;\n\treadonly observedAtMs: number;\n\treadonly expiresAtMs: number;\n}\nexport interface ReferenceObservation extends ObservationBase {\n\treadonly kind: \"reference\";\n\treadonly sourceId: string;\n\treadonly version: string | null;\n\treadonly stance: \"support\" | \"refute\";\n\treadonly documentDigest: string;\n\treadonly locator: string;\n}\nexport interface CheckObservation extends ObservationBase {\n\treadonly kind: \"check\";\n\treadonly runnerId: string;\n\treadonly checkId: string;\n\t/** Host-ordered snapshot. In OMK, project the existing strict evidence ledger here. */\n\treadonly sequence: number;\n\treadonly verdict: \"pass\" | \"fail\" | \"pending\";\n}\nexport interface DecisionObservation extends ObservationBase {\n\treadonly kind: \"decision\";\n\treadonly actorId: string;\n\treadonly accepted: boolean;\n}\nexport type Observation = ReferenceObservation | CheckObservation | DecisionObservation;\nexport type GapReason =\n\t| \"unassessed-step\"\n\t| \"unknown-version\"\n\t| \"unsupported-reference\"\n\t| \"contradictory-reference\"\n\t| \"missing-check\"\n\t| \"failed-check\"\n\t| \"pending-check\"\n\t| \"missing-user-decision\";\nexport interface KnowledgeGap {\n\treadonly claimId: string;\n\treadonly binding: string;\n\treadonly reason: GapReason;\n\treadonly required: boolean;\n\treadonly impact: number;\n\treadonly checkId: string | null;\n}\nexport interface KnowledgeReport {\n\treadonly state: \"supported\" | \"gaps\";\n\treadonly gaps: readonly KnowledgeGap[];\n\treadonly supportedClaimIds: readonly string[];\n\treadonly rejectedObservations: readonly { id: string; reason: string }[];\n}\nexport interface KnowledgeInput {\n\treadonly stage: Stage;\n\treadonly requiresAssessment: boolean;\n\treadonly nowMs: number;\n\treadonly claims: readonly Claim[];\n\t/** Admitted host observations only. Never pass a model's JSON here as runner truth. */\n\treadonly observations: readonly Observation[];\n\treadonly sources: readonly SourceIdentity[];\n\treadonly trustedRunnerIds: readonly string[];\n\treadonly decisionActorIds: readonly string[];\n}\n\nexport function inspectKnowledge(input: KnowledgeInput): KnowledgeReport {\n\tmember(input.stage, [\"before-change\", \"after-change\"], \"stage\");\n\tinteger(input.nowMs, \"nowMs\");\n\tensure(typeof input.requiresAssessment === \"boolean\", \"requiresAssessment must be boolean\");\n\tensure(input.claims.length <= 128 && input.observations.length <= 4096, \"knowledge input too large\");\n\tunique(\n\t\tinput.claims.map((c) => c.id),\n\t\t\"claim ids\",\n\t\t128,\n\t);\n\tunique(\n\t\tinput.sources.map((s) => s.id),\n\t\t\"source ids\",\n\t\t512,\n\t);\n\tunique(input.trustedRunnerIds, \"runner ids\");\n\tunique(input.decisionActorIds, \"decision actor ids\");\n\tfor (const c of input.claims) {\n\t\ttext(c.binding, \"binding\");\n\t\ttext(c.statement, \"statement\");\n\t\tmember(c.phase, [\"precondition\", \"postcondition\"], \"claim phase\");\n\t\tfor (const v of [c.required, c.needsReference, c.requiresVersion, c.needsUserDecision]) {\n\t\t\tensure(typeof v === \"boolean\", \"invalid claim flag\");\n\t\t}\n\t\tensure(Number.isFinite(c.impact) && c.impact >= 0 && c.impact <= 1_000_000, \"invalid impact\");\n\t\tinteger(c.minSourceFamilies, \"minSourceFamilies\", 16);\n\t\tensure(!c.needsReference || c.minSourceFamilies > 0, \"reference needs at least one source family\");\n\t\tif (c.version !== null) text(c.version, \"version\", 128);\n\t\tif (c.publicQuery !== null) text(c.publicQuery, \"publicQuery\", 500);\n\t\tunique(c.requiredCheckIds, \"check ids\", 128);\n\t\tensure(\n\t\t\tc.needsReference || c.requiredCheckIds.length > 0 || c.needsUserDecision,\n\t\t\t\"claim has no evidence predicate\",\n\t\t);\n\t}\n\tconst sources = new Map(\n\t\tinput.sources.map((s) => {\n\t\t\ttext(s.family, \"source family\");\n\t\t\tmember(s.kind, [\"repository\", \"official\", \"community\", \"model\"], \"source kind\");\n\t\t\treturn [s.id, s] as const;\n\t\t}),\n\t);\n\tconst observations = new Map<string, Observation>();\n\tconst sequences = new Map<string, string>();\n\tfor (const obs of input.observations) {\n\t\ttext(obs.id, \"observation id\");\n\t\ttext(obs.claimId, \"observation claim\");\n\t\ttext(obs.binding, \"observation binding\");\n\t\tinteger(obs.observedAtMs, \"observedAtMs\");\n\t\tinteger(obs.expiresAtMs, \"expiresAtMs\");\n\t\tensure(obs.expiresAtMs >= obs.observedAtMs, \"invalid observation validity interval\");\n\t\tmember(obs.kind, [\"reference\", \"check\", \"decision\"], \"observation kind\");\n\t\tif (obs.kind === \"reference\") {\n\t\t\ttext(obs.sourceId, \"sourceId\");\n\t\t\ttext(obs.documentDigest, \"documentDigest\");\n\t\t\ttext(obs.locator, \"locator\");\n\t\t\tif (obs.version !== null) text(obs.version, \"observation version\", 128);\n\t\t\tmember(obs.stance, [\"support\", \"refute\"], \"stance\");\n\t\t} else if (obs.kind === \"check\") {\n\t\t\ttext(obs.runnerId, \"runnerId\");\n\t\t\ttext(obs.checkId, \"checkId\");\n\t\t\tinteger(obs.sequence, \"sequence\");\n\t\t\tmember(obs.verdict, [\"pass\", \"fail\", \"pending\"], \"check verdict\");\n\t\t\tconst key = canonical([obs.claimId, obs.binding, obs.checkId, obs.sequence]);\n\t\t\tconst previous = sequences.get(key);\n\t\t\tensure(previous === undefined || previous === canonical(obs), \"conflicting check sequence\");\n\t\t\tsequences.set(key, canonical(obs));\n\t\t} else {\n\t\t\ttext(obs.actorId, \"actorId\");\n\t\t\tensure(typeof obs.accepted === \"boolean\", \"invalid decision\");\n\t\t}\n\t\tconst previous = observations.get(obs.id);\n\t\tensure(previous === undefined || canonical(previous) === canonical(obs), \"conflicting observation id\");\n\t\tobservations.set(obs.id, obs);\n\t}\n\tconst relevantClaims = input.claims.filter((c) => input.stage === \"after-change\" || c.phase === \"precondition\");\n\tconst rejectedObservations: { id: string; reason: string }[] = [];\n\tconst admissible = new Map<string, Observation[]>();\n\tconst claimMap = new Map(relevantClaims.map((c) => [c.id, c]));\n\tfor (const obs of observations.values()) {\n\t\tconst c = claimMap.get(obs.claimId);\n\t\tlet reason: string | undefined;\n\t\tif (!c) reason = \"irrelevant-claim-or-stage\";\n\t\telse if (obs.binding !== c.binding) reason = \"stale-binding\";\n\t\telse if (obs.observedAtMs > input.nowMs || obs.expiresAtMs <= input.nowMs) reason = \"expired-or-future\";\n\t\telse if (obs.kind === \"reference\") {\n\t\t\tconst source = sources.get(obs.sourceId);\n\t\t\tif (!source || (source.kind !== \"repository\" && source.kind !== \"official\")) reason = \"inadmissible-source\";\n\t\t\telse if (c.requiresVersion && (c.version === null || obs.version !== c.version)) reason = \"version-mismatch\";\n\t\t} else if (obs.kind === \"check\" && !input.trustedRunnerIds.includes(obs.runnerId)) reason = \"untrusted-runner\";\n\t\telse if (obs.kind === \"decision\" && !input.decisionActorIds.includes(obs.actorId)) {\n\t\t\treason = \"untrusted-decision-actor\";\n\t\t}\n\t\tif (reason) rejectedObservations.push({ id: obs.id, reason });\n\t\telse admissible.set(obs.claimId, [...(admissible.get(obs.claimId) ?? []), obs]);\n\t}\n\tconst gaps: KnowledgeGap[] = [];\n\tconst supportedClaimIds: string[] = [];\n\tif (input.requiresAssessment && relevantClaims.filter((c) => c.required).length === 0) {\n\t\tgaps.push({\n\t\t\tclaimId: \"$step\",\n\t\t\tbinding: \"unassessed\",\n\t\t\treason: \"unassessed-step\",\n\t\t\trequired: true,\n\t\t\timpact: 1_000_000,\n\t\t\tcheckId: null,\n\t\t});\n\t}\n\tfor (const c of relevantClaims) {\n\t\tconst before = gaps.length;\n\t\tconst evidence = admissible.get(c.id) ?? [];\n\t\tconst add = (reason: GapReason, checkId: string | null = null): void => {\n\t\t\tgaps.push({ claimId: c.id, binding: c.binding, reason, required: c.required, impact: c.impact, checkId });\n\t\t};\n\t\tif (c.requiresVersion && c.version === null) add(\"unknown-version\");\n\t\tif (c.needsReference) {\n\t\t\tconst refs = evidence.filter((obs): obs is ReferenceObservation => obs.kind === \"reference\");\n\t\t\tconst support = new Set(\n\t\t\t\trefs.filter((r) => r.stance === \"support\").map((r) => sources.get(r.sourceId)!.family),\n\t\t\t);\n\t\t\tif (refs.some((r) => r.stance === \"refute\")) add(\"contradictory-reference\");\n\t\t\telse if (support.size < c.minSourceFamilies) add(\"unsupported-reference\");\n\t\t}\n\t\tfor (const checkId of c.requiredCheckIds) {\n\t\t\tconst records = evidence\n\t\t\t\t.filter((obs): obs is CheckObservation => obs.kind === \"check\" && obs.checkId === checkId)\n\t\t\t\t.sort((a, b) => a.sequence - b.sequence);\n\t\t\tconst latest = records.at(-1);\n\t\t\tif (!latest) add(\"missing-check\", checkId);\n\t\t\telse if (latest.verdict === \"fail\") add(\"failed-check\", checkId);\n\t\t\telse if (latest.verdict === \"pending\") add(\"pending-check\", checkId);\n\t\t}\n\t\tif (c.needsUserDecision) {\n\t\t\tconst decisions = evidence.filter((obs): obs is DecisionObservation => obs.kind === \"decision\");\n\t\t\tif (!decisions.some((d) => d.accepted) || decisions.some((d) => !d.accepted)) add(\"missing-user-decision\");\n\t\t}\n\t\tif (before === gaps.length) supportedClaimIds.push(c.id);\n\t}\n\tgaps.sort(\n\t\t(a, b) =>\n\t\t\tNumber(b.required) - Number(a.required) ||\n\t\t\tb.impact - a.impact ||\n\t\t\tlexical(a.claimId, b.claimId) ||\n\t\t\tlexical(a.reason, b.reason),\n\t);\n\treturn {\n\t\tstate: gaps.some((g) => g.required) ? \"gaps\" : \"supported\",\n\t\tgaps,\n\t\tsupportedClaimIds: supportedClaimIds.sort(lexical),\n\t\trejectedObservations,\n\t};\n}\n"]}
@@ -0,0 +1,82 @@
1
+ export type ObservationSource = "host-observed" | "analyzer-inferred" | "model-hypothesized";
2
+ export type Coverage = "covered" | "partial" | "unsupported" | "unknown";
3
+ /** §4.2: one observable change atom, not a filename or keyword. */
4
+ export interface ChangeAtom {
5
+ readonly id: string;
6
+ readonly targetId: string;
7
+ readonly operation: string;
8
+ readonly trustBoundary: string;
9
+ readonly temporal: "synchronous" | "async" | "concurrent" | "retried" | "none";
10
+ readonly externalEffect: "none" | "read" | "write" | "network" | "payment" | "delete";
11
+ readonly source: ObservationSource;
12
+ readonly analyzerCoverage: Coverage;
13
+ }
14
+ /** A versioned host rule: when its predicates hold, instantiate obligations. */
15
+ export interface ObligationRule {
16
+ readonly ruleId: string;
17
+ readonly ruleVersion: string;
18
+ readonly description: string;
19
+ readonly match: {
20
+ readonly temporal?: readonly ChangeAtom["temporal"][];
21
+ readonly externalEffect?: readonly ChangeAtom["externalEffect"][];
22
+ readonly trustBoundary?: readonly string[];
23
+ readonly operation?: readonly string[];
24
+ };
25
+ /** Obligations instantiated when this rule fires. */
26
+ readonly produce: readonly {
27
+ readonly obligationId: string;
28
+ readonly statement: string;
29
+ readonly kind: "precondition" | "postcondition";
30
+ readonly checkMethodId: string | null;
31
+ readonly required: boolean;
32
+ readonly impact: number;
33
+ readonly minSourceFamilies?: number;
34
+ readonly requiresVersion?: boolean;
35
+ }[];
36
+ }
37
+ export type ObligationStatus = "candidate" | "required" | "satisfied" | "violated" | "blocked-high-risk";
38
+ export interface Obligation {
39
+ readonly id: string;
40
+ readonly atomId: string;
41
+ readonly ruleId: string;
42
+ readonly ruleVersion: string;
43
+ readonly statement: string;
44
+ readonly kind: "precondition" | "postcondition";
45
+ readonly checkMethodId: string | null;
46
+ readonly scope: string;
47
+ readonly triggerObservationIds: readonly string[];
48
+ readonly required: boolean;
49
+ readonly impact: number;
50
+ readonly novelty: number;
51
+ readonly normalizedCost: number;
52
+ readonly coverageFraction: number;
53
+ status: ObligationStatus;
54
+ }
55
+ export interface ObligationReport {
56
+ readonly required: readonly Obligation[];
57
+ readonly candidates: readonly Obligation[];
58
+ /** Effects/rules we could not map — never claim completeness. */
59
+ readonly unmappedEffects: readonly string[];
60
+ readonly unsupportedSyntax: readonly string[];
61
+ readonly unobservedConsumers: readonly string[];
62
+ readonly coverage: "complete" | "partial" | "unknown";
63
+ }
64
+ export declare function validateAtom(atom: ChangeAtom): void;
65
+ /**
66
+ * Instantiate host rules over observed atoms. Rules fire only on atoms whose
67
+ * predicates are satisfied; `model-hypothesized` atoms produce candidates,
68
+ * never required obligations. High-risk effects on unverified hypotheses are
69
+ * surfaced as `blocked-high-risk` candidates so the host can gate the effect.
70
+ */
71
+ export declare function instantiateObligations(atoms: readonly ChangeAtom[], rules: readonly ObligationRule[], nowMs: number): ObligationReport;
72
+ /**
73
+ * §4.4 ranking score. NOT a failure probability — an explainable ordering key:
74
+ * J(o) = impact·(1-coverage)·(1+novelty) / (ε + normalizedCost).
75
+ * Priority classes are applied by the caller before this score is consulted.
76
+ */
77
+ export declare function obligationPriority(o: Obligation, epsilon?: number): number;
78
+ /** Close an obligation when its bound check passes; open violations when it fails. */
79
+ export declare function settleObligation(obligations: readonly Obligation[], obligationId: string, checkOutcome: "pass" | "fail" | "unverifiable"): readonly Obligation[];
80
+ /** Structural fingerprint for de-duplication across checkpoints. */
81
+ export declare function obligationFingerprint(o: Obligation): string;
82
+ //# sourceMappingURL=obligations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obligations.d.ts","sourceRoot":"","sources":["../../src/metacognition/obligations.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,mBAAmB,GAAG,oBAAoB,CAAC;AAC7F,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAC;AAEzE,oEAAmE;AACnE,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;IAC/E,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtF,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC;CACpC;AACD,gFAAgF;AAChF,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE;QACf,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAC3C,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACvC,CAAC;IACF,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,SAAS;QAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAAC;QAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QACtC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;QACpC,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;KACnC,EAAE,CAAC;CACJ;AACD,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,mBAAmB,CAAC;AACzG,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,CAAC;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,MAAM,EAAE,gBAAgB,CAAC;CACzB;AACD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,SAAS,UAAU,EAAE,CAAC;IAC3C,mEAAiE;IACjE,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;CACtD;AAKD,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CASnD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,KAAK,EAAE,MAAM,GACX,gBAAgB,CAiFlB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,SAAO,GAAG,MAAM,CAOxE;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC/B,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,GAC5C,SAAS,UAAU,EAAE,CAQvB;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAE3D","sourcesContent":["/**\n * Algorithm A — missing-condition discovery and obligation generation.\n * Spec: OMK_metacognitive_control_algorithms_2026-09-19.md §4.\n *\n * Change atoms (target + operation + trust boundary + temporal property +\n * external effect + observation source + analyzer coverage) are matched\n * against a versioned host rule set. Host facts promote candidates to\n * required obligations; model hypotheses stay candidates. Model proposals\n * can never remove user or policy obligations.\n */\nimport { canonical, ensure, finite, integer, lexical, member, text, unique } from \"./validation.ts\";\n\nexport type ObservationSource = \"host-observed\" | \"analyzer-inferred\" | \"model-hypothesized\";\nexport type Coverage = \"covered\" | \"partial\" | \"unsupported\" | \"unknown\";\n\n/** §4.2: one observable change atom, not a filename or keyword. */\nexport interface ChangeAtom {\n\treadonly id: string;\n\treadonly targetId: string;\n\treadonly operation: string;\n\treadonly trustBoundary: string;\n\treadonly temporal: \"synchronous\" | \"async\" | \"concurrent\" | \"retried\" | \"none\";\n\treadonly externalEffect: \"none\" | \"read\" | \"write\" | \"network\" | \"payment\" | \"delete\";\n\treadonly source: ObservationSource;\n\treadonly analyzerCoverage: Coverage;\n}\n/** A versioned host rule: when its predicates hold, instantiate obligations. */\nexport interface ObligationRule {\n\treadonly ruleId: string;\n\treadonly ruleVersion: string;\n\treadonly description: string;\n\treadonly match: {\n\t\treadonly temporal?: readonly ChangeAtom[\"temporal\"][];\n\t\treadonly externalEffect?: readonly ChangeAtom[\"externalEffect\"][];\n\t\treadonly trustBoundary?: readonly string[];\n\t\treadonly operation?: readonly string[];\n\t};\n\t/** Obligations instantiated when this rule fires. */\n\treadonly produce: readonly {\n\t\treadonly obligationId: string;\n\t\treadonly statement: string;\n\t\treadonly kind: \"precondition\" | \"postcondition\";\n\t\treadonly checkMethodId: string | null;\n\t\treadonly required: boolean;\n\t\treadonly impact: number;\n\t\treadonly minSourceFamilies?: number;\n\t\treadonly requiresVersion?: boolean;\n\t}[];\n}\nexport type ObligationStatus = \"candidate\" | \"required\" | \"satisfied\" | \"violated\" | \"blocked-high-risk\";\nexport interface Obligation {\n\treadonly id: string;\n\treadonly atomId: string;\n\treadonly ruleId: string;\n\treadonly ruleVersion: string;\n\treadonly statement: string;\n\treadonly kind: \"precondition\" | \"postcondition\";\n\treadonly checkMethodId: string | null;\n\treadonly scope: string;\n\treadonly triggerObservationIds: readonly string[];\n\treadonly required: boolean;\n\treadonly impact: number;\n\treadonly novelty: number;\n\treadonly normalizedCost: number;\n\treadonly coverageFraction: number;\n\tstatus: ObligationStatus;\n}\nexport interface ObligationReport {\n\treadonly required: readonly Obligation[];\n\treadonly candidates: readonly Obligation[];\n\t/** Effects/rules we could not map — never claim completeness. */\n\treadonly unmappedEffects: readonly string[];\n\treadonly unsupportedSyntax: readonly string[];\n\treadonly unobservedConsumers: readonly string[];\n\treadonly coverage: \"complete\" | \"partial\" | \"unknown\";\n}\n\nconst ATOM_BOUND = 512;\nconst RULE_BOUND = 256;\n\nexport function validateAtom(atom: ChangeAtom): void {\n\ttext(atom.id, \"atom id\", 128);\n\ttext(atom.targetId, \"targetId\", 512);\n\ttext(atom.operation, \"operation\", 128);\n\ttext(atom.trustBoundary, \"trustBoundary\", 256);\n\tmember(atom.temporal, [\"synchronous\", \"async\", \"concurrent\", \"retried\", \"none\"], \"temporal\");\n\tmember(atom.externalEffect, [\"none\", \"read\", \"write\", \"network\", \"payment\", \"delete\"], \"externalEffect\");\n\tmember(atom.source, [\"host-observed\", \"analyzer-inferred\", \"model-hypothesized\"], \"atom source\");\n\tmember(atom.analyzerCoverage, [\"covered\", \"partial\", \"unsupported\", \"unknown\"], \"analyzerCoverage\");\n}\n\n/**\n * Instantiate host rules over observed atoms. Rules fire only on atoms whose\n * predicates are satisfied; `model-hypothesized` atoms produce candidates,\n * never required obligations. High-risk effects on unverified hypotheses are\n * surfaced as `blocked-high-risk` candidates so the host can gate the effect.\n */\nexport function instantiateObligations(\n\tatoms: readonly ChangeAtom[],\n\trules: readonly ObligationRule[],\n\tnowMs: number,\n): ObligationReport {\n\tinteger(nowMs, \"nowMs\");\n\tensure(atoms.length <= ATOM_BOUND, \"too many atoms\");\n\tensure(rules.length <= RULE_BOUND, \"too many rules\");\n\tunique(\n\t\tatoms.map((a) => a.id),\n\t\t\"atom ids\",\n\t);\n\tunique(\n\t\trules.map((r) => r.ruleId),\n\t\t\"rule ids\",\n\t);\n\tfor (const atom of atoms) validateAtom(atom);\n\tfor (const rule of rules) {\n\t\ttext(rule.ruleVersion, \"ruleVersion\", 64);\n\t\ttext(rule.description, \"rule description\", 512);\n\t\tensure(rule.produce.length > 0 && rule.produce.length <= 32, \"rule produce bounds\");\n\t}\n\tconst required: Obligation[] = [];\n\tconst candidates: Obligation[] = [];\n\tconst unmappedEffects: string[] = [];\n\tconst unsupportedSyntax: string[] = [];\n\tconst _unobservedConsumers: string[] = [];\n\tlet sawUnknownCoverage = false;\n\tfor (const atom of atoms) {\n\t\tif (atom.analyzerCoverage === \"unknown\") sawUnknownCoverage = true;\n\t\tif (atom.analyzerCoverage === \"unsupported\") unsupportedSyntax.push(atom.id);\n\t\tlet matched = false;\n\t\tfor (const rule of rules) {\n\t\t\tconst m = rule.match;\n\t\t\tif (m.temporal && !m.temporal.includes(atom.temporal)) continue;\n\t\t\tif (m.externalEffect && !m.externalEffect.includes(atom.externalEffect)) continue;\n\t\t\tif (m.trustBoundary && !m.trustBoundary.includes(atom.trustBoundary)) continue;\n\t\t\tif (m.operation && !m.operation.includes(atom.operation)) continue;\n\t\t\tmatched = true;\n\t\t\tfor (const prod of rule.produce) {\n\t\t\t\tfinite(prod.impact, \"obligation impact\", 1_000_000);\n\t\t\t\tconst novelty = atom.source === \"model-hypothesized\" ? 1 : 0.5;\n\t\t\t\tconst obligation: Obligation = {\n\t\t\t\t\tid: `${rule.ruleId}:${atom.id}:${prod.obligationId}`,\n\t\t\t\t\tatomId: atom.id,\n\t\t\t\t\truleId: rule.ruleId,\n\t\t\t\t\truleVersion: rule.ruleVersion,\n\t\t\t\t\tstatement: prod.statement,\n\t\t\t\t\tkind: prod.kind,\n\t\t\t\t\tcheckMethodId: prod.checkMethodId,\n\t\t\t\t\tscope: atom.targetId,\n\t\t\t\t\ttriggerObservationIds: [atom.id],\n\t\t\t\t\trequired: prod.required,\n\t\t\t\t\timpact: prod.impact,\n\t\t\t\t\tnovelty,\n\t\t\t\t\tnormalizedCost: 1,\n\t\t\t\t\tcoverageFraction: 0,\n\t\t\t\t\tstatus:\n\t\t\t\t\t\tatom.source === \"model-hypothesized\"\n\t\t\t\t\t\t\t? atom.externalEffect === \"write\" ||\n\t\t\t\t\t\t\t\tatom.externalEffect === \"payment\" ||\n\t\t\t\t\t\t\t\tatom.externalEffect === \"delete\"\n\t\t\t\t\t\t\t\t? \"blocked-high-risk\"\n\t\t\t\t\t\t\t\t: \"candidate\"\n\t\t\t\t\t\t\t: prod.required\n\t\t\t\t\t\t\t\t? \"required\"\n\t\t\t\t\t\t\t\t: \"candidate\",\n\t\t\t\t};\n\t\t\t\t(atom.source === \"model-hypothesized\" ? candidates : required).push(obligation);\n\t\t\t}\n\t\t}\n\t\tif (!matched && atom.externalEffect !== \"none\") unmappedEffects.push(atom.id);\n\t}\n\tconst sortObligations = (a: Obligation, b: Obligation): number => b.impact - a.impact || lexical(a.id, b.id);\n\trequired.sort(sortObligations);\n\tcandidates.sort(sortObligations);\n\treturn {\n\t\trequired: required.filter((o) => o.status === \"required\"),\n\t\tcandidates,\n\t\tunmappedEffects: unmappedEffects.sort(lexical),\n\t\tunsupportedSyntax: unsupportedSyntax.sort(lexical),\n\t\tunobservedConsumers: [],\n\t\tcoverage:\n\t\t\tsawUnknownCoverage || unmappedEffects.length > 0 || unsupportedSyntax.length > 0 ? \"unknown\" : \"partial\",\n\t};\n}\n\n/**\n * §4.4 ranking score. NOT a failure probability — an explainable ordering key:\n * J(o) = impact·(1-coverage)·(1+novelty) / (ε + normalizedCost).\n * Priority classes are applied by the caller before this score is consulted.\n */\nexport function obligationPriority(o: Obligation, epsilon = 0.01): number {\n\tfinite(o.impact, \"impact\", 1_000_000);\n\tfinite(o.coverageFraction, \"coverage\", 1);\n\tfinite(o.novelty, \"novelty\", 1);\n\tfinite(o.normalizedCost, \"cost\", 1_000_000);\n\tfinite(epsilon, \"epsilon\", 1);\n\treturn (o.impact * (1 - o.coverageFraction) * (1 + o.novelty)) / (epsilon + o.normalizedCost);\n}\n\n/** Close an obligation when its bound check passes; open violations when it fails. */\nexport function settleObligation(\n\tobligations: readonly Obligation[],\n\tobligationId: string,\n\tcheckOutcome: \"pass\" | \"fail\" | \"unverifiable\",\n): readonly Obligation[] {\n\ttext(obligationId, \"obligationId\", 512);\n\treturn obligations.map((o) => {\n\t\tif (o.id !== obligationId) return o;\n\t\tconst status: ObligationStatus =\n\t\t\tcheckOutcome === \"pass\" ? \"satisfied\" : checkOutcome === \"fail\" ? \"violated\" : o.status;\n\t\treturn { ...o, status };\n\t});\n}\n\n/** Structural fingerprint for de-duplication across checkpoints. */\nexport function obligationFingerprint(o: Obligation): string {\n\treturn canonical([o.ruleId, o.ruleVersion, o.atomId, o.statement, o.scope]);\n}\n"]}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Algorithm A — missing-condition discovery and obligation generation.
3
+ * Spec: OMK_metacognitive_control_algorithms_2026-09-19.md §4.
4
+ *
5
+ * Change atoms (target + operation + trust boundary + temporal property +
6
+ * external effect + observation source + analyzer coverage) are matched
7
+ * against a versioned host rule set. Host facts promote candidates to
8
+ * required obligations; model hypotheses stay candidates. Model proposals
9
+ * can never remove user or policy obligations.
10
+ */
11
+ import { canonical, ensure, finite, integer, lexical, member, text, unique } from "./validation.js";
12
+ const ATOM_BOUND = 512;
13
+ const RULE_BOUND = 256;
14
+ export function validateAtom(atom) {
15
+ text(atom.id, "atom id", 128);
16
+ text(atom.targetId, "targetId", 512);
17
+ text(atom.operation, "operation", 128);
18
+ text(atom.trustBoundary, "trustBoundary", 256);
19
+ member(atom.temporal, ["synchronous", "async", "concurrent", "retried", "none"], "temporal");
20
+ member(atom.externalEffect, ["none", "read", "write", "network", "payment", "delete"], "externalEffect");
21
+ member(atom.source, ["host-observed", "analyzer-inferred", "model-hypothesized"], "atom source");
22
+ member(atom.analyzerCoverage, ["covered", "partial", "unsupported", "unknown"], "analyzerCoverage");
23
+ }
24
+ /**
25
+ * Instantiate host rules over observed atoms. Rules fire only on atoms whose
26
+ * predicates are satisfied; `model-hypothesized` atoms produce candidates,
27
+ * never required obligations. High-risk effects on unverified hypotheses are
28
+ * surfaced as `blocked-high-risk` candidates so the host can gate the effect.
29
+ */
30
+ export function instantiateObligations(atoms, rules, nowMs) {
31
+ integer(nowMs, "nowMs");
32
+ ensure(atoms.length <= ATOM_BOUND, "too many atoms");
33
+ ensure(rules.length <= RULE_BOUND, "too many rules");
34
+ unique(atoms.map((a) => a.id), "atom ids");
35
+ unique(rules.map((r) => r.ruleId), "rule ids");
36
+ for (const atom of atoms)
37
+ validateAtom(atom);
38
+ for (const rule of rules) {
39
+ text(rule.ruleVersion, "ruleVersion", 64);
40
+ text(rule.description, "rule description", 512);
41
+ ensure(rule.produce.length > 0 && rule.produce.length <= 32, "rule produce bounds");
42
+ }
43
+ const required = [];
44
+ const candidates = [];
45
+ const unmappedEffects = [];
46
+ const unsupportedSyntax = [];
47
+ const _unobservedConsumers = [];
48
+ let sawUnknownCoverage = false;
49
+ for (const atom of atoms) {
50
+ if (atom.analyzerCoverage === "unknown")
51
+ sawUnknownCoverage = true;
52
+ if (atom.analyzerCoverage === "unsupported")
53
+ unsupportedSyntax.push(atom.id);
54
+ let matched = false;
55
+ for (const rule of rules) {
56
+ const m = rule.match;
57
+ if (m.temporal && !m.temporal.includes(atom.temporal))
58
+ continue;
59
+ if (m.externalEffect && !m.externalEffect.includes(atom.externalEffect))
60
+ continue;
61
+ if (m.trustBoundary && !m.trustBoundary.includes(atom.trustBoundary))
62
+ continue;
63
+ if (m.operation && !m.operation.includes(atom.operation))
64
+ continue;
65
+ matched = true;
66
+ for (const prod of rule.produce) {
67
+ finite(prod.impact, "obligation impact", 1_000_000);
68
+ const novelty = atom.source === "model-hypothesized" ? 1 : 0.5;
69
+ const obligation = {
70
+ id: `${rule.ruleId}:${atom.id}:${prod.obligationId}`,
71
+ atomId: atom.id,
72
+ ruleId: rule.ruleId,
73
+ ruleVersion: rule.ruleVersion,
74
+ statement: prod.statement,
75
+ kind: prod.kind,
76
+ checkMethodId: prod.checkMethodId,
77
+ scope: atom.targetId,
78
+ triggerObservationIds: [atom.id],
79
+ required: prod.required,
80
+ impact: prod.impact,
81
+ novelty,
82
+ normalizedCost: 1,
83
+ coverageFraction: 0,
84
+ status: atom.source === "model-hypothesized"
85
+ ? atom.externalEffect === "write" ||
86
+ atom.externalEffect === "payment" ||
87
+ atom.externalEffect === "delete"
88
+ ? "blocked-high-risk"
89
+ : "candidate"
90
+ : prod.required
91
+ ? "required"
92
+ : "candidate",
93
+ };
94
+ (atom.source === "model-hypothesized" ? candidates : required).push(obligation);
95
+ }
96
+ }
97
+ if (!matched && atom.externalEffect !== "none")
98
+ unmappedEffects.push(atom.id);
99
+ }
100
+ const sortObligations = (a, b) => b.impact - a.impact || lexical(a.id, b.id);
101
+ required.sort(sortObligations);
102
+ candidates.sort(sortObligations);
103
+ return {
104
+ required: required.filter((o) => o.status === "required"),
105
+ candidates,
106
+ unmappedEffects: unmappedEffects.sort(lexical),
107
+ unsupportedSyntax: unsupportedSyntax.sort(lexical),
108
+ unobservedConsumers: [],
109
+ coverage: sawUnknownCoverage || unmappedEffects.length > 0 || unsupportedSyntax.length > 0 ? "unknown" : "partial",
110
+ };
111
+ }
112
+ /**
113
+ * §4.4 ranking score. NOT a failure probability — an explainable ordering key:
114
+ * J(o) = impact·(1-coverage)·(1+novelty) / (ε + normalizedCost).
115
+ * Priority classes are applied by the caller before this score is consulted.
116
+ */
117
+ export function obligationPriority(o, epsilon = 0.01) {
118
+ finite(o.impact, "impact", 1_000_000);
119
+ finite(o.coverageFraction, "coverage", 1);
120
+ finite(o.novelty, "novelty", 1);
121
+ finite(o.normalizedCost, "cost", 1_000_000);
122
+ finite(epsilon, "epsilon", 1);
123
+ return (o.impact * (1 - o.coverageFraction) * (1 + o.novelty)) / (epsilon + o.normalizedCost);
124
+ }
125
+ /** Close an obligation when its bound check passes; open violations when it fails. */
126
+ export function settleObligation(obligations, obligationId, checkOutcome) {
127
+ text(obligationId, "obligationId", 512);
128
+ return obligations.map((o) => {
129
+ if (o.id !== obligationId)
130
+ return o;
131
+ const status = checkOutcome === "pass" ? "satisfied" : checkOutcome === "fail" ? "violated" : o.status;
132
+ return { ...o, status };
133
+ });
134
+ }
135
+ /** Structural fingerprint for de-duplication across checkpoints. */
136
+ export function obligationFingerprint(o) {
137
+ return canonical([o.ruleId, o.ruleVersion, o.atomId, o.statement, o.scope]);
138
+ }
139
+ //# sourceMappingURL=obligations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obligations.js","sourceRoot":"","sources":["../../src/metacognition/obligations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Algorithm A — missing-condition discovery and obligation generation.\n * Spec: OMK_metacognitive_control_algorithms_2026-09-19.md §4.\n *\n * Change atoms (target + operation + trust boundary + temporal property +\n * external effect + observation source + analyzer coverage) are matched\n * against a versioned host rule set. Host facts promote candidates to\n * required obligations; model hypotheses stay candidates. Model proposals\n * can never remove user or policy obligations.\n */\nimport { canonical, ensure, finite, integer, lexical, member, text, unique } from \"./validation.ts\";\n\nexport type ObservationSource = \"host-observed\" | \"analyzer-inferred\" | \"model-hypothesized\";\nexport type Coverage = \"covered\" | \"partial\" | \"unsupported\" | \"unknown\";\n\n/** §4.2: one observable change atom, not a filename or keyword. */\nexport interface ChangeAtom {\n\treadonly id: string;\n\treadonly targetId: string;\n\treadonly operation: string;\n\treadonly trustBoundary: string;\n\treadonly temporal: \"synchronous\" | \"async\" | \"concurrent\" | \"retried\" | \"none\";\n\treadonly externalEffect: \"none\" | \"read\" | \"write\" | \"network\" | \"payment\" | \"delete\";\n\treadonly source: ObservationSource;\n\treadonly analyzerCoverage: Coverage;\n}\n/** A versioned host rule: when its predicates hold, instantiate obligations. */\nexport interface ObligationRule {\n\treadonly ruleId: string;\n\treadonly ruleVersion: string;\n\treadonly description: string;\n\treadonly match: {\n\t\treadonly temporal?: readonly ChangeAtom[\"temporal\"][];\n\t\treadonly externalEffect?: readonly ChangeAtom[\"externalEffect\"][];\n\t\treadonly trustBoundary?: readonly string[];\n\t\treadonly operation?: readonly string[];\n\t};\n\t/** Obligations instantiated when this rule fires. */\n\treadonly produce: readonly {\n\t\treadonly obligationId: string;\n\t\treadonly statement: string;\n\t\treadonly kind: \"precondition\" | \"postcondition\";\n\t\treadonly checkMethodId: string | null;\n\t\treadonly required: boolean;\n\t\treadonly impact: number;\n\t\treadonly minSourceFamilies?: number;\n\t\treadonly requiresVersion?: boolean;\n\t}[];\n}\nexport type ObligationStatus = \"candidate\" | \"required\" | \"satisfied\" | \"violated\" | \"blocked-high-risk\";\nexport interface Obligation {\n\treadonly id: string;\n\treadonly atomId: string;\n\treadonly ruleId: string;\n\treadonly ruleVersion: string;\n\treadonly statement: string;\n\treadonly kind: \"precondition\" | \"postcondition\";\n\treadonly checkMethodId: string | null;\n\treadonly scope: string;\n\treadonly triggerObservationIds: readonly string[];\n\treadonly required: boolean;\n\treadonly impact: number;\n\treadonly novelty: number;\n\treadonly normalizedCost: number;\n\treadonly coverageFraction: number;\n\tstatus: ObligationStatus;\n}\nexport interface ObligationReport {\n\treadonly required: readonly Obligation[];\n\treadonly candidates: readonly Obligation[];\n\t/** Effects/rules we could not map — never claim completeness. */\n\treadonly unmappedEffects: readonly string[];\n\treadonly unsupportedSyntax: readonly string[];\n\treadonly unobservedConsumers: readonly string[];\n\treadonly coverage: \"complete\" | \"partial\" | \"unknown\";\n}\n\nconst ATOM_BOUND = 512;\nconst RULE_BOUND = 256;\n\nexport function validateAtom(atom: ChangeAtom): void {\n\ttext(atom.id, \"atom id\", 128);\n\ttext(atom.targetId, \"targetId\", 512);\n\ttext(atom.operation, \"operation\", 128);\n\ttext(atom.trustBoundary, \"trustBoundary\", 256);\n\tmember(atom.temporal, [\"synchronous\", \"async\", \"concurrent\", \"retried\", \"none\"], \"temporal\");\n\tmember(atom.externalEffect, [\"none\", \"read\", \"write\", \"network\", \"payment\", \"delete\"], \"externalEffect\");\n\tmember(atom.source, [\"host-observed\", \"analyzer-inferred\", \"model-hypothesized\"], \"atom source\");\n\tmember(atom.analyzerCoverage, [\"covered\", \"partial\", \"unsupported\", \"unknown\"], \"analyzerCoverage\");\n}\n\n/**\n * Instantiate host rules over observed atoms. Rules fire only on atoms whose\n * predicates are satisfied; `model-hypothesized` atoms produce candidates,\n * never required obligations. High-risk effects on unverified hypotheses are\n * surfaced as `blocked-high-risk` candidates so the host can gate the effect.\n */\nexport function instantiateObligations(\n\tatoms: readonly ChangeAtom[],\n\trules: readonly ObligationRule[],\n\tnowMs: number,\n): ObligationReport {\n\tinteger(nowMs, \"nowMs\");\n\tensure(atoms.length <= ATOM_BOUND, \"too many atoms\");\n\tensure(rules.length <= RULE_BOUND, \"too many rules\");\n\tunique(\n\t\tatoms.map((a) => a.id),\n\t\t\"atom ids\",\n\t);\n\tunique(\n\t\trules.map((r) => r.ruleId),\n\t\t\"rule ids\",\n\t);\n\tfor (const atom of atoms) validateAtom(atom);\n\tfor (const rule of rules) {\n\t\ttext(rule.ruleVersion, \"ruleVersion\", 64);\n\t\ttext(rule.description, \"rule description\", 512);\n\t\tensure(rule.produce.length > 0 && rule.produce.length <= 32, \"rule produce bounds\");\n\t}\n\tconst required: Obligation[] = [];\n\tconst candidates: Obligation[] = [];\n\tconst unmappedEffects: string[] = [];\n\tconst unsupportedSyntax: string[] = [];\n\tconst _unobservedConsumers: string[] = [];\n\tlet sawUnknownCoverage = false;\n\tfor (const atom of atoms) {\n\t\tif (atom.analyzerCoverage === \"unknown\") sawUnknownCoverage = true;\n\t\tif (atom.analyzerCoverage === \"unsupported\") unsupportedSyntax.push(atom.id);\n\t\tlet matched = false;\n\t\tfor (const rule of rules) {\n\t\t\tconst m = rule.match;\n\t\t\tif (m.temporal && !m.temporal.includes(atom.temporal)) continue;\n\t\t\tif (m.externalEffect && !m.externalEffect.includes(atom.externalEffect)) continue;\n\t\t\tif (m.trustBoundary && !m.trustBoundary.includes(atom.trustBoundary)) continue;\n\t\t\tif (m.operation && !m.operation.includes(atom.operation)) continue;\n\t\t\tmatched = true;\n\t\t\tfor (const prod of rule.produce) {\n\t\t\t\tfinite(prod.impact, \"obligation impact\", 1_000_000);\n\t\t\t\tconst novelty = atom.source === \"model-hypothesized\" ? 1 : 0.5;\n\t\t\t\tconst obligation: Obligation = {\n\t\t\t\t\tid: `${rule.ruleId}:${atom.id}:${prod.obligationId}`,\n\t\t\t\t\tatomId: atom.id,\n\t\t\t\t\truleId: rule.ruleId,\n\t\t\t\t\truleVersion: rule.ruleVersion,\n\t\t\t\t\tstatement: prod.statement,\n\t\t\t\t\tkind: prod.kind,\n\t\t\t\t\tcheckMethodId: prod.checkMethodId,\n\t\t\t\t\tscope: atom.targetId,\n\t\t\t\t\ttriggerObservationIds: [atom.id],\n\t\t\t\t\trequired: prod.required,\n\t\t\t\t\timpact: prod.impact,\n\t\t\t\t\tnovelty,\n\t\t\t\t\tnormalizedCost: 1,\n\t\t\t\t\tcoverageFraction: 0,\n\t\t\t\t\tstatus:\n\t\t\t\t\t\tatom.source === \"model-hypothesized\"\n\t\t\t\t\t\t\t? atom.externalEffect === \"write\" ||\n\t\t\t\t\t\t\t\tatom.externalEffect === \"payment\" ||\n\t\t\t\t\t\t\t\tatom.externalEffect === \"delete\"\n\t\t\t\t\t\t\t\t? \"blocked-high-risk\"\n\t\t\t\t\t\t\t\t: \"candidate\"\n\t\t\t\t\t\t\t: prod.required\n\t\t\t\t\t\t\t\t? \"required\"\n\t\t\t\t\t\t\t\t: \"candidate\",\n\t\t\t\t};\n\t\t\t\t(atom.source === \"model-hypothesized\" ? candidates : required).push(obligation);\n\t\t\t}\n\t\t}\n\t\tif (!matched && atom.externalEffect !== \"none\") unmappedEffects.push(atom.id);\n\t}\n\tconst sortObligations = (a: Obligation, b: Obligation): number => b.impact - a.impact || lexical(a.id, b.id);\n\trequired.sort(sortObligations);\n\tcandidates.sort(sortObligations);\n\treturn {\n\t\trequired: required.filter((o) => o.status === \"required\"),\n\t\tcandidates,\n\t\tunmappedEffects: unmappedEffects.sort(lexical),\n\t\tunsupportedSyntax: unsupportedSyntax.sort(lexical),\n\t\tunobservedConsumers: [],\n\t\tcoverage:\n\t\t\tsawUnknownCoverage || unmappedEffects.length > 0 || unsupportedSyntax.length > 0 ? \"unknown\" : \"partial\",\n\t};\n}\n\n/**\n * §4.4 ranking score. NOT a failure probability — an explainable ordering key:\n * J(o) = impact·(1-coverage)·(1+novelty) / (ε + normalizedCost).\n * Priority classes are applied by the caller before this score is consulted.\n */\nexport function obligationPriority(o: Obligation, epsilon = 0.01): number {\n\tfinite(o.impact, \"impact\", 1_000_000);\n\tfinite(o.coverageFraction, \"coverage\", 1);\n\tfinite(o.novelty, \"novelty\", 1);\n\tfinite(o.normalizedCost, \"cost\", 1_000_000);\n\tfinite(epsilon, \"epsilon\", 1);\n\treturn (o.impact * (1 - o.coverageFraction) * (1 + o.novelty)) / (epsilon + o.normalizedCost);\n}\n\n/** Close an obligation when its bound check passes; open violations when it fails. */\nexport function settleObligation(\n\tobligations: readonly Obligation[],\n\tobligationId: string,\n\tcheckOutcome: \"pass\" | \"fail\" | \"unverifiable\",\n): readonly Obligation[] {\n\ttext(obligationId, \"obligationId\", 512);\n\treturn obligations.map((o) => {\n\t\tif (o.id !== obligationId) return o;\n\t\tconst status: ObligationStatus =\n\t\t\tcheckOutcome === \"pass\" ? \"satisfied\" : checkOutcome === \"fail\" ? \"violated\" : o.status;\n\t\treturn { ...o, status };\n\t});\n}\n\n/** Structural fingerprint for de-duplication across checkpoints. */\nexport function obligationFingerprint(o: Obligation): string {\n\treturn canonical([o.ruleId, o.ruleVersion, o.atomId, o.statement, o.scope]);\n}\n"]}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Observation validity and state packing (Jev audit algorithm A2, finding F10).
3
+ *
4
+ * F10: the value the existing code calls `freshness` is really a change
5
+ * indicator. Those are different facts — a screen observed one millisecond ago
6
+ * that has not changed scores zero on one and one on the other — so this module
7
+ * reports them separately and never derives one from the other.
8
+ *
9
+ * For anything risky the decay score is not the gate at all. An explicit
10
+ * maximum observation age and equality of the document and action generations
11
+ * decide validity; the decay value is a continuous signal for ranking, not a
12
+ * learned safety probability.
13
+ *
14
+ * "Check then click" is not a database transaction: the page keeps running.
15
+ * Re-checking the target narrows the race window, and the postcondition is what
16
+ * actually establishes the result.
17
+ */
18
+ /** f = exp(−Δt/τ). A ranking signal, not a probability of safety. */
19
+ export declare function timeDecayFreshness(elapsedMs: number, decayConstantMs: number): number;
20
+ /** n = 1[h(x_t) ≠ h(x_{t−1})]. Orthogonal to age. */
21
+ export declare function changeIndicator(previousStateHash: string | undefined, currentStateHash: string | undefined): 0 | 1;
22
+ export interface ObservationValidityInput {
23
+ readonly observedAtMs: number;
24
+ readonly dispatchAtMs: number;
25
+ readonly decayConstantMs: number;
26
+ /** Hard bound for this risk tier; outranks any decay score. */
27
+ readonly maxObservationAgeMs: number;
28
+ /** Navigation, frame swap, tab swap, permission-session change. */
29
+ readonly observedDocumentGeneration: number;
30
+ readonly currentDocumentGeneration: number;
31
+ /** Chosen element's attachment, role, name, arguments, enabled state. */
32
+ readonly observedActionGeneration: number;
33
+ readonly currentActionGeneration: number;
34
+ readonly previousStateHash?: string;
35
+ readonly currentStateHash?: string;
36
+ }
37
+ export type ObservationValidityVerdict = {
38
+ readonly valid: true;
39
+ readonly freshness: number;
40
+ readonly changed: 0 | 1;
41
+ readonly ageMs: number;
42
+ } | {
43
+ readonly valid: false;
44
+ readonly reason: "document-generation-changed" | "action-generation-changed" | "max-age-exceeded";
45
+ };
46
+ /**
47
+ * Decide whether an observation may still back a dispatch.
48
+ *
49
+ * Generation mismatches are reported before age: if the page navigated, saying
50
+ * "observation too old" sends the operator to tune a timeout instead of looking
51
+ * at the navigation that actually invalidated the target.
52
+ */
53
+ export declare function evaluateObservationValidity(input: ObservationValidityInput): ObservationValidityVerdict;
54
+ export interface StateItem {
55
+ readonly id: string;
56
+ readonly tokenCost: number;
57
+ readonly utility: number;
58
+ readonly required: boolean;
59
+ }
60
+ export type StatePackingResult = {
61
+ readonly status: "packed";
62
+ readonly selected: readonly string[];
63
+ readonly tokensUsed: number;
64
+ readonly utility: number;
65
+ } | {
66
+ readonly status: "incomplete-state";
67
+ readonly missingRequired: readonly string[];
68
+ readonly requiredTokens: number;
69
+ readonly budget: number;
70
+ };
71
+ /**
72
+ * Pack observation state under a token budget.
73
+ *
74
+ * Required evidence is pinned first. When it alone exceeds the budget the
75
+ * result is `incomplete-state`, never a quietly truncated view: the caller has
76
+ * to narrow the observation rather than act on a state that lost its evidence.
77
+ *
78
+ * Optional items are then taken by utility density. That is the fixed-rule
79
+ * starting point the design asks for, not an optimal knapsack solution, and it
80
+ * is not claimed to be one.
81
+ */
82
+ export declare function packState(items: readonly StateItem[], budget: number): StatePackingResult;
83
+ //# sourceMappingURL=observation-validity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation-validity.d.ts","sourceRoot":"","sources":["../../src/metacognition/observation-validity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,yEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAUrF;AAED,yDAAqD;AACrD,wBAAgB,eAAe,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,EAAE,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,CAGlH;AAED,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,mEAAmE;IACnE,QAAQ,CAAC,0BAA0B,EAAE,MAAM,CAAC;IAC5C,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,yEAAyE;IACzE,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,MAAM,0BAA0B,GACnC;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrG;IACA,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,6BAA6B,GAAG,2BAA2B,GAAG,kBAAkB,CAAC;CACjG,CAAC;AAEL;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,wBAAwB,GAAG,0BAA0B,CAyBvG;AAED,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,MAAM,kBAAkB,GAC3B;IACA,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACxB,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACvB,CAAC;AAEL;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,kBAAkB,CA4CzF","sourcesContent":["/**\n * Observation validity and state packing (Jev audit algorithm A2, finding F10).\n *\n * F10: the value the existing code calls `freshness` is really a change\n * indicator. Those are different facts — a screen observed one millisecond ago\n * that has not changed scores zero on one and one on the other — so this module\n * reports them separately and never derives one from the other.\n *\n * For anything risky the decay score is not the gate at all. An explicit\n * maximum observation age and equality of the document and action generations\n * decide validity; the decay value is a continuous signal for ranking, not a\n * learned safety probability.\n *\n * \"Check then click\" is not a database transaction: the page keeps running.\n * Re-checking the target narrows the race window, and the postcondition is what\n * actually establishes the result.\n */\n\nimport { ensure } from \"./validation.ts\";\n\n/** f = exp(−Δt/τ). A ranking signal, not a probability of safety. */\nexport function timeDecayFreshness(elapsedMs: number, decayConstantMs: number): number {\n\tensure(\n\t\ttypeof elapsedMs === \"number\" && Number.isFinite(elapsedMs) && elapsedMs >= 0,\n\t\t\"elapsedMs must be a nonnegative finite number\",\n\t);\n\tensure(\n\t\ttypeof decayConstantMs === \"number\" && Number.isFinite(decayConstantMs) && decayConstantMs > 0,\n\t\t\"decayConstantMs must be positive\",\n\t);\n\treturn Math.exp(-elapsedMs / decayConstantMs);\n}\n\n/** n = 1[h(x_t) ≠ h(x_{t−1})]. Orthogonal to age. */\nexport function changeIndicator(previousStateHash: string | undefined, currentStateHash: string | undefined): 0 | 1 {\n\tif (previousStateHash === undefined || currentStateHash === undefined) return 0;\n\treturn previousStateHash === currentStateHash ? 0 : 1;\n}\n\nexport interface ObservationValidityInput {\n\treadonly observedAtMs: number;\n\treadonly dispatchAtMs: number;\n\treadonly decayConstantMs: number;\n\t/** Hard bound for this risk tier; outranks any decay score. */\n\treadonly maxObservationAgeMs: number;\n\t/** Navigation, frame swap, tab swap, permission-session change. */\n\treadonly observedDocumentGeneration: number;\n\treadonly currentDocumentGeneration: number;\n\t/** Chosen element's attachment, role, name, arguments, enabled state. */\n\treadonly observedActionGeneration: number;\n\treadonly currentActionGeneration: number;\n\treadonly previousStateHash?: string;\n\treadonly currentStateHash?: string;\n}\n\nexport type ObservationValidityVerdict =\n\t| { readonly valid: true; readonly freshness: number; readonly changed: 0 | 1; readonly ageMs: number }\n\t| {\n\t\t\treadonly valid: false;\n\t\t\treadonly reason: \"document-generation-changed\" | \"action-generation-changed\" | \"max-age-exceeded\";\n\t };\n\n/**\n * Decide whether an observation may still back a dispatch.\n *\n * Generation mismatches are reported before age: if the page navigated, saying\n * \"observation too old\" sends the operator to tune a timeout instead of looking\n * at the navigation that actually invalidated the target.\n */\nexport function evaluateObservationValidity(input: ObservationValidityInput): ObservationValidityVerdict {\n\tfor (const [label, value] of [\n\t\t[\"observedAtMs\", input.observedAtMs],\n\t\t[\"dispatchAtMs\", input.dispatchAtMs],\n\t\t[\"maxObservationAgeMs\", input.maxObservationAgeMs],\n\t] as const) {\n\t\tensure(typeof value === \"number\" && Number.isFinite(value) && value >= 0, `${label} must be nonnegative`);\n\t}\n\tconst ageMs = input.dispatchAtMs - input.observedAtMs;\n\tensure(ageMs >= 0, \"dispatchAtMs must not precede observedAtMs on a monotonic clock\");\n\n\tif (input.observedDocumentGeneration !== input.currentDocumentGeneration) {\n\t\treturn { valid: false, reason: \"document-generation-changed\" };\n\t}\n\tif (input.observedActionGeneration !== input.currentActionGeneration) {\n\t\treturn { valid: false, reason: \"action-generation-changed\" };\n\t}\n\tif (ageMs > input.maxObservationAgeMs) return { valid: false, reason: \"max-age-exceeded\" };\n\n\treturn {\n\t\tvalid: true,\n\t\tfreshness: timeDecayFreshness(ageMs, input.decayConstantMs),\n\t\tchanged: changeIndicator(input.previousStateHash, input.currentStateHash),\n\t\tageMs,\n\t};\n}\n\nexport interface StateItem {\n\treadonly id: string;\n\treadonly tokenCost: number;\n\treadonly utility: number;\n\treadonly required: boolean;\n}\n\nexport type StatePackingResult =\n\t| {\n\t\t\treadonly status: \"packed\";\n\t\t\treadonly selected: readonly string[];\n\t\t\treadonly tokensUsed: number;\n\t\t\treadonly utility: number;\n\t }\n\t| {\n\t\t\treadonly status: \"incomplete-state\";\n\t\t\treadonly missingRequired: readonly string[];\n\t\t\treadonly requiredTokens: number;\n\t\t\treadonly budget: number;\n\t };\n\n/**\n * Pack observation state under a token budget.\n *\n * Required evidence is pinned first. When it alone exceeds the budget the\n * result is `incomplete-state`, never a quietly truncated view: the caller has\n * to narrow the observation rather than act on a state that lost its evidence.\n *\n * Optional items are then taken by utility density. That is the fixed-rule\n * starting point the design asks for, not an optimal knapsack solution, and it\n * is not claimed to be one.\n */\nexport function packState(items: readonly StateItem[], budget: number): StatePackingResult {\n\tensure(Array.isArray(items), \"items must be an array\");\n\tensure(Number.isFinite(budget) && budget >= 0, \"budget must be nonnegative\");\n\tfor (const item of items) {\n\t\tensure(typeof item.id === \"string\" && item.id.length > 0, \"each item needs a non-empty id\");\n\t\tensure(Number.isFinite(item.tokenCost) && item.tokenCost >= 0, \"tokenCost must be nonnegative\");\n\t\tensure(Number.isFinite(item.utility) && item.utility >= 0, \"utility must be nonnegative\");\n\t}\n\n\tconst required: StateItem[] = [];\n\tconst optional: Array<{ item: StateItem; density: number }> = [];\n\tfor (const item of items) {\n\t\tif (item.required) required.push(item);\n\t\telse optional.push({ item, density: item.tokenCost === 0 ? Infinity : item.utility / item.tokenCost });\n\t}\n\tconst requiredTokens = required.reduce((sum, item) => sum + item.tokenCost, 0);\n\tif (requiredTokens > budget) {\n\t\treturn {\n\t\t\tstatus: \"incomplete-state\",\n\t\t\tmissingRequired: required.map((item) => item.id),\n\t\t\trequiredTokens,\n\t\t\tbudget,\n\t\t};\n\t}\n\n\tconst selected = required.map((item) => item.id);\n\tlet tokensUsed = requiredTokens;\n\tlet utility = required.reduce((sum, item) => sum + item.utility, 0);\n\n\t// Density order, with id as a tiebreak so equal densities pack deterministically.\n\tconst byId = (a: StateItem, b: StateItem): number => {\n\t\tif (a.id < b.id) return -1;\n\t\treturn a.id > b.id ? 1 : 0;\n\t};\n\toptional.sort((a, b) => b.density - a.density || byId(a.item, b.item));\n\n\tfor (const { item } of optional) {\n\t\tif (tokensUsed + item.tokenCost > budget) continue;\n\t\tselected.push(item.id);\n\t\ttokensUsed += item.tokenCost;\n\t\tutility += item.utility;\n\t}\n\n\treturn { status: \"packed\", selected, tokensUsed, utility };\n}\n"]}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Observation validity and state packing (Jev audit algorithm A2, finding F10).
3
+ *
4
+ * F10: the value the existing code calls `freshness` is really a change
5
+ * indicator. Those are different facts — a screen observed one millisecond ago
6
+ * that has not changed scores zero on one and one on the other — so this module
7
+ * reports them separately and never derives one from the other.
8
+ *
9
+ * For anything risky the decay score is not the gate at all. An explicit
10
+ * maximum observation age and equality of the document and action generations
11
+ * decide validity; the decay value is a continuous signal for ranking, not a
12
+ * learned safety probability.
13
+ *
14
+ * "Check then click" is not a database transaction: the page keeps running.
15
+ * Re-checking the target narrows the race window, and the postcondition is what
16
+ * actually establishes the result.
17
+ */
18
+ import { ensure } from "./validation.js";
19
+ /** f = exp(−Δt/τ). A ranking signal, not a probability of safety. */
20
+ export function timeDecayFreshness(elapsedMs, decayConstantMs) {
21
+ ensure(typeof elapsedMs === "number" && Number.isFinite(elapsedMs) && elapsedMs >= 0, "elapsedMs must be a nonnegative finite number");
22
+ ensure(typeof decayConstantMs === "number" && Number.isFinite(decayConstantMs) && decayConstantMs > 0, "decayConstantMs must be positive");
23
+ return Math.exp(-elapsedMs / decayConstantMs);
24
+ }
25
+ /** n = 1[h(x_t) ≠ h(x_{t−1})]. Orthogonal to age. */
26
+ export function changeIndicator(previousStateHash, currentStateHash) {
27
+ if (previousStateHash === undefined || currentStateHash === undefined)
28
+ return 0;
29
+ return previousStateHash === currentStateHash ? 0 : 1;
30
+ }
31
+ /**
32
+ * Decide whether an observation may still back a dispatch.
33
+ *
34
+ * Generation mismatches are reported before age: if the page navigated, saying
35
+ * "observation too old" sends the operator to tune a timeout instead of looking
36
+ * at the navigation that actually invalidated the target.
37
+ */
38
+ export function evaluateObservationValidity(input) {
39
+ for (const [label, value] of [
40
+ ["observedAtMs", input.observedAtMs],
41
+ ["dispatchAtMs", input.dispatchAtMs],
42
+ ["maxObservationAgeMs", input.maxObservationAgeMs],
43
+ ]) {
44
+ ensure(typeof value === "number" && Number.isFinite(value) && value >= 0, `${label} must be nonnegative`);
45
+ }
46
+ const ageMs = input.dispatchAtMs - input.observedAtMs;
47
+ ensure(ageMs >= 0, "dispatchAtMs must not precede observedAtMs on a monotonic clock");
48
+ if (input.observedDocumentGeneration !== input.currentDocumentGeneration) {
49
+ return { valid: false, reason: "document-generation-changed" };
50
+ }
51
+ if (input.observedActionGeneration !== input.currentActionGeneration) {
52
+ return { valid: false, reason: "action-generation-changed" };
53
+ }
54
+ if (ageMs > input.maxObservationAgeMs)
55
+ return { valid: false, reason: "max-age-exceeded" };
56
+ return {
57
+ valid: true,
58
+ freshness: timeDecayFreshness(ageMs, input.decayConstantMs),
59
+ changed: changeIndicator(input.previousStateHash, input.currentStateHash),
60
+ ageMs,
61
+ };
62
+ }
63
+ /**
64
+ * Pack observation state under a token budget.
65
+ *
66
+ * Required evidence is pinned first. When it alone exceeds the budget the
67
+ * result is `incomplete-state`, never a quietly truncated view: the caller has
68
+ * to narrow the observation rather than act on a state that lost its evidence.
69
+ *
70
+ * Optional items are then taken by utility density. That is the fixed-rule
71
+ * starting point the design asks for, not an optimal knapsack solution, and it
72
+ * is not claimed to be one.
73
+ */
74
+ export function packState(items, budget) {
75
+ ensure(Array.isArray(items), "items must be an array");
76
+ ensure(Number.isFinite(budget) && budget >= 0, "budget must be nonnegative");
77
+ for (const item of items) {
78
+ ensure(typeof item.id === "string" && item.id.length > 0, "each item needs a non-empty id");
79
+ ensure(Number.isFinite(item.tokenCost) && item.tokenCost >= 0, "tokenCost must be nonnegative");
80
+ ensure(Number.isFinite(item.utility) && item.utility >= 0, "utility must be nonnegative");
81
+ }
82
+ const required = [];
83
+ const optional = [];
84
+ for (const item of items) {
85
+ if (item.required)
86
+ required.push(item);
87
+ else
88
+ optional.push({ item, density: item.tokenCost === 0 ? Infinity : item.utility / item.tokenCost });
89
+ }
90
+ const requiredTokens = required.reduce((sum, item) => sum + item.tokenCost, 0);
91
+ if (requiredTokens > budget) {
92
+ return {
93
+ status: "incomplete-state",
94
+ missingRequired: required.map((item) => item.id),
95
+ requiredTokens,
96
+ budget,
97
+ };
98
+ }
99
+ const selected = required.map((item) => item.id);
100
+ let tokensUsed = requiredTokens;
101
+ let utility = required.reduce((sum, item) => sum + item.utility, 0);
102
+ // Density order, with id as a tiebreak so equal densities pack deterministically.
103
+ const byId = (a, b) => {
104
+ if (a.id < b.id)
105
+ return -1;
106
+ return a.id > b.id ? 1 : 0;
107
+ };
108
+ optional.sort((a, b) => b.density - a.density || byId(a.item, b.item));
109
+ for (const { item } of optional) {
110
+ if (tokensUsed + item.tokenCost > budget)
111
+ continue;
112
+ selected.push(item.id);
113
+ tokensUsed += item.tokenCost;
114
+ utility += item.utility;
115
+ }
116
+ return { status: "packed", selected, tokensUsed, utility };
117
+ }
118
+ //# sourceMappingURL=observation-validity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observation-validity.js","sourceRoot":"","sources":["../../src/metacognition/observation-validity.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Observation validity and state packing (Jev audit algorithm A2, finding F10).\n *\n * F10: the value the existing code calls `freshness` is really a change\n * indicator. Those are different facts — a screen observed one millisecond ago\n * that has not changed scores zero on one and one on the other — so this module\n * reports them separately and never derives one from the other.\n *\n * For anything risky the decay score is not the gate at all. An explicit\n * maximum observation age and equality of the document and action generations\n * decide validity; the decay value is a continuous signal for ranking, not a\n * learned safety probability.\n *\n * \"Check then click\" is not a database transaction: the page keeps running.\n * Re-checking the target narrows the race window, and the postcondition is what\n * actually establishes the result.\n */\n\nimport { ensure } from \"./validation.ts\";\n\n/** f = exp(−Δt/τ). A ranking signal, not a probability of safety. */\nexport function timeDecayFreshness(elapsedMs: number, decayConstantMs: number): number {\n\tensure(\n\t\ttypeof elapsedMs === \"number\" && Number.isFinite(elapsedMs) && elapsedMs >= 0,\n\t\t\"elapsedMs must be a nonnegative finite number\",\n\t);\n\tensure(\n\t\ttypeof decayConstantMs === \"number\" && Number.isFinite(decayConstantMs) && decayConstantMs > 0,\n\t\t\"decayConstantMs must be positive\",\n\t);\n\treturn Math.exp(-elapsedMs / decayConstantMs);\n}\n\n/** n = 1[h(x_t) ≠ h(x_{t−1})]. Orthogonal to age. */\nexport function changeIndicator(previousStateHash: string | undefined, currentStateHash: string | undefined): 0 | 1 {\n\tif (previousStateHash === undefined || currentStateHash === undefined) return 0;\n\treturn previousStateHash === currentStateHash ? 0 : 1;\n}\n\nexport interface ObservationValidityInput {\n\treadonly observedAtMs: number;\n\treadonly dispatchAtMs: number;\n\treadonly decayConstantMs: number;\n\t/** Hard bound for this risk tier; outranks any decay score. */\n\treadonly maxObservationAgeMs: number;\n\t/** Navigation, frame swap, tab swap, permission-session change. */\n\treadonly observedDocumentGeneration: number;\n\treadonly currentDocumentGeneration: number;\n\t/** Chosen element's attachment, role, name, arguments, enabled state. */\n\treadonly observedActionGeneration: number;\n\treadonly currentActionGeneration: number;\n\treadonly previousStateHash?: string;\n\treadonly currentStateHash?: string;\n}\n\nexport type ObservationValidityVerdict =\n\t| { readonly valid: true; readonly freshness: number; readonly changed: 0 | 1; readonly ageMs: number }\n\t| {\n\t\t\treadonly valid: false;\n\t\t\treadonly reason: \"document-generation-changed\" | \"action-generation-changed\" | \"max-age-exceeded\";\n\t };\n\n/**\n * Decide whether an observation may still back a dispatch.\n *\n * Generation mismatches are reported before age: if the page navigated, saying\n * \"observation too old\" sends the operator to tune a timeout instead of looking\n * at the navigation that actually invalidated the target.\n */\nexport function evaluateObservationValidity(input: ObservationValidityInput): ObservationValidityVerdict {\n\tfor (const [label, value] of [\n\t\t[\"observedAtMs\", input.observedAtMs],\n\t\t[\"dispatchAtMs\", input.dispatchAtMs],\n\t\t[\"maxObservationAgeMs\", input.maxObservationAgeMs],\n\t] as const) {\n\t\tensure(typeof value === \"number\" && Number.isFinite(value) && value >= 0, `${label} must be nonnegative`);\n\t}\n\tconst ageMs = input.dispatchAtMs - input.observedAtMs;\n\tensure(ageMs >= 0, \"dispatchAtMs must not precede observedAtMs on a monotonic clock\");\n\n\tif (input.observedDocumentGeneration !== input.currentDocumentGeneration) {\n\t\treturn { valid: false, reason: \"document-generation-changed\" };\n\t}\n\tif (input.observedActionGeneration !== input.currentActionGeneration) {\n\t\treturn { valid: false, reason: \"action-generation-changed\" };\n\t}\n\tif (ageMs > input.maxObservationAgeMs) return { valid: false, reason: \"max-age-exceeded\" };\n\n\treturn {\n\t\tvalid: true,\n\t\tfreshness: timeDecayFreshness(ageMs, input.decayConstantMs),\n\t\tchanged: changeIndicator(input.previousStateHash, input.currentStateHash),\n\t\tageMs,\n\t};\n}\n\nexport interface StateItem {\n\treadonly id: string;\n\treadonly tokenCost: number;\n\treadonly utility: number;\n\treadonly required: boolean;\n}\n\nexport type StatePackingResult =\n\t| {\n\t\t\treadonly status: \"packed\";\n\t\t\treadonly selected: readonly string[];\n\t\t\treadonly tokensUsed: number;\n\t\t\treadonly utility: number;\n\t }\n\t| {\n\t\t\treadonly status: \"incomplete-state\";\n\t\t\treadonly missingRequired: readonly string[];\n\t\t\treadonly requiredTokens: number;\n\t\t\treadonly budget: number;\n\t };\n\n/**\n * Pack observation state under a token budget.\n *\n * Required evidence is pinned first. When it alone exceeds the budget the\n * result is `incomplete-state`, never a quietly truncated view: the caller has\n * to narrow the observation rather than act on a state that lost its evidence.\n *\n * Optional items are then taken by utility density. That is the fixed-rule\n * starting point the design asks for, not an optimal knapsack solution, and it\n * is not claimed to be one.\n */\nexport function packState(items: readonly StateItem[], budget: number): StatePackingResult {\n\tensure(Array.isArray(items), \"items must be an array\");\n\tensure(Number.isFinite(budget) && budget >= 0, \"budget must be nonnegative\");\n\tfor (const item of items) {\n\t\tensure(typeof item.id === \"string\" && item.id.length > 0, \"each item needs a non-empty id\");\n\t\tensure(Number.isFinite(item.tokenCost) && item.tokenCost >= 0, \"tokenCost must be nonnegative\");\n\t\tensure(Number.isFinite(item.utility) && item.utility >= 0, \"utility must be nonnegative\");\n\t}\n\n\tconst required: StateItem[] = [];\n\tconst optional: Array<{ item: StateItem; density: number }> = [];\n\tfor (const item of items) {\n\t\tif (item.required) required.push(item);\n\t\telse optional.push({ item, density: item.tokenCost === 0 ? Infinity : item.utility / item.tokenCost });\n\t}\n\tconst requiredTokens = required.reduce((sum, item) => sum + item.tokenCost, 0);\n\tif (requiredTokens > budget) {\n\t\treturn {\n\t\t\tstatus: \"incomplete-state\",\n\t\t\tmissingRequired: required.map((item) => item.id),\n\t\t\trequiredTokens,\n\t\t\tbudget,\n\t\t};\n\t}\n\n\tconst selected = required.map((item) => item.id);\n\tlet tokensUsed = requiredTokens;\n\tlet utility = required.reduce((sum, item) => sum + item.utility, 0);\n\n\t// Density order, with id as a tiebreak so equal densities pack deterministically.\n\tconst byId = (a: StateItem, b: StateItem): number => {\n\t\tif (a.id < b.id) return -1;\n\t\treturn a.id > b.id ? 1 : 0;\n\t};\n\toptional.sort((a, b) => b.density - a.density || byId(a.item, b.item));\n\n\tfor (const { item } of optional) {\n\t\tif (tokensUsed + item.tokenCost > budget) continue;\n\t\tselected.push(item.id);\n\t\ttokensUsed += item.tokenCost;\n\t\tutility += item.utility;\n\t}\n\n\treturn { status: \"packed\", selected, tokensUsed, utility };\n}\n"]}