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,57 @@
1
+ import { instantiateObligations } from "./obligations.js";
2
+ import { selectAction } from "./policy.js";
3
+ import { finishState, validateMetaState } from "./state.js";
4
+ import { integer } from "./validation.js";
5
+ import { evaluateVerifier } from "./verifier.js";
6
+ /**
7
+ * One checkpoint evaluation. Refreshes obligations from observed atoms when
8
+ * provided, resolves registered predictions against fresh observations when
9
+ * provided, evaluates verifier mutants when provided, then selects the next
10
+ * action under the §14 priority table.
11
+ */
12
+ export function checkpoint(input) {
13
+ integer(input.nowMs, "nowMs");
14
+ validateMetaState(input.state);
15
+ let state = input.state;
16
+ let newObligations = 0;
17
+ if (input.atoms && input.rules) {
18
+ const report = instantiateObligations(input.atoms, input.rules, input.nowMs);
19
+ const merged = [...state.obligations, ...report.required, ...report.candidates];
20
+ newObligations = report.required.length + report.candidates.length;
21
+ state = { ...state, obligations: merged };
22
+ }
23
+ let mismatches = 0;
24
+ for (const p of state.predictions) {
25
+ if (p.status === "resolved" && p.mismatch !== undefined && p.mismatch !== "none")
26
+ mismatches += 1;
27
+ }
28
+ const verifierEvaluations = [...state.verifier.evaluations];
29
+ if (input.mutants) {
30
+ for (const obligation of state.obligations) {
31
+ const scoped = input.mutants.filter((m) => m.obligationId === obligation.id);
32
+ if (scoped.length === 0)
33
+ continue;
34
+ verifierEvaluations.push(evaluateVerifier(obligation.id, input.mutants, state.verifier.runnerHealth === "healthy"));
35
+ }
36
+ state = { ...state, verifier: { ...state.verifier, evaluations: verifierEvaluations } };
37
+ }
38
+ const action = selectAction(state, input.constraints, {
39
+ receipt: input.receipt ?? null,
40
+ maxRepetitions: input.options?.maxRepetitions,
41
+ switchCost: input.options?.switchCost,
42
+ estimatedSwitchGain: input.options?.estimatedSwitchGain,
43
+ voiCandidates: input.options?.voiCandidates,
44
+ progress: input.options?.progress,
45
+ });
46
+ const finish = finishState(state, input.receipt ?? null);
47
+ return {
48
+ state: { ...state, checkpointCount: state.checkpointCount + 1 },
49
+ action,
50
+ finish,
51
+ newObligations,
52
+ newPredictions: 0,
53
+ mismatches,
54
+ verifierEvaluations,
55
+ };
56
+ }
57
+ //# sourceMappingURL=checkpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/metacognition/checkpoint.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * §9.4 checkpoint ordering: refresh obligations from host observations,\n * evaluate knowledge gaps, classify prediction mismatches, evaluate verifier\n * blind spots and runner health, then select one bounded action.\n *\n * The host calls this at a safe decision boundary — never mid-stream, and\n * never as a path for model reasoning to remove a `required` obligation.\n */\nimport type { ChangeAtom, ObligationRule } from \"./obligations.ts\";\nimport { instantiateObligations } from \"./obligations.ts\";\nimport { type ActionConstraints, type MetaAction, type MetaActionKind, selectAction } from \"./policy.ts\";\nimport type { MetaState } from \"./state.ts\";\nimport { type FinishState, finishState, validateMetaState } from \"./state.ts\";\nimport { integer } from \"./validation.ts\";\nimport { evaluateVerifier, type MutantRecord, type VerifierEvaluation } from \"./verifier.ts\";\n\nexport interface CheckpointInput {\n\treadonly state: MetaState;\n\treadonly atoms?: readonly ChangeAtom[];\n\treadonly rules?: readonly ObligationRule[];\n\treadonly nowMs: number;\n\treadonly constraints: ActionConstraints;\n\treadonly mutants?: readonly MutantRecord[];\n\treadonly receipt?: { receiptId: string; candidateHash: string; scope: string } | null;\n\treadonly options?: {\n\t\treadonly maxRepetitions?: number;\n\t\treadonly switchCost?: number;\n\t\treadonly estimatedSwitchGain?: number;\n\t\treadonly voiCandidates?: readonly { kind: MetaActionKind; voi: number }[];\n\t\treadonly progress?: {\n\t\t\treadonly goalScope: string;\n\t\t\treadonly candidateFamily: string;\n\t\t\treadonly errorClass: string;\n\t\t\treadonly approach: string;\n\t\t\treadonly checkMethod: string;\n\t\t\treadonly sourceFamily: string;\n\t\t};\n\t};\n}\nexport interface CheckpointResult {\n\treadonly state: MetaState;\n\treadonly action: MetaAction;\n\treadonly finish: FinishState;\n\treadonly newObligations: number;\n\treadonly newPredictions: number;\n\treadonly mismatches: number;\n\treadonly verifierEvaluations: readonly VerifierEvaluation[];\n}\n\n/**\n * One checkpoint evaluation. Refreshes obligations from observed atoms when\n * provided, resolves registered predictions against fresh observations when\n * provided, evaluates verifier mutants when provided, then selects the next\n * action under the §14 priority table.\n */\nexport function checkpoint(input: CheckpointInput): CheckpointResult {\n\tinteger(input.nowMs, \"nowMs\");\n\tvalidateMetaState(input.state);\n\tlet state = input.state;\n\tlet newObligations = 0;\n\tif (input.atoms && input.rules) {\n\t\tconst report = instantiateObligations(input.atoms, input.rules, input.nowMs);\n\t\tconst merged = [...state.obligations, ...report.required, ...report.candidates];\n\t\tnewObligations = report.required.length + report.candidates.length;\n\t\tstate = { ...state, obligations: merged };\n\t}\n\tlet mismatches = 0;\n\tfor (const p of state.predictions) {\n\t\tif (p.status === \"resolved\" && p.mismatch !== undefined && p.mismatch !== \"none\") mismatches += 1;\n\t}\n\tconst verifierEvaluations: VerifierEvaluation[] = [...state.verifier.evaluations];\n\tif (input.mutants) {\n\t\tfor (const obligation of state.obligations) {\n\t\t\tconst scoped = input.mutants.filter((m) => m.obligationId === obligation.id);\n\t\t\tif (scoped.length === 0) continue;\n\t\t\tverifierEvaluations.push(\n\t\t\t\tevaluateVerifier(obligation.id, input.mutants, state.verifier.runnerHealth === \"healthy\"),\n\t\t\t);\n\t\t}\n\t\tstate = { ...state, verifier: { ...state.verifier, evaluations: verifierEvaluations } };\n\t}\n\tconst action = selectAction(state, input.constraints, {\n\t\treceipt: input.receipt ?? null,\n\t\tmaxRepetitions: input.options?.maxRepetitions,\n\t\tswitchCost: input.options?.switchCost,\n\t\testimatedSwitchGain: input.options?.estimatedSwitchGain,\n\t\tvoiCandidates: input.options?.voiCandidates,\n\t\tprogress: input.options?.progress,\n\t});\n\tconst finish = finishState(state, input.receipt ?? null);\n\treturn {\n\t\tstate: { ...state, checkpointCount: state.checkpointCount + 1 },\n\t\taction,\n\t\tfinish,\n\t\tnewObligations,\n\t\tnewPredictions: 0,\n\t\tmismatches,\n\t\tverifierEvaluations,\n\t};\n}\n"]}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Fixed-origin Context7 GET adapter with explicit egress approval.
3
+ *
4
+ * Ported from docs/OMK_skill_knowledge_control_2026-09-19.zip
5
+ * (src/context7.ts). Every attempted HTTP request consumes a shared
6
+ * AcquisitionPool permit; there is no retry, redirect-following, or
7
+ * auto-selection of the first result. Returned `rules` fields are data, never
8
+ * promoted to instructions.
9
+ */
10
+ import type { AcquisitionPool, AcquisitionResult } from "./retrieval.ts";
11
+ export interface Context7Options {
12
+ readonly apiKey: string;
13
+ readonly enabled: boolean;
14
+ readonly approvedLibraryNames: readonly string[];
15
+ readonly approvedLibraryIds: readonly string[];
16
+ readonly approvedQueries: readonly string[];
17
+ readonly pool: AcquisitionPool;
18
+ readonly maxResponseBytes?: number;
19
+ readonly fetchImpl?: typeof fetch;
20
+ }
21
+ export interface LibraryCandidate {
22
+ readonly id: string;
23
+ readonly title: string;
24
+ readonly versions: readonly string[];
25
+ }
26
+ export interface DocumentationCandidate {
27
+ readonly uri: string;
28
+ readonly body: string;
29
+ readonly requestedLibraryId: string;
30
+ readonly trust: "candidate-only";
31
+ }
32
+ /** Fixed-origin GET adapter. In OMK prefer routing equivalent requests through admitted MCP tools. */
33
+ export declare class Context7Client {
34
+ private readonly key;
35
+ private readonly enabled;
36
+ private readonly names;
37
+ private readonly ids;
38
+ private readonly queries;
39
+ private readonly pool;
40
+ private readonly fetcher;
41
+ private readonly limit;
42
+ constructor(options: Context7Options);
43
+ resolveLibraries(name: string, query: string, signal?: AbortSignal): Promise<AcquisitionResult<readonly LibraryCandidate[]>>;
44
+ getDocumentation(id: string, query: string, signal?: AbortSignal): Promise<AcquisitionResult<readonly DocumentationCandidate[]>>;
45
+ private authorize;
46
+ private get;
47
+ }
48
+ //# sourceMappingURL=context7.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context7.d.ts","sourceRoot":"","sources":["../../src/metacognition/context7.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGzE,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAClC;AACD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AACD,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;CACjC;AACD,sGAAsG;AACtG,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,YAAY,OAAO,EAAE,eAAe,EAanC;IACD,gBAAgB,CACf,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,iBAAiB,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAAC,CAkBzD;IACD,gBAAgB,CACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,iBAAiB,CAAC,SAAS,sBAAsB,EAAE,CAAC,CAAC,CAqC/D;IACD,OAAO,CAAC,SAAS;YAKH,GAAG;CAiDjB","sourcesContent":["/**\n * Fixed-origin Context7 GET adapter with explicit egress approval.\n *\n * Ported from docs/OMK_skill_knowledge_control_2026-09-19.zip\n * (src/context7.ts). Every attempted HTTP request consumes a shared\n * AcquisitionPool permit; there is no retry, redirect-following, or\n * auto-selection of the first result. Returned `rules` fields are data, never\n * promoted to instructions.\n */\nimport type { AcquisitionPool, AcquisitionResult } from \"./retrieval.ts\";\nimport { ensure, integer, text } from \"./validation.ts\";\n\nexport interface Context7Options {\n\treadonly apiKey: string;\n\treadonly enabled: boolean;\n\treadonly approvedLibraryNames: readonly string[];\n\treadonly approvedLibraryIds: readonly string[];\n\treadonly approvedQueries: readonly string[];\n\treadonly pool: AcquisitionPool;\n\treadonly maxResponseBytes?: number;\n\treadonly fetchImpl?: typeof fetch;\n}\nexport interface LibraryCandidate {\n\treadonly id: string;\n\treadonly title: string;\n\treadonly versions: readonly string[];\n}\nexport interface DocumentationCandidate {\n\treadonly uri: string;\n\treadonly body: string;\n\treadonly requestedLibraryId: string;\n\treadonly trust: \"candidate-only\";\n}\n/** Fixed-origin GET adapter. In OMK prefer routing equivalent requests through admitted MCP tools. */\nexport class Context7Client {\n\tprivate readonly key: string;\n\tprivate readonly enabled: boolean;\n\tprivate readonly names: ReadonlySet<string>;\n\tprivate readonly ids: ReadonlySet<string>;\n\tprivate readonly queries: ReadonlySet<string>;\n\tprivate readonly pool: AcquisitionPool;\n\tprivate readonly fetcher: typeof fetch;\n\tprivate readonly limit: number;\n\tconstructor(options: Context7Options) {\n\t\ttext(options.apiKey, \"apiKey\", 4096);\n\t\tensure(typeof options.enabled === \"boolean\", \"enabled must be boolean\");\n\t\tthis.limit = options.maxResponseBytes ?? 200_000;\n\t\tinteger(this.limit, \"maxResponseBytes\", 2_000_000);\n\t\tensure(this.limit > 0, \"response limit must be positive\");\n\t\tthis.key = options.apiKey;\n\t\tthis.enabled = options.enabled;\n\t\tthis.names = new Set(options.approvedLibraryNames);\n\t\tthis.ids = new Set(options.approvedLibraryIds);\n\t\tthis.queries = new Set(options.approvedQueries);\n\t\tthis.pool = options.pool;\n\t\tthis.fetcher = options.fetchImpl ?? fetch;\n\t}\n\tresolveLibraries(\n\t\tname: string,\n\t\tquery: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<AcquisitionResult<readonly LibraryCandidate[]>> {\n\t\tthis.authorize(query);\n\t\ttext(name, \"libraryName\", 500);\n\t\tensure(this.names.has(name), \"unapproved library name\");\n\t\treturn this.pool.run(async (abort) => {\n\t\t\tconst payload = await this.get(\"/api/v2/libs/search\", { libraryName: name, query }, abort);\n\t\t\tconst object = record(payload);\n\t\t\tensure(Array.isArray(object.results), \"invalid search response\");\n\t\t\tensure(object.results.length <= 256, \"too many library candidates\");\n\t\t\treturn object.results.map((raw): LibraryCandidate => {\n\t\t\t\tconst candidate = record(raw);\n\t\t\t\tconst id = string(candidate.id),\n\t\t\t\t\ttitle = string(candidate.title);\n\t\t\t\tconst versions = candidate.versions ?? [];\n\t\t\t\tensure(Array.isArray(versions) && versions.every((v) => typeof v === \"string\"), \"invalid versions\");\n\t\t\t\treturn { id, title, versions: versions as string[] };\n\t\t\t});\n\t\t}, signal);\n\t}\n\tgetDocumentation(\n\t\tid: string,\n\t\tquery: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<AcquisitionResult<readonly DocumentationCandidate[]>> {\n\t\tthis.authorize(query);\n\t\ttext(id, \"libraryId\", 500);\n\t\tensure(this.ids.has(id), \"unapproved library id: validate identity/version before retrieval\");\n\t\treturn this.pool.run(async (abort) => {\n\t\t\tconst object = record(await this.get(\"/api/v2/context\", { libraryId: id, query, type: \"json\" }, abort));\n\t\t\tconst info = object.infoSnippets,\n\t\t\t\tcode = object.codeSnippets;\n\t\t\tensure(Array.isArray(info) && Array.isArray(code), \"invalid documentation response\");\n\t\t\tensure(info.length + code.length <= 256, \"too many snippets\");\n\t\t\tconst result: DocumentationCandidate[] = [];\n\t\t\tconst add = (uri: unknown, body: string): void => {\n\t\t\t\tif (typeof uri !== \"string\") return;\n\t\t\t\tlet parsed: URL;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = new URL(uri);\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Metadata only, never followed. Reject executable/non-web references.\n\t\t\t\tif (parsed.protocol !== \"https:\" || parsed.username || parsed.password) return;\n\t\t\t\tresult.push({ uri: parsed.href, body, requestedLibraryId: id, trust: \"candidate-only\" });\n\t\t\t};\n\t\t\tfor (const raw of info) {\n\t\t\t\tconst v = record(raw);\n\t\t\t\tadd(v.pageId, string(v.content));\n\t\t\t}\n\t\t\tfor (const raw of code) {\n\t\t\t\tconst v = record(raw);\n\t\t\t\tconst list = v.codeList;\n\t\t\t\tensure(Array.isArray(list), \"invalid codeList\");\n\t\t\t\tconst body = list.map((item) => string(record(item).code)).join(\"\\n\\n\");\n\t\t\t\tadd(v.codeId, body);\n\t\t\t}\n\t\t\t// The response's optional `rules` field is deliberately not promoted to instructions.\n\t\t\treturn result;\n\t\t}, signal);\n\t}\n\tprivate authorize(query: string): void {\n\t\tensure(this.enabled, \"remote acquisition disabled\");\n\t\ttext(query, \"public query\", 500);\n\t\tensure(this.queries.has(query), \"query has not been approved for egress\");\n\t}\n\tprivate async get(path: string, parameters: Record<string, string>, signal: AbortSignal): Promise<unknown> {\n\t\tconst url = new URL(path, \"https://context7.com\");\n\t\tfor (const [key, value] of Object.entries(parameters)) url.searchParams.set(key, value);\n\t\tconst response = await this.fetcher(url, {\n\t\t\tmethod: \"GET\",\n\t\t\tredirect: \"error\",\n\t\t\tsignal,\n\t\t\theaders: { Authorization: `Bearer ${this.key}`, Accept: \"application/json\" },\n\t\t});\n\t\t// No retry here: every attempted HTTP request must acquire a fresh shared budget slot.\n\t\tif (response.status !== 200) {\n\t\t\tif (response.body) await response.body.cancel();\n\t\t\tthrow new Error(`context7-http-${response.status}`);\n\t\t}\n\t\tconst contentType = response.headers.get(\"content-type\") ?? \"\";\n\t\tif (!contentType.includes(\"application/json\")) {\n\t\t\tif (response.body) await response.body.cancel();\n\t\t\tthrow new Error(\"unexpected response content type\");\n\t\t}\n\t\tensure(response.body !== null, \"missing response body\");\n\t\tconst reader = response.body.getReader();\n\t\tlet bytes = 0;\n\t\tconst chunks: Uint8Array[] = [];\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst next = await reader.read();\n\t\t\t\tif (next.done) break;\n\t\t\t\tbytes += next.value.byteLength;\n\t\t\t\tensure(bytes <= this.limit, \"response byte budget exceeded\");\n\t\t\t\tchunks.push(next.value);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait reader.cancel();\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treader.releaseLock();\n\t\t}\n\t\tconst joined = new Uint8Array(bytes);\n\t\tlet at = 0;\n\t\tfor (const chunk of chunks) {\n\t\t\tjoined.set(chunk, at);\n\t\t\tat += chunk.byteLength;\n\t\t}\n\t\ttry {\n\t\t\treturn JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(joined)) as unknown;\n\t\t} catch {\n\t\t\tthrow new Error(\"malformed context7 response body\");\n\t\t}\n\t}\n}\nfunction record(value: unknown): Record<string, unknown> {\n\tensure(value !== null && typeof value === \"object\" && !Array.isArray(value), \"expected response object\");\n\treturn value as Record<string, unknown>;\n}\nfunction string(value: unknown): string {\n\tensure(typeof value === \"string\", \"expected response string\");\n\treturn value;\n}\n"]}
@@ -0,0 +1,154 @@
1
+ import { ensure, integer, text } from "./validation.js";
2
+ /** Fixed-origin GET adapter. In OMK prefer routing equivalent requests through admitted MCP tools. */
3
+ export class Context7Client {
4
+ key;
5
+ enabled;
6
+ names;
7
+ ids;
8
+ queries;
9
+ pool;
10
+ fetcher;
11
+ limit;
12
+ constructor(options) {
13
+ text(options.apiKey, "apiKey", 4096);
14
+ ensure(typeof options.enabled === "boolean", "enabled must be boolean");
15
+ this.limit = options.maxResponseBytes ?? 200_000;
16
+ integer(this.limit, "maxResponseBytes", 2_000_000);
17
+ ensure(this.limit > 0, "response limit must be positive");
18
+ this.key = options.apiKey;
19
+ this.enabled = options.enabled;
20
+ this.names = new Set(options.approvedLibraryNames);
21
+ this.ids = new Set(options.approvedLibraryIds);
22
+ this.queries = new Set(options.approvedQueries);
23
+ this.pool = options.pool;
24
+ this.fetcher = options.fetchImpl ?? fetch;
25
+ }
26
+ resolveLibraries(name, query, signal) {
27
+ this.authorize(query);
28
+ text(name, "libraryName", 500);
29
+ ensure(this.names.has(name), "unapproved library name");
30
+ return this.pool.run(async (abort) => {
31
+ const payload = await this.get("/api/v2/libs/search", { libraryName: name, query }, abort);
32
+ const object = record(payload);
33
+ ensure(Array.isArray(object.results), "invalid search response");
34
+ ensure(object.results.length <= 256, "too many library candidates");
35
+ return object.results.map((raw) => {
36
+ const candidate = record(raw);
37
+ const id = string(candidate.id), title = string(candidate.title);
38
+ const versions = candidate.versions ?? [];
39
+ ensure(Array.isArray(versions) && versions.every((v) => typeof v === "string"), "invalid versions");
40
+ return { id, title, versions: versions };
41
+ });
42
+ }, signal);
43
+ }
44
+ getDocumentation(id, query, signal) {
45
+ this.authorize(query);
46
+ text(id, "libraryId", 500);
47
+ ensure(this.ids.has(id), "unapproved library id: validate identity/version before retrieval");
48
+ return this.pool.run(async (abort) => {
49
+ const object = record(await this.get("/api/v2/context", { libraryId: id, query, type: "json" }, abort));
50
+ const info = object.infoSnippets, code = object.codeSnippets;
51
+ ensure(Array.isArray(info) && Array.isArray(code), "invalid documentation response");
52
+ ensure(info.length + code.length <= 256, "too many snippets");
53
+ const result = [];
54
+ const add = (uri, body) => {
55
+ if (typeof uri !== "string")
56
+ return;
57
+ let parsed;
58
+ try {
59
+ parsed = new URL(uri);
60
+ }
61
+ catch {
62
+ return;
63
+ }
64
+ // Metadata only, never followed. Reject executable/non-web references.
65
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password)
66
+ return;
67
+ result.push({ uri: parsed.href, body, requestedLibraryId: id, trust: "candidate-only" });
68
+ };
69
+ for (const raw of info) {
70
+ const v = record(raw);
71
+ add(v.pageId, string(v.content));
72
+ }
73
+ for (const raw of code) {
74
+ const v = record(raw);
75
+ const list = v.codeList;
76
+ ensure(Array.isArray(list), "invalid codeList");
77
+ const body = list.map((item) => string(record(item).code)).join("\n\n");
78
+ add(v.codeId, body);
79
+ }
80
+ // The response's optional `rules` field is deliberately not promoted to instructions.
81
+ return result;
82
+ }, signal);
83
+ }
84
+ authorize(query) {
85
+ ensure(this.enabled, "remote acquisition disabled");
86
+ text(query, "public query", 500);
87
+ ensure(this.queries.has(query), "query has not been approved for egress");
88
+ }
89
+ async get(path, parameters, signal) {
90
+ const url = new URL(path, "https://context7.com");
91
+ for (const [key, value] of Object.entries(parameters))
92
+ url.searchParams.set(key, value);
93
+ const response = await this.fetcher(url, {
94
+ method: "GET",
95
+ redirect: "error",
96
+ signal,
97
+ headers: { Authorization: `Bearer ${this.key}`, Accept: "application/json" },
98
+ });
99
+ // No retry here: every attempted HTTP request must acquire a fresh shared budget slot.
100
+ if (response.status !== 200) {
101
+ if (response.body)
102
+ await response.body.cancel();
103
+ throw new Error(`context7-http-${response.status}`);
104
+ }
105
+ const contentType = response.headers.get("content-type") ?? "";
106
+ if (!contentType.includes("application/json")) {
107
+ if (response.body)
108
+ await response.body.cancel();
109
+ throw new Error("unexpected response content type");
110
+ }
111
+ ensure(response.body !== null, "missing response body");
112
+ const reader = response.body.getReader();
113
+ let bytes = 0;
114
+ const chunks = [];
115
+ try {
116
+ while (true) {
117
+ const next = await reader.read();
118
+ if (next.done)
119
+ break;
120
+ bytes += next.value.byteLength;
121
+ ensure(bytes <= this.limit, "response byte budget exceeded");
122
+ chunks.push(next.value);
123
+ }
124
+ }
125
+ catch (error) {
126
+ await reader.cancel();
127
+ throw error;
128
+ }
129
+ finally {
130
+ reader.releaseLock();
131
+ }
132
+ const joined = new Uint8Array(bytes);
133
+ let at = 0;
134
+ for (const chunk of chunks) {
135
+ joined.set(chunk, at);
136
+ at += chunk.byteLength;
137
+ }
138
+ try {
139
+ return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(joined));
140
+ }
141
+ catch {
142
+ throw new Error("malformed context7 response body");
143
+ }
144
+ }
145
+ }
146
+ function record(value) {
147
+ ensure(value !== null && typeof value === "object" && !Array.isArray(value), "expected response object");
148
+ return value;
149
+ }
150
+ function string(value) {
151
+ ensure(typeof value === "string", "expected response string");
152
+ return value;
153
+ }
154
+ //# sourceMappingURL=context7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context7.js","sourceRoot":"","sources":["../../src/metacognition/context7.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Fixed-origin Context7 GET adapter with explicit egress approval.\n *\n * Ported from docs/OMK_skill_knowledge_control_2026-09-19.zip\n * (src/context7.ts). Every attempted HTTP request consumes a shared\n * AcquisitionPool permit; there is no retry, redirect-following, or\n * auto-selection of the first result. Returned `rules` fields are data, never\n * promoted to instructions.\n */\nimport type { AcquisitionPool, AcquisitionResult } from \"./retrieval.ts\";\nimport { ensure, integer, text } from \"./validation.ts\";\n\nexport interface Context7Options {\n\treadonly apiKey: string;\n\treadonly enabled: boolean;\n\treadonly approvedLibraryNames: readonly string[];\n\treadonly approvedLibraryIds: readonly string[];\n\treadonly approvedQueries: readonly string[];\n\treadonly pool: AcquisitionPool;\n\treadonly maxResponseBytes?: number;\n\treadonly fetchImpl?: typeof fetch;\n}\nexport interface LibraryCandidate {\n\treadonly id: string;\n\treadonly title: string;\n\treadonly versions: readonly string[];\n}\nexport interface DocumentationCandidate {\n\treadonly uri: string;\n\treadonly body: string;\n\treadonly requestedLibraryId: string;\n\treadonly trust: \"candidate-only\";\n}\n/** Fixed-origin GET adapter. In OMK prefer routing equivalent requests through admitted MCP tools. */\nexport class Context7Client {\n\tprivate readonly key: string;\n\tprivate readonly enabled: boolean;\n\tprivate readonly names: ReadonlySet<string>;\n\tprivate readonly ids: ReadonlySet<string>;\n\tprivate readonly queries: ReadonlySet<string>;\n\tprivate readonly pool: AcquisitionPool;\n\tprivate readonly fetcher: typeof fetch;\n\tprivate readonly limit: number;\n\tconstructor(options: Context7Options) {\n\t\ttext(options.apiKey, \"apiKey\", 4096);\n\t\tensure(typeof options.enabled === \"boolean\", \"enabled must be boolean\");\n\t\tthis.limit = options.maxResponseBytes ?? 200_000;\n\t\tinteger(this.limit, \"maxResponseBytes\", 2_000_000);\n\t\tensure(this.limit > 0, \"response limit must be positive\");\n\t\tthis.key = options.apiKey;\n\t\tthis.enabled = options.enabled;\n\t\tthis.names = new Set(options.approvedLibraryNames);\n\t\tthis.ids = new Set(options.approvedLibraryIds);\n\t\tthis.queries = new Set(options.approvedQueries);\n\t\tthis.pool = options.pool;\n\t\tthis.fetcher = options.fetchImpl ?? fetch;\n\t}\n\tresolveLibraries(\n\t\tname: string,\n\t\tquery: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<AcquisitionResult<readonly LibraryCandidate[]>> {\n\t\tthis.authorize(query);\n\t\ttext(name, \"libraryName\", 500);\n\t\tensure(this.names.has(name), \"unapproved library name\");\n\t\treturn this.pool.run(async (abort) => {\n\t\t\tconst payload = await this.get(\"/api/v2/libs/search\", { libraryName: name, query }, abort);\n\t\t\tconst object = record(payload);\n\t\t\tensure(Array.isArray(object.results), \"invalid search response\");\n\t\t\tensure(object.results.length <= 256, \"too many library candidates\");\n\t\t\treturn object.results.map((raw): LibraryCandidate => {\n\t\t\t\tconst candidate = record(raw);\n\t\t\t\tconst id = string(candidate.id),\n\t\t\t\t\ttitle = string(candidate.title);\n\t\t\t\tconst versions = candidate.versions ?? [];\n\t\t\t\tensure(Array.isArray(versions) && versions.every((v) => typeof v === \"string\"), \"invalid versions\");\n\t\t\t\treturn { id, title, versions: versions as string[] };\n\t\t\t});\n\t\t}, signal);\n\t}\n\tgetDocumentation(\n\t\tid: string,\n\t\tquery: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<AcquisitionResult<readonly DocumentationCandidate[]>> {\n\t\tthis.authorize(query);\n\t\ttext(id, \"libraryId\", 500);\n\t\tensure(this.ids.has(id), \"unapproved library id: validate identity/version before retrieval\");\n\t\treturn this.pool.run(async (abort) => {\n\t\t\tconst object = record(await this.get(\"/api/v2/context\", { libraryId: id, query, type: \"json\" }, abort));\n\t\t\tconst info = object.infoSnippets,\n\t\t\t\tcode = object.codeSnippets;\n\t\t\tensure(Array.isArray(info) && Array.isArray(code), \"invalid documentation response\");\n\t\t\tensure(info.length + code.length <= 256, \"too many snippets\");\n\t\t\tconst result: DocumentationCandidate[] = [];\n\t\t\tconst add = (uri: unknown, body: string): void => {\n\t\t\t\tif (typeof uri !== \"string\") return;\n\t\t\t\tlet parsed: URL;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = new URL(uri);\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Metadata only, never followed. Reject executable/non-web references.\n\t\t\t\tif (parsed.protocol !== \"https:\" || parsed.username || parsed.password) return;\n\t\t\t\tresult.push({ uri: parsed.href, body, requestedLibraryId: id, trust: \"candidate-only\" });\n\t\t\t};\n\t\t\tfor (const raw of info) {\n\t\t\t\tconst v = record(raw);\n\t\t\t\tadd(v.pageId, string(v.content));\n\t\t\t}\n\t\t\tfor (const raw of code) {\n\t\t\t\tconst v = record(raw);\n\t\t\t\tconst list = v.codeList;\n\t\t\t\tensure(Array.isArray(list), \"invalid codeList\");\n\t\t\t\tconst body = list.map((item) => string(record(item).code)).join(\"\\n\\n\");\n\t\t\t\tadd(v.codeId, body);\n\t\t\t}\n\t\t\t// The response's optional `rules` field is deliberately not promoted to instructions.\n\t\t\treturn result;\n\t\t}, signal);\n\t}\n\tprivate authorize(query: string): void {\n\t\tensure(this.enabled, \"remote acquisition disabled\");\n\t\ttext(query, \"public query\", 500);\n\t\tensure(this.queries.has(query), \"query has not been approved for egress\");\n\t}\n\tprivate async get(path: string, parameters: Record<string, string>, signal: AbortSignal): Promise<unknown> {\n\t\tconst url = new URL(path, \"https://context7.com\");\n\t\tfor (const [key, value] of Object.entries(parameters)) url.searchParams.set(key, value);\n\t\tconst response = await this.fetcher(url, {\n\t\t\tmethod: \"GET\",\n\t\t\tredirect: \"error\",\n\t\t\tsignal,\n\t\t\theaders: { Authorization: `Bearer ${this.key}`, Accept: \"application/json\" },\n\t\t});\n\t\t// No retry here: every attempted HTTP request must acquire a fresh shared budget slot.\n\t\tif (response.status !== 200) {\n\t\t\tif (response.body) await response.body.cancel();\n\t\t\tthrow new Error(`context7-http-${response.status}`);\n\t\t}\n\t\tconst contentType = response.headers.get(\"content-type\") ?? \"\";\n\t\tif (!contentType.includes(\"application/json\")) {\n\t\t\tif (response.body) await response.body.cancel();\n\t\t\tthrow new Error(\"unexpected response content type\");\n\t\t}\n\t\tensure(response.body !== null, \"missing response body\");\n\t\tconst reader = response.body.getReader();\n\t\tlet bytes = 0;\n\t\tconst chunks: Uint8Array[] = [];\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tconst next = await reader.read();\n\t\t\t\tif (next.done) break;\n\t\t\t\tbytes += next.value.byteLength;\n\t\t\t\tensure(bytes <= this.limit, \"response byte budget exceeded\");\n\t\t\t\tchunks.push(next.value);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait reader.cancel();\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treader.releaseLock();\n\t\t}\n\t\tconst joined = new Uint8Array(bytes);\n\t\tlet at = 0;\n\t\tfor (const chunk of chunks) {\n\t\t\tjoined.set(chunk, at);\n\t\t\tat += chunk.byteLength;\n\t\t}\n\t\ttry {\n\t\t\treturn JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(joined)) as unknown;\n\t\t} catch {\n\t\t\tthrow new Error(\"malformed context7 response body\");\n\t\t}\n\t}\n}\nfunction record(value: unknown): Record<string, unknown> {\n\tensure(value !== null && typeof value === \"object\" && !Array.isArray(value), \"expected response object\");\n\treturn value as Record<string, unknown>;\n}\nfunction string(value: unknown): string {\n\tensure(typeof value === \"string\", \"expected response string\");\n\treturn value;\n}\n"]}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Minimum expected loss over a finite set of terminal decisions.
3
+ * losses[d][h] is the loss of decision d when hypothesis h is true.
4
+ */
5
+ export declare function bayesRisk(prior: readonly number[], losses: readonly (readonly number[])[]): number;
6
+ export interface ExperimentBranch {
7
+ readonly outcome: number;
8
+ readonly probability: number;
9
+ readonly posterior: readonly number[];
10
+ readonly risk: number;
11
+ }
12
+ export interface ExperimentValue {
13
+ readonly before: number;
14
+ readonly expectedAfter: number;
15
+ readonly grossValue: number;
16
+ readonly cost: number;
17
+ readonly netValue: number;
18
+ readonly branches: readonly ExperimentBranch[];
19
+ }
20
+ /**
21
+ * One-step value of information: Bayes risk before minus expected Bayes risk
22
+ * after observing the experiment outcome, minus the experiment cost.
23
+ * likelihoodByHypothesis[h][o] = P(outcome o | hypothesis h).
24
+ * Zero-probability outcomes are skipped; the caller must treat an actually
25
+ * observed impossible outcome as a model mismatch, never renormalize it away.
26
+ */
27
+ export declare function experimentValue(prior: readonly number[], losses: readonly (readonly number[])[], likelihoodByHypothesis: readonly (readonly number[])[], cost: number): ExperimentValue;
28
+ /** Brier score for one binary event. */
29
+ export declare function brier(predicted: number, outcome: 0 | 1): number;
30
+ /** Negative log-likelihood surprise for one binary event (epsilon-clamped). */
31
+ export declare function surprise(predicted: number, outcome: 0 | 1, epsilon?: number): number;
32
+ /**
33
+ * Beta posterior mean for an independent binary task outcome under a fixed
34
+ * policy in a homogeneous condition bucket. The prior (alpha, beta) must be
35
+ * declared by the host; this is not a learned-calibration claim.
36
+ */
37
+ export declare function betaPosteriorMean(alpha: number, beta: number, successes: number, failures: number): number;
38
+ /**
39
+ * CUSUM-style drift accumulator over per-observation losses in one condition
40
+ * bucket. Returns the new accumulator value; the caller compares it against
41
+ * a host-declared threshold h_g. Not a guaranteed false-alarm rate.
42
+ */
43
+ export declare function driftStatistic(previous: number, loss: number, referenceMean: number, slack: number): number;
44
+ //# sourceMappingURL=decision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../src/metacognition/decision.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,CAclG;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC9B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,EACtC,sBAAsB,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,EACtD,IAAI,EAAE,MAAM,GACV,eAAe,CA8BjB;AAED,wCAAwC;AACxC,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAI/D;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,SAAQ,GAAG,MAAM,CAMnF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO1G;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAM3G","sourcesContent":["/**\n * Finite decision-model arithmetic for metacognitive control.\n *\n * TypeScript port of docs/OMK_meta_algorithm_checks_2026-09-19.zip\n * (check_examples.py) — the numerical checks referenced by\n * OMK_metacognitive_control_algorithms_2026-09-19.md §5.3, §6.2.\n *\n * These are illustrative finite-model computations, NOT measured OMK risk\n * estimates. Callers must supply real, defensible probabilities; this module\n * only guarantees the arithmetic is correct and rejects malformed inputs.\n */\nimport { ensure, finite, probability, probabilityVector } from \"./validation.ts\";\n\n/**\n * Minimum expected loss over a finite set of terminal decisions.\n * losses[d][h] is the loss of decision d when hypothesis h is true.\n */\nexport function bayesRisk(prior: readonly number[], losses: readonly (readonly number[])[]): number {\n\tprobabilityVector(prior, \"prior\");\n\tensure(losses.length > 0, \"at least one terminal decision is required\");\n\tlet best = Number.POSITIVE_INFINITY;\n\tfor (const row of losses) {\n\t\tensure(row.length === prior.length, \"loss row must match hypotheses\");\n\t\tlet risk = 0;\n\t\tfor (let h = 0; h < prior.length; h++) {\n\t\t\tfinite(row[h]!, \"loss\");\n\t\t\trisk += prior[h]! * row[h]!;\n\t\t}\n\t\tif (risk < best) best = risk;\n\t}\n\treturn best;\n}\n\nexport interface ExperimentBranch {\n\treadonly outcome: number;\n\treadonly probability: number;\n\treadonly posterior: readonly number[];\n\treadonly risk: number;\n}\nexport interface ExperimentValue {\n\treadonly before: number;\n\treadonly expectedAfter: number;\n\treadonly grossValue: number;\n\treadonly cost: number;\n\treadonly netValue: number;\n\treadonly branches: readonly ExperimentBranch[];\n}\n\n/**\n * One-step value of information: Bayes risk before minus expected Bayes risk\n * after observing the experiment outcome, minus the experiment cost.\n * likelihoodByHypothesis[h][o] = P(outcome o | hypothesis h).\n * Zero-probability outcomes are skipped; the caller must treat an actually\n * observed impossible outcome as a model mismatch, never renormalize it away.\n */\nexport function experimentValue(\n\tprior: readonly number[],\n\tlosses: readonly (readonly number[])[],\n\tlikelihoodByHypothesis: readonly (readonly number[])[],\n\tcost: number,\n): ExperimentValue {\n\tprobabilityVector(prior, \"prior\");\n\tfinite(cost, \"cost\");\n\tconst rows = likelihoodByHypothesis.map((row) => {\n\t\tprobabilityVector(row, \"likelihood\");\n\t\treturn row;\n\t});\n\tensure(rows.length === prior.length, \"likelihood matrix must match hypotheses\");\n\tensure(new Set(rows.map((r) => r.length)).size === 1, \"likelihood matrix shape mismatch\");\n\tconst outcomeCount = rows[0]!.length;\n\tconst before = bayesRisk(prior, losses);\n\tconst branches: ExperimentBranch[] = [];\n\tlet expectedAfter = 0;\n\tfor (let outcome = 0; outcome < outcomeCount; outcome++) {\n\t\tconst masses = prior.map((p, h) => p * rows[h]![outcome]!);\n\t\tconst marginal = masses.reduce((a, b) => a + b, 0);\n\t\tif (marginal === 0) continue;\n\t\tconst posterior = masses.map((m) => m / marginal);\n\t\tconst after = bayesRisk(posterior, losses);\n\t\texpectedAfter += marginal * after;\n\t\tbranches.push({ outcome, probability: marginal, posterior, risk: after });\n\t}\n\treturn {\n\t\tbefore,\n\t\texpectedAfter,\n\t\tgrossValue: before - expectedAfter,\n\t\tcost,\n\t\tnetValue: before - expectedAfter - cost,\n\t\tbranches,\n\t};\n}\n\n/** Brier score for one binary event. */\nexport function brier(predicted: number, outcome: 0 | 1): number {\n\tprobability(predicted, \"predicted\");\n\tconst p = outcome === 1 ? predicted : 1 - predicted;\n\treturn (1 - p) ** 2;\n}\n\n/** Negative log-likelihood surprise for one binary event (epsilon-clamped). */\nexport function surprise(predicted: number, outcome: 0 | 1, epsilon = 1e-12): number {\n\tprobability(predicted, \"predicted\");\n\tfinite(epsilon, \"epsilon\", 1);\n\tensure(epsilon > 0, \"epsilon must be positive\");\n\tconst p = outcome === 1 ? predicted : 1 - predicted;\n\treturn -Math.log(Math.max(epsilon, p));\n}\n\n/**\n * Beta posterior mean for an independent binary task outcome under a fixed\n * policy in a homogeneous condition bucket. The prior (alpha, beta) must be\n * declared by the host; this is not a learned-calibration claim.\n */\nexport function betaPosteriorMean(alpha: number, beta: number, successes: number, failures: number): number {\n\tfinite(alpha, \"alpha\", 1e9);\n\tfinite(beta, \"beta\", 1e9);\n\tensure(alpha > 0 && beta > 0, \"beta prior parameters must be positive\");\n\tfinite(successes, \"successes\", 1e12);\n\tfinite(failures, \"failures\", 1e12);\n\treturn (alpha + successes) / (alpha + beta + successes + failures);\n}\n\n/**\n * CUSUM-style drift accumulator over per-observation losses in one condition\n * bucket. Returns the new accumulator value; the caller compares it against\n * a host-declared threshold h_g. Not a guaranteed false-alarm rate.\n */\nexport function driftStatistic(previous: number, loss: number, referenceMean: number, slack: number): number {\n\tfinite(previous, \"previous\");\n\tfinite(loss, \"loss\");\n\tfinite(referenceMean, \"referenceMean\");\n\tfinite(slack, \"slack\");\n\treturn Math.max(0, previous + loss - referenceMean - slack);\n}\n"]}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Finite decision-model arithmetic for metacognitive control.
3
+ *
4
+ * TypeScript port of docs/OMK_meta_algorithm_checks_2026-09-19.zip
5
+ * (check_examples.py) — the numerical checks referenced by
6
+ * OMK_metacognitive_control_algorithms_2026-09-19.md §5.3, §6.2.
7
+ *
8
+ * These are illustrative finite-model computations, NOT measured OMK risk
9
+ * estimates. Callers must supply real, defensible probabilities; this module
10
+ * only guarantees the arithmetic is correct and rejects malformed inputs.
11
+ */
12
+ import { ensure, finite, probability, probabilityVector } from "./validation.js";
13
+ /**
14
+ * Minimum expected loss over a finite set of terminal decisions.
15
+ * losses[d][h] is the loss of decision d when hypothesis h is true.
16
+ */
17
+ export function bayesRisk(prior, losses) {
18
+ probabilityVector(prior, "prior");
19
+ ensure(losses.length > 0, "at least one terminal decision is required");
20
+ let best = Number.POSITIVE_INFINITY;
21
+ for (const row of losses) {
22
+ ensure(row.length === prior.length, "loss row must match hypotheses");
23
+ let risk = 0;
24
+ for (let h = 0; h < prior.length; h++) {
25
+ finite(row[h], "loss");
26
+ risk += prior[h] * row[h];
27
+ }
28
+ if (risk < best)
29
+ best = risk;
30
+ }
31
+ return best;
32
+ }
33
+ /**
34
+ * One-step value of information: Bayes risk before minus expected Bayes risk
35
+ * after observing the experiment outcome, minus the experiment cost.
36
+ * likelihoodByHypothesis[h][o] = P(outcome o | hypothesis h).
37
+ * Zero-probability outcomes are skipped; the caller must treat an actually
38
+ * observed impossible outcome as a model mismatch, never renormalize it away.
39
+ */
40
+ export function experimentValue(prior, losses, likelihoodByHypothesis, cost) {
41
+ probabilityVector(prior, "prior");
42
+ finite(cost, "cost");
43
+ const rows = likelihoodByHypothesis.map((row) => {
44
+ probabilityVector(row, "likelihood");
45
+ return row;
46
+ });
47
+ ensure(rows.length === prior.length, "likelihood matrix must match hypotheses");
48
+ ensure(new Set(rows.map((r) => r.length)).size === 1, "likelihood matrix shape mismatch");
49
+ const outcomeCount = rows[0].length;
50
+ const before = bayesRisk(prior, losses);
51
+ const branches = [];
52
+ let expectedAfter = 0;
53
+ for (let outcome = 0; outcome < outcomeCount; outcome++) {
54
+ const masses = prior.map((p, h) => p * rows[h][outcome]);
55
+ const marginal = masses.reduce((a, b) => a + b, 0);
56
+ if (marginal === 0)
57
+ continue;
58
+ const posterior = masses.map((m) => m / marginal);
59
+ const after = bayesRisk(posterior, losses);
60
+ expectedAfter += marginal * after;
61
+ branches.push({ outcome, probability: marginal, posterior, risk: after });
62
+ }
63
+ return {
64
+ before,
65
+ expectedAfter,
66
+ grossValue: before - expectedAfter,
67
+ cost,
68
+ netValue: before - expectedAfter - cost,
69
+ branches,
70
+ };
71
+ }
72
+ /** Brier score for one binary event. */
73
+ export function brier(predicted, outcome) {
74
+ probability(predicted, "predicted");
75
+ const p = outcome === 1 ? predicted : 1 - predicted;
76
+ return (1 - p) ** 2;
77
+ }
78
+ /** Negative log-likelihood surprise for one binary event (epsilon-clamped). */
79
+ export function surprise(predicted, outcome, epsilon = 1e-12) {
80
+ probability(predicted, "predicted");
81
+ finite(epsilon, "epsilon", 1);
82
+ ensure(epsilon > 0, "epsilon must be positive");
83
+ const p = outcome === 1 ? predicted : 1 - predicted;
84
+ return -Math.log(Math.max(epsilon, p));
85
+ }
86
+ /**
87
+ * Beta posterior mean for an independent binary task outcome under a fixed
88
+ * policy in a homogeneous condition bucket. The prior (alpha, beta) must be
89
+ * declared by the host; this is not a learned-calibration claim.
90
+ */
91
+ export function betaPosteriorMean(alpha, beta, successes, failures) {
92
+ finite(alpha, "alpha", 1e9);
93
+ finite(beta, "beta", 1e9);
94
+ ensure(alpha > 0 && beta > 0, "beta prior parameters must be positive");
95
+ finite(successes, "successes", 1e12);
96
+ finite(failures, "failures", 1e12);
97
+ return (alpha + successes) / (alpha + beta + successes + failures);
98
+ }
99
+ /**
100
+ * CUSUM-style drift accumulator over per-observation losses in one condition
101
+ * bucket. Returns the new accumulator value; the caller compares it against
102
+ * a host-declared threshold h_g. Not a guaranteed false-alarm rate.
103
+ */
104
+ export function driftStatistic(previous, loss, referenceMean, slack) {
105
+ finite(previous, "previous");
106
+ finite(loss, "loss");
107
+ finite(referenceMean, "referenceMean");
108
+ finite(slack, "slack");
109
+ return Math.max(0, previous + loss - referenceMean - slack);
110
+ }
111
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/metacognition/decision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEjF;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAwB,EAAE,MAAsC,EAAU;IACnG,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,4CAA4C,CAAC,CAAC;IACxE,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAAC;QACtE,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,EAAE,MAAM,CAAC,CAAC;YACxB,IAAI,IAAI,KAAK,CAAC,CAAC,CAAE,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC;QAC7B,CAAC;QACD,IAAI,IAAI,GAAG,IAAI;YAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AAAA,CACZ;AAiBD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC9B,KAAwB,EACxB,MAAsC,EACtC,sBAAsD,EACtD,IAAY,EACM;IAClB,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrB,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QAChD,iBAAiB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACrC,OAAO,GAAG,CAAC;IAAA,CACX,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,yCAAyC,CAAC,CAAC;IAChF,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,kCAAkC,CAAC,CAAC;IAC1F,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC;IACrC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC,OAAO,CAAE,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACnD,IAAI,QAAQ,KAAK,CAAC;YAAE,SAAS;QAC7B,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC3C,aAAa,IAAI,QAAQ,GAAG,KAAK,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO;QACN,MAAM;QACN,aAAa;QACb,UAAU,EAAE,MAAM,GAAG,aAAa;QAClC,IAAI;QACJ,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;QACvC,QAAQ;KACR,CAAC;AAAA,CACF;AAED,wCAAwC;AACxC,MAAM,UAAU,KAAK,CAAC,SAAiB,EAAE,OAAc,EAAU;IAChE,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IACpD,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AAAA,CACpB;AAED,+EAA+E;AAC/E,MAAM,UAAU,QAAQ,CAAC,SAAiB,EAAE,OAAc,EAAE,OAAO,GAAG,KAAK,EAAU;IACpF,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACpC,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,0BAA0B,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AAAA,CACvC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,IAAY,EAAE,SAAiB,EAAE,QAAgB,EAAU;IAC3G,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,wCAAwC,CAAC,CAAC;IACxE,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC;AAAA,CACnE;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,IAAY,EAAE,aAAqB,EAAE,KAAa,EAAU;IAC5G,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC7B,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrB,MAAM,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,GAAG,aAAa,GAAG,KAAK,CAAC,CAAC;AAAA,CAC5D","sourcesContent":["/**\n * Finite decision-model arithmetic for metacognitive control.\n *\n * TypeScript port of docs/OMK_meta_algorithm_checks_2026-09-19.zip\n * (check_examples.py) — the numerical checks referenced by\n * OMK_metacognitive_control_algorithms_2026-09-19.md §5.3, §6.2.\n *\n * These are illustrative finite-model computations, NOT measured OMK risk\n * estimates. Callers must supply real, defensible probabilities; this module\n * only guarantees the arithmetic is correct and rejects malformed inputs.\n */\nimport { ensure, finite, probability, probabilityVector } from \"./validation.ts\";\n\n/**\n * Minimum expected loss over a finite set of terminal decisions.\n * losses[d][h] is the loss of decision d when hypothesis h is true.\n */\nexport function bayesRisk(prior: readonly number[], losses: readonly (readonly number[])[]): number {\n\tprobabilityVector(prior, \"prior\");\n\tensure(losses.length > 0, \"at least one terminal decision is required\");\n\tlet best = Number.POSITIVE_INFINITY;\n\tfor (const row of losses) {\n\t\tensure(row.length === prior.length, \"loss row must match hypotheses\");\n\t\tlet risk = 0;\n\t\tfor (let h = 0; h < prior.length; h++) {\n\t\t\tfinite(row[h]!, \"loss\");\n\t\t\trisk += prior[h]! * row[h]!;\n\t\t}\n\t\tif (risk < best) best = risk;\n\t}\n\treturn best;\n}\n\nexport interface ExperimentBranch {\n\treadonly outcome: number;\n\treadonly probability: number;\n\treadonly posterior: readonly number[];\n\treadonly risk: number;\n}\nexport interface ExperimentValue {\n\treadonly before: number;\n\treadonly expectedAfter: number;\n\treadonly grossValue: number;\n\treadonly cost: number;\n\treadonly netValue: number;\n\treadonly branches: readonly ExperimentBranch[];\n}\n\n/**\n * One-step value of information: Bayes risk before minus expected Bayes risk\n * after observing the experiment outcome, minus the experiment cost.\n * likelihoodByHypothesis[h][o] = P(outcome o | hypothesis h).\n * Zero-probability outcomes are skipped; the caller must treat an actually\n * observed impossible outcome as a model mismatch, never renormalize it away.\n */\nexport function experimentValue(\n\tprior: readonly number[],\n\tlosses: readonly (readonly number[])[],\n\tlikelihoodByHypothesis: readonly (readonly number[])[],\n\tcost: number,\n): ExperimentValue {\n\tprobabilityVector(prior, \"prior\");\n\tfinite(cost, \"cost\");\n\tconst rows = likelihoodByHypothesis.map((row) => {\n\t\tprobabilityVector(row, \"likelihood\");\n\t\treturn row;\n\t});\n\tensure(rows.length === prior.length, \"likelihood matrix must match hypotheses\");\n\tensure(new Set(rows.map((r) => r.length)).size === 1, \"likelihood matrix shape mismatch\");\n\tconst outcomeCount = rows[0]!.length;\n\tconst before = bayesRisk(prior, losses);\n\tconst branches: ExperimentBranch[] = [];\n\tlet expectedAfter = 0;\n\tfor (let outcome = 0; outcome < outcomeCount; outcome++) {\n\t\tconst masses = prior.map((p, h) => p * rows[h]![outcome]!);\n\t\tconst marginal = masses.reduce((a, b) => a + b, 0);\n\t\tif (marginal === 0) continue;\n\t\tconst posterior = masses.map((m) => m / marginal);\n\t\tconst after = bayesRisk(posterior, losses);\n\t\texpectedAfter += marginal * after;\n\t\tbranches.push({ outcome, probability: marginal, posterior, risk: after });\n\t}\n\treturn {\n\t\tbefore,\n\t\texpectedAfter,\n\t\tgrossValue: before - expectedAfter,\n\t\tcost,\n\t\tnetValue: before - expectedAfter - cost,\n\t\tbranches,\n\t};\n}\n\n/** Brier score for one binary event. */\nexport function brier(predicted: number, outcome: 0 | 1): number {\n\tprobability(predicted, \"predicted\");\n\tconst p = outcome === 1 ? predicted : 1 - predicted;\n\treturn (1 - p) ** 2;\n}\n\n/** Negative log-likelihood surprise for one binary event (epsilon-clamped). */\nexport function surprise(predicted: number, outcome: 0 | 1, epsilon = 1e-12): number {\n\tprobability(predicted, \"predicted\");\n\tfinite(epsilon, \"epsilon\", 1);\n\tensure(epsilon > 0, \"epsilon must be positive\");\n\tconst p = outcome === 1 ? predicted : 1 - predicted;\n\treturn -Math.log(Math.max(epsilon, p));\n}\n\n/**\n * Beta posterior mean for an independent binary task outcome under a fixed\n * policy in a homogeneous condition bucket. The prior (alpha, beta) must be\n * declared by the host; this is not a learned-calibration claim.\n */\nexport function betaPosteriorMean(alpha: number, beta: number, successes: number, failures: number): number {\n\tfinite(alpha, \"alpha\", 1e9);\n\tfinite(beta, \"beta\", 1e9);\n\tensure(alpha > 0 && beta > 0, \"beta prior parameters must be positive\");\n\tfinite(successes, \"successes\", 1e12);\n\tfinite(failures, \"failures\", 1e12);\n\treturn (alpha + successes) / (alpha + beta + successes + failures);\n}\n\n/**\n * CUSUM-style drift accumulator over per-observation losses in one condition\n * bucket. Returns the new accumulator value; the caller compares it against\n * a host-declared threshold h_g. Not a guaranteed false-alarm rate.\n */\nexport function driftStatistic(previous: number, loss: number, referenceMean: number, slack: number): number {\n\tfinite(previous, \"previous\");\n\tfinite(loss, \"loss\");\n\tfinite(referenceMean, \"referenceMean\");\n\tfinite(slack, \"slack\");\n\treturn Math.max(0, previous + loss - referenceMean - slack);\n}\n"]}
@@ -0,0 +1,73 @@
1
+ /** One logged decision for DR evaluation. Single checkpoint, not a trajectory. */
2
+ export interface LoggedDecision {
3
+ readonly contextHash: string;
4
+ readonly action: string;
5
+ readonly reward: number;
6
+ /** Logged selection probability under the recording policy. Required, never imputed. */
7
+ readonly propensity: number;
8
+ }
9
+ export interface DRInput {
10
+ readonly decisions: readonly LoggedDecision[];
11
+ /** π(a|x): the evaluated policy's action for each logged context. */
12
+ readonly evaluatedActions: readonly string[];
13
+ /** r̂(x,a): reward model per context-action pair. */
14
+ readonly rewardModel: readonly (readonly number[])[];
15
+ }
16
+ export interface DREstimate {
17
+ readonly value: number;
18
+ readonly n: number;
19
+ readonly clipped: number;
20
+ /** Contexts where the evaluated action had zero logged support — excluded, never imputed. */
21
+ readonly unsupported: number;
22
+ }
23
+ /**
24
+ * Single-decision Doubly Robust estimate:
25
+ * V̂_DR(π) = 1/n Σ [ Σ_a π(a|x_i)r̂(x_i,a) + (π(a_i|x_i)/μ(a_i|x_i))(r_i - r̂(x_i,a_i)) ].
26
+ * Deterministic logging policies that never tried an action cannot evaluate
27
+ * that action post-hoc — those rows are excluded and counted.
28
+ */
29
+ export declare function doublyRobustEstimate(input: DRInput, maxWeight?: number): DREstimate;
30
+ /** §11.3 experience memory — failure mechanism and discrimination, not essays. */
31
+ export interface ExperienceRecord {
32
+ readonly recordId: string;
33
+ readonly conditions: {
34
+ readonly modelRevision: string;
35
+ readonly toolchain: string;
36
+ readonly environmentHash: string;
37
+ readonly taskBand: string;
38
+ };
39
+ readonly failureMechanism: string;
40
+ readonly firstWrongExpectation: string;
41
+ readonly discriminatingObservation: string;
42
+ readonly appliedFixOrStrategy: string;
43
+ readonly checksBefore: readonly string[];
44
+ readonly checksAfter: readonly string[];
45
+ readonly knownCounterexamples: readonly string[];
46
+ readonly applicabilityConditions: readonly string[];
47
+ readonly evidenceRefs: readonly string[];
48
+ readonly policyVersion: string;
49
+ readonly skillHashes: readonly string[];
50
+ }
51
+ export declare function validateExperienceRecord(r: ExperienceRecord): void;
52
+ /** §15.3 completion metrics. Zero denominators are `undefined`, never 0 or 1. */
53
+ export interface OutcomeCounts {
54
+ readonly declaredComplete: number;
55
+ readonly independentFailAmongDeclared: number;
56
+ readonly allTasks: number;
57
+ readonly succeeded: number;
58
+ readonly abstained: number;
59
+ readonly totalCost: number;
60
+ }
61
+ export declare function completionMetrics(c: OutcomeCounts): {
62
+ readonly falseCompletionDeclared?: number;
63
+ readonly falseCompletionAll?: number;
64
+ readonly successRate?: number;
65
+ readonly abstainRate?: number;
66
+ readonly meanCost?: number;
67
+ };
68
+ /** §15.3 hidden-obligation detection with false alarms, for held-out requirements. */
69
+ export declare function hiddenObligationMetrics(detected: number, totalHidden: number, falseAlarms: number): {
70
+ readonly detectionRate?: number;
71
+ readonly falseAlarms: number;
72
+ };
73
+ //# sourceMappingURL=evaluation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluation.d.ts","sourceRoot":"","sources":["../../src/metacognition/evaluation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * §11 causal strategy evaluation + §15 outcome metrics.\n *\n * Doubly Robust estimation is a second-stage offline tool over logged\n * single-checkpoint decisions: it needs real logged propensities, action\n * support, and rewards — never probabilities invented after the fact.\n * Completion metrics report false-completion alongside success/abstain rates,\n * because a policy that never completes can trivially zero false completions.\n */\nimport { ensure, finite, integer, probability, text } from \"./validation.ts\";\n\n/** One logged decision for DR evaluation. Single checkpoint, not a trajectory. */\nexport interface LoggedDecision {\n\treadonly contextHash: string;\n\treadonly action: string;\n\treadonly reward: number;\n\t/** Logged selection probability under the recording policy. Required, never imputed. */\n\treadonly propensity: number;\n}\nexport interface DRInput {\n\treadonly decisions: readonly LoggedDecision[];\n\t/** π(a|x): the evaluated policy's action for each logged context. */\n\treadonly evaluatedActions: readonly string[];\n\t/** r̂(x,a): reward model per context-action pair. */\n\treadonly rewardModel: readonly (readonly number[])[];\n}\nexport interface DREstimate {\n\treadonly value: number;\n\treadonly n: number;\n\treadonly clipped: number;\n\t/** Contexts where the evaluated action had zero logged support — excluded, never imputed. */\n\treadonly unsupported: number;\n}\n\n/**\n * Single-decision Doubly Robust estimate:\n * V̂_DR(π) = 1/n Σ [ Σ_a π(a|x_i)r̂(x_i,a) + (π(a_i|x_i)/μ(a_i|x_i))(r_i - r̂(x_i,a_i)) ].\n * Deterministic logging policies that never tried an action cannot evaluate\n * that action post-hoc — those rows are excluded and counted.\n */\nexport function doublyRobustEstimate(input: DRInput, maxWeight = 50): DREstimate {\n\tconst { decisions, evaluatedActions, rewardModel } = input;\n\tinteger(decisions.length, \"decisions\", 1_000_000);\n\tensure(decisions.length > 0, \"no logged decisions\");\n\tensure(evaluatedActions.length === decisions.length, \"evaluated action count mismatch\");\n\tensure(rewardModel.length === decisions.length, \"reward model row mismatch\");\n\tfinite(maxWeight, \"maxWeight\", 1e9);\n\tlet sum = 0,\n\t\tclipped = 0,\n\t\tunsupported = 0,\n\t\tusable = 0;\n\tfor (let i = 0; i < decisions.length; i++) {\n\t\tconst d = decisions[i]!;\n\t\ttext(d.contextHash, \"contextHash\", 256);\n\t\ttext(d.action, \"action\", 128);\n\t\tfinite(d.reward, \"reward\");\n\t\tprobability(d.propensity, \"propensity\");\n\t\ttext(evaluatedActions[i]!, \"evaluated action\", 128);\n\t\tconst rewards = rewardModel[i]!;\n\t\tensure(rewards.length > 0, \"reward model row empty\");\n\t\tfor (const r of rewards) finite(r, \"reward model value\");\n\t\t// Contexts may carry several logged actions; μ is per recorded decision.\n\t\tconst modelMean = rewards.reduce((a, b) => a + b, 0) / rewards.length;\n\t\tif (d.propensity === 0 && d.action === evaluatedActions[i]) {\n\t\t\tunsupported++;\n\t\t\tcontinue;\n\t\t}\n\t\tusable++;\n\t\tconst weight = d.action === evaluatedActions[i] ? Math.min(maxWeight, 1 / d.propensity) : 0;\n\t\tif (weight === maxWeight) clipped++;\n\t\tsum += modelMean + weight * (d.reward - modelMean);\n\t}\n\tensure(usable > 0, \"no decisions with logged support for the evaluated policy\");\n\treturn { value: sum / usable, n: usable, clipped, unsupported };\n}\n\n/** §11.3 experience memory — failure mechanism and discrimination, not essays. */\nexport interface ExperienceRecord {\n\treadonly recordId: string;\n\treadonly conditions: {\n\t\treadonly modelRevision: string;\n\t\treadonly toolchain: string;\n\t\treadonly environmentHash: string;\n\t\treadonly taskBand: string;\n\t};\n\treadonly failureMechanism: string;\n\treadonly firstWrongExpectation: string;\n\treadonly discriminatingObservation: string;\n\treadonly appliedFixOrStrategy: string;\n\treadonly checksBefore: readonly string[];\n\treadonly checksAfter: readonly string[];\n\treadonly knownCounterexamples: readonly string[];\n\treadonly applicabilityConditions: readonly string[];\n\treadonly evidenceRefs: readonly string[];\n\treadonly policyVersion: string;\n\treadonly skillHashes: readonly string[];\n}\nexport function validateExperienceRecord(r: ExperienceRecord): void {\n\ttext(r.recordId, \"recordId\", 128);\n\ttext(r.failureMechanism, \"failureMechanism\", 2048);\n\ttext(r.firstWrongExpectation, \"firstWrongExpectation\", 2048);\n\ttext(r.discriminatingObservation, \"discriminatingObservation\", 2048);\n\ttext(r.appliedFixOrStrategy, \"appliedFixOrStrategy\", 2048);\n\ttext(r.policyVersion, \"policyVersion\", 64);\n\tfor (const list of [\n\t\tr.checksBefore,\n\t\tr.checksAfter,\n\t\tr.knownCounterexamples,\n\t\tr.applicabilityConditions,\n\t\tr.evidenceRefs,\n\t\tr.skillHashes,\n\t]) {\n\t\tensure(Array.isArray(list) && list.length <= 128, \"experience record list bound\");\n\t}\n}\n\n/** §15.3 completion metrics. Zero denominators are `undefined`, never 0 or 1. */\nexport interface OutcomeCounts {\n\treadonly declaredComplete: number;\n\treadonly independentFailAmongDeclared: number;\n\treadonly allTasks: number;\n\treadonly succeeded: number;\n\treadonly abstained: number;\n\treadonly totalCost: number;\n}\nexport function completionMetrics(c: OutcomeCounts): {\n\treadonly falseCompletionDeclared?: number;\n\treadonly falseCompletionAll?: number;\n\treadonly successRate?: number;\n\treadonly abstainRate?: number;\n\treadonly meanCost?: number;\n} {\n\tinteger(c.declaredComplete, \"declaredComplete\");\n\tinteger(c.independentFailAmongDeclared, \"independentFail\");\n\tinteger(c.allTasks, \"allTasks\");\n\tinteger(c.succeeded, \"succeeded\");\n\tinteger(c.abstained, \"abstained\");\n\tfinite(c.totalCost, \"totalCost\");\n\tensure(c.independentFailAmongDeclared <= c.declaredComplete, \"fail count exceeds declared\");\n\tensure(\n\t\tc.declaredComplete <= c.allTasks && c.succeeded <= c.allTasks && c.abstained <= c.allTasks,\n\t\t\"counts exceed task total\",\n\t);\n\treturn {\n\t\tfalseCompletionDeclared: c.declaredComplete > 0 ? c.independentFailAmongDeclared / c.declaredComplete : undefined,\n\t\tfalseCompletionAll: c.allTasks > 0 ? c.independentFailAmongDeclared / c.allTasks : undefined,\n\t\tsuccessRate: c.allTasks > 0 ? c.succeeded / c.allTasks : undefined,\n\t\tabstainRate: c.allTasks > 0 ? c.abstained / c.allTasks : undefined,\n\t\tmeanCost: c.allTasks > 0 ? c.totalCost / c.allTasks : undefined,\n\t};\n}\n\n/** §15.3 hidden-obligation detection with false alarms, for held-out requirements. */\nexport function hiddenObligationMetrics(\n\tdetected: number,\n\ttotalHidden: number,\n\tfalseAlarms: number,\n): {\n\treadonly detectionRate?: number;\n\treadonly falseAlarms: number;\n} {\n\tinteger(detected, \"detected\");\n\tinteger(totalHidden, \"totalHidden\");\n\tinteger(falseAlarms, \"falseAlarms\");\n\tensure(detected <= totalHidden, \"detected exceeds hidden total\");\n\treturn {\n\t\tdetectionRate: totalHidden > 0 ? detected / totalHidden : undefined,\n\t\tfalseAlarms,\n\t};\n}\n"]}