open-multi-agent-kit 0.95.2 → 0.96.1

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 (259) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +37 -4
  3. package/dist/approvals/approval-receipt-store.d.ts.map +1 -1
  4. package/dist/approvals/approval-receipt-store.js +25 -0
  5. package/dist/approvals/approval-receipt-store.js.map +1 -1
  6. package/dist/commands/doctor-provider.d.ts.map +1 -1
  7. package/dist/commands/doctor-provider.js +15 -20
  8. package/dist/commands/doctor-provider.js.map +1 -1
  9. package/dist/commands/sdk-session-cli.d.ts +24 -0
  10. package/dist/commands/sdk-session-cli.d.ts.map +1 -0
  11. package/dist/commands/sdk-session-cli.js +225 -0
  12. package/dist/commands/sdk-session-cli.js.map +1 -0
  13. package/dist/core/advisory-judge-model.d.ts +18 -0
  14. package/dist/core/advisory-judge-model.d.ts.map +1 -0
  15. package/dist/core/advisory-judge-model.js +168 -0
  16. package/dist/core/advisory-judge-model.js.map +1 -0
  17. package/dist/core/advisory-judge-response.d.ts +8 -0
  18. package/dist/core/advisory-judge-response.d.ts.map +1 -0
  19. package/dist/core/advisory-judge-response.js +61 -0
  20. package/dist/core/advisory-judge-response.js.map +1 -0
  21. package/dist/core/advisory-judge-types.d.ts +53 -0
  22. package/dist/core/advisory-judge-types.d.ts.map +1 -0
  23. package/dist/core/advisory-judge-types.js +2 -0
  24. package/dist/core/advisory-judge-types.js.map +1 -0
  25. package/dist/core/advisory-judge.d.ts +8 -0
  26. package/dist/core/advisory-judge.d.ts.map +1 -0
  27. package/dist/core/advisory-judge.js +178 -0
  28. package/dist/core/advisory-judge.js.map +1 -0
  29. package/dist/core/agent-session-services.d.ts +1 -0
  30. package/dist/core/agent-session-services.d.ts.map +1 -1
  31. package/dist/core/agent-session-services.js +1 -0
  32. package/dist/core/agent-session-services.js.map +1 -1
  33. package/dist/core/agent-session.d.ts +6 -3
  34. package/dist/core/agent-session.d.ts.map +1 -1
  35. package/dist/core/agent-session.js +141 -184
  36. package/dist/core/agent-session.js.map +1 -1
  37. package/dist/core/auth-storage.d.ts.map +1 -1
  38. package/dist/core/auth-storage.js +28 -4
  39. package/dist/core/auth-storage.js.map +1 -1
  40. package/dist/core/compaction-gate.d.ts +28 -0
  41. package/dist/core/compaction-gate.d.ts.map +1 -0
  42. package/dist/core/compaction-gate.js +34 -0
  43. package/dist/core/compaction-gate.js.map +1 -0
  44. package/dist/core/context-budget-system-prompt-items.d.ts.map +1 -1
  45. package/dist/core/context-budget-system-prompt-items.js +5 -3
  46. package/dist/core/context-budget-system-prompt-items.js.map +1 -1
  47. package/dist/core/domain-loadouts.d.ts.map +1 -1
  48. package/dist/core/domain-loadouts.js +2 -2
  49. package/dist/core/domain-loadouts.js.map +1 -1
  50. package/dist/core/durable-goal-checkpoint.d.ts +6 -0
  51. package/dist/core/durable-goal-checkpoint.d.ts.map +1 -0
  52. package/dist/core/durable-goal-checkpoint.js +195 -0
  53. package/dist/core/durable-goal-checkpoint.js.map +1 -0
  54. package/dist/core/durable-goal-parse.d.ts +3 -0
  55. package/dist/core/durable-goal-parse.d.ts.map +1 -0
  56. package/dist/core/durable-goal-parse.js +86 -0
  57. package/dist/core/durable-goal-parse.js.map +1 -0
  58. package/dist/core/durable-goal-reducer.d.ts +3 -0
  59. package/dist/core/durable-goal-reducer.d.ts.map +1 -0
  60. package/dist/core/durable-goal-reducer.js +175 -0
  61. package/dist/core/durable-goal-reducer.js.map +1 -0
  62. package/dist/core/durable-goal-store.d.ts +19 -0
  63. package/dist/core/durable-goal-store.d.ts.map +1 -0
  64. package/dist/core/durable-goal-store.js +126 -0
  65. package/dist/core/durable-goal-store.js.map +1 -0
  66. package/dist/core/durable-goal.d.ts +92 -0
  67. package/dist/core/durable-goal.d.ts.map +1 -0
  68. package/dist/core/durable-goal.js +62 -0
  69. package/dist/core/durable-goal.js.map +1 -0
  70. package/dist/core/extensions/builtin/goal-controller.d.ts +3 -0
  71. package/dist/core/extensions/builtin/goal-controller.d.ts.map +1 -0
  72. package/dist/core/extensions/builtin/goal-controller.js +125 -0
  73. package/dist/core/extensions/builtin/goal-controller.js.map +1 -0
  74. package/dist/core/extensions/builtin/identical-loop.d.ts +3 -0
  75. package/dist/core/extensions/builtin/identical-loop.d.ts.map +1 -0
  76. package/dist/core/extensions/builtin/identical-loop.js +31 -0
  77. package/dist/core/extensions/builtin/identical-loop.js.map +1 -0
  78. package/dist/core/extensions/builtin/prompt-preset.d.ts +3 -0
  79. package/dist/core/extensions/builtin/prompt-preset.d.ts.map +1 -0
  80. package/dist/core/extensions/builtin/prompt-preset.js +13 -0
  81. package/dist/core/extensions/builtin/prompt-preset.js.map +1 -0
  82. package/dist/core/extensions/builtin/tool-pair-repair.d.ts +3 -0
  83. package/dist/core/extensions/builtin/tool-pair-repair.d.ts.map +1 -0
  84. package/dist/core/extensions/builtin/tool-pair-repair.js +12 -0
  85. package/dist/core/extensions/builtin/tool-pair-repair.js.map +1 -0
  86. package/dist/core/extensions/types.d.ts +6 -2
  87. package/dist/core/extensions/types.d.ts.map +1 -1
  88. package/dist/core/extensions/types.js.map +1 -1
  89. package/dist/core/goal-continuation.d.ts +13 -0
  90. package/dist/core/goal-continuation.d.ts.map +1 -0
  91. package/dist/core/goal-continuation.js +10 -0
  92. package/dist/core/goal-continuation.js.map +1 -0
  93. package/dist/core/grok-harness.d.ts +1 -1
  94. package/dist/core/grok-harness.d.ts.map +1 -1
  95. package/dist/core/grok-harness.js +1 -1
  96. package/dist/core/grok-harness.js.map +1 -1
  97. package/dist/core/grok-playbook.d.ts +1 -1
  98. package/dist/core/grok-playbook.d.ts.map +1 -1
  99. package/dist/core/grok-playbook.js +1 -1
  100. package/dist/core/grok-playbook.js.map +1 -1
  101. package/dist/core/identical-loop.d.ts +15 -0
  102. package/dist/core/identical-loop.d.ts.map +1 -0
  103. package/dist/core/identical-loop.js +34 -0
  104. package/dist/core/identical-loop.js.map +1 -0
  105. package/dist/core/index.d.ts +1 -1
  106. package/dist/core/index.d.ts.map +1 -1
  107. package/dist/core/index.js +1 -1
  108. package/dist/core/index.js.map +1 -1
  109. package/dist/core/model-prompt-policy.d.ts +11 -0
  110. package/dist/core/model-prompt-policy.d.ts.map +1 -0
  111. package/dist/core/model-prompt-policy.js +17 -0
  112. package/dist/core/model-prompt-policy.js.map +1 -0
  113. package/dist/core/model-registry.d.ts.map +1 -1
  114. package/dist/core/model-registry.js +16 -4
  115. package/dist/core/model-registry.js.map +1 -1
  116. package/dist/core/model-resolver.d.ts.map +1 -1
  117. package/dist/core/model-resolver.js +2 -2
  118. package/dist/core/model-resolver.js.map +1 -1
  119. package/dist/core/prompt-budget.d.ts +21 -0
  120. package/dist/core/prompt-budget.d.ts.map +1 -0
  121. package/dist/core/prompt-budget.js +51 -0
  122. package/dist/core/prompt-budget.js.map +1 -0
  123. package/dist/core/prompt-cache.d.ts +14 -0
  124. package/dist/core/prompt-cache.d.ts.map +1 -0
  125. package/dist/core/prompt-cache.js +16 -0
  126. package/dist/core/prompt-cache.js.map +1 -0
  127. package/dist/core/prompt-preset.d.ts +8 -0
  128. package/dist/core/prompt-preset.d.ts.map +1 -0
  129. package/dist/core/prompt-preset.js +56 -0
  130. package/dist/core/prompt-preset.js.map +1 -0
  131. package/dist/core/provider-resilience.d.ts +23 -0
  132. package/dist/core/provider-resilience.d.ts.map +1 -1
  133. package/dist/core/provider-resilience.js +34 -1
  134. package/dist/core/provider-resilience.js.map +1 -1
  135. package/dist/core/provider-retry.d.ts +29 -0
  136. package/dist/core/provider-retry.d.ts.map +1 -0
  137. package/dist/core/provider-retry.js +49 -0
  138. package/dist/core/provider-retry.js.map +1 -0
  139. package/dist/core/provider-usage.d.ts +2 -1
  140. package/dist/core/provider-usage.d.ts.map +1 -1
  141. package/dist/core/provider-usage.js +40 -6
  142. package/dist/core/provider-usage.js.map +1 -1
  143. package/dist/core/resource-loader.d.ts.map +1 -1
  144. package/dist/core/resource-loader.js +32 -0
  145. package/dist/core/resource-loader.js.map +1 -1
  146. package/dist/core/sandbox/backend.d.ts +12 -0
  147. package/dist/core/sandbox/backend.d.ts.map +1 -1
  148. package/dist/core/sandbox/backend.js +52 -42
  149. package/dist/core/sandbox/backend.js.map +1 -1
  150. package/dist/core/sandbox/policy.d.ts +2 -0
  151. package/dist/core/sandbox/policy.d.ts.map +1 -1
  152. package/dist/core/sandbox/policy.js +2 -1
  153. package/dist/core/sandbox/policy.js.map +1 -1
  154. package/dist/core/sdk.d.ts +2 -0
  155. package/dist/core/sdk.d.ts.map +1 -1
  156. package/dist/core/sdk.js +1 -0
  157. package/dist/core/sdk.js.map +1 -1
  158. package/dist/core/session-system-prompt.d.ts +28 -0
  159. package/dist/core/session-system-prompt.d.ts.map +1 -0
  160. package/dist/core/session-system-prompt.js +37 -0
  161. package/dist/core/session-system-prompt.js.map +1 -0
  162. package/dist/core/strict-record.d.ts +2 -0
  163. package/dist/core/strict-record.d.ts.map +1 -0
  164. package/dist/core/strict-record.js +9 -0
  165. package/dist/core/strict-record.js.map +1 -0
  166. package/dist/core/subagent-orchestration.d.ts.map +1 -1
  167. package/dist/core/subagent-orchestration.js +4 -2
  168. package/dist/core/subagent-orchestration.js.map +1 -1
  169. package/dist/core/tool-pair-repair.d.ts +11 -0
  170. package/dist/core/tool-pair-repair.d.ts.map +1 -0
  171. package/dist/core/tool-pair-repair.js +38 -0
  172. package/dist/core/tool-pair-repair.js.map +1 -0
  173. package/dist/core/tools/artifact-spill.d.ts +13 -0
  174. package/dist/core/tools/artifact-spill.d.ts.map +1 -0
  175. package/dist/core/tools/artifact-spill.js +26 -0
  176. package/dist/core/tools/artifact-spill.js.map +1 -0
  177. package/dist/core/tools/bash.d.ts +7 -4
  178. package/dist/core/tools/bash.d.ts.map +1 -1
  179. package/dist/core/tools/bash.js +8 -7
  180. package/dist/core/tools/bash.js.map +1 -1
  181. package/dist/core/tools/diagnostics.d.ts.map +1 -1
  182. package/dist/core/tools/diagnostics.js +8 -2
  183. package/dist/core/tools/diagnostics.js.map +1 -1
  184. package/dist/core/tools/index.d.ts +1 -1
  185. package/dist/core/tools/index.d.ts.map +1 -1
  186. package/dist/core/tools/index.js.map +1 -1
  187. package/dist/core/tools/read.d.ts +1 -0
  188. package/dist/core/tools/read.d.ts.map +1 -1
  189. package/dist/core/tools/read.js +10 -1
  190. package/dist/core/tools/read.js.map +1 -1
  191. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  192. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  193. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  194. package/dist/guardrails/evidence-protocol.d.ts +10 -0
  195. package/dist/guardrails/evidence-protocol.d.ts.map +1 -0
  196. package/dist/guardrails/evidence-protocol.js +34 -0
  197. package/dist/guardrails/evidence-protocol.js.map +1 -0
  198. package/dist/guardrails/evidence-system.d.ts +3 -1
  199. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  200. package/dist/guardrails/evidence-system.js +22 -14
  201. package/dist/guardrails/evidence-system.js.map +1 -1
  202. package/dist/guardrails/replay-ledger-lock-owner.d.ts.map +1 -1
  203. package/dist/guardrails/replay-ledger-lock-owner.js +3 -1
  204. package/dist/guardrails/replay-ledger-lock-owner.js.map +1 -1
  205. package/dist/guardrails/replay-payload-hash.d.ts +6 -0
  206. package/dist/guardrails/replay-payload-hash.d.ts.map +1 -0
  207. package/dist/guardrails/replay-payload-hash.js +24 -0
  208. package/dist/guardrails/replay-payload-hash.js.map +1 -0
  209. package/dist/index.d.ts +20 -2
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +19 -0
  212. package/dist/index.js.map +1 -1
  213. package/dist/main.d.ts.map +1 -1
  214. package/dist/main.js +8 -0
  215. package/dist/main.js.map +1 -1
  216. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  217. package/dist/modes/interactive/theme/theme.js +14 -3
  218. package/dist/modes/interactive/theme/theme.js.map +1 -1
  219. package/dist/types/evidence.d.ts +11 -3
  220. package/dist/types/evidence.d.ts.map +1 -1
  221. package/dist/types/evidence.js.map +1 -1
  222. package/docs/adaptorch-preview-spec.md +1 -1
  223. package/docs/adaptorch-preview.md +2 -2
  224. package/docs/book-to-skill.md +79 -0
  225. package/docs/compaction.md +10 -0
  226. package/docs/containerization.md +9 -0
  227. package/docs/docs.json +18 -2
  228. package/docs/environment-variables.md +11 -4
  229. package/docs/extensions.md +14 -1
  230. package/docs/grok-harness.md +35 -12
  231. package/docs/index.md +9 -5
  232. package/docs/loadout-domains/grok-harness.md +2 -2
  233. package/docs/models.md +21 -8
  234. package/docs/provider-resilience.md +42 -55
  235. package/docs/providers.md +13 -4
  236. package/docs/run-protocol.md +104 -0
  237. package/docs/sdk.md +111 -5
  238. package/docs/security.md +22 -32
  239. package/docs/sessions.md +20 -0
  240. package/docs/settings.md +2 -0
  241. package/docs/skills.md +9 -1
  242. package/docs/usage.md +38 -16
  243. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  244. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  245. package/examples/extensions/custom-provider-gitlab-duo/index.ts +6 -1
  246. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  247. package/examples/extensions/gondolin/package-lock.json +2 -2
  248. package/examples/extensions/gondolin/package.json +1 -1
  249. package/examples/extensions/sandbox/package-lock.json +2 -2
  250. package/examples/extensions/sandbox/package.json +1 -1
  251. package/examples/extensions/with-deps/package-lock.json +2 -2
  252. package/examples/extensions/with-deps/package.json +1 -1
  253. package/npm-shrinkwrap.json +37 -15
  254. package/package.json +8 -5
  255. package/dist/core/context-budget-compressors.d.ts +0 -50
  256. package/dist/core/context-budget-compressors.d.ts.map +0 -1
  257. package/dist/core/context-budget-compressors.js +0 -166
  258. package/dist/core/context-budget-compressors.js.map +0 -1
  259. package/dist/core/extensions/loader.js.bak-sharedjiti-20260812-111246 +0 -553
@@ -1,87 +1,74 @@
1
- # Provider resilience (root-level)
1
+ # Provider Resilience
2
2
 
3
- Built into OMK core not an optional extension.
3
+ OMK can recover an agent turn from provider failures that are unlikely to succeed unchanged:
4
4
 
5
- ## What it does
5
+ - content or safety stops reported as errors
6
+ - billing-cycle or quota exhaustion
7
+ - orphaned `tool_call_id` protocol errors
8
+ - transient transport and server failures
6
9
 
7
- 1. **Blocks sticky safety models** (e.g. `claude-fable-5`) from being selected as the session chat model.
8
- 2. **Ejects** them at prompt time if a resumed session still has one loaded.
9
- 3. On **content/safety stop** (`stop_reason=refusal`), **auto-failovers** to `k3 → grok-4.5 → deepseek` before retry.
10
- 4. Works with message sanitize (`transform-messages` orphan `tool_call_id` drop) so K3 protocol 400s can heal on retry.
10
+ This is availability behavior, not a safety bypass. Provider safety policy and the user's configured model access remain authoritative.
11
11
 
12
- This is session survival engineering, not a jailbreak.
12
+ ## Settings
13
13
 
14
- ## Settings (`~/.omk/agent/settings.json`)
14
+ Configure resilience in `~/.omk/agent/settings.json` or `.omk/settings.json`:
15
15
 
16
16
  ```json
17
17
  {
18
- "defaultProvider": "kimi-coding",
19
- "defaultModel": "k3",
20
18
  "providerResilience": {
21
19
  "blockStickySafetyModels": true,
22
20
  "autoFailoverOnSafetyStop": true,
23
21
  "failoverCandidates": [
24
22
  { "provider": "kimi-coding", "id": "k3" },
25
- { "provider": "grok-oauth-proxy", "id": "grok-4.5" },
26
- { "provider": "deepseek", "id": "deepseek-v4-pro" }
23
+ { "provider": "modelstudio-maas", "id": "qwen3.8-max-preview" }
27
24
  ]
28
25
  }
29
26
  }
30
27
  ```
31
28
 
32
- | Key | Default | Meaning |
33
- |---|---|---|
34
- | `blockStickySafetyModels` | `true` | Refuse `setModel` / initial pick of Fable-class ids |
35
- | `autoFailoverOnSafetyStop` | `true` | Switch model before auto-retry on safety stop |
36
- | `failoverCandidates` | k3→grok→deepseek… | Ordered targets |
29
+ | Setting | Default | Behavior |
30
+ |---|---:|---|
31
+ | `blockStickySafetyModels` | `true` | Blocks interactive and automatic activation of models known to produce sticky false-positive safety stops. The catalog still lists them; set this to `false` to use an interactive or saved selection. |
32
+ | `autoFailoverOnSafetyStop` | `true` | Enables failover for safety stops and quota/billing exhaustion. |
33
+ | `failoverCandidates` | built-in chain | Ordered models considered before an automatic retry. |
37
34
 
38
- Disable only if you intentionally want Fable:
35
+ Automatic recovery also requires `retry.enabled: true` and available retry budget.
39
36
 
40
- ```json
41
- "providerResilience": { "blockStickySafetyModels": false, "autoFailoverOnSafetyStop": false }
42
- ```
37
+ An explicit `--model` or `--provider`/`--model` pin keeps automatic resilience from replacing that model. A later manual model selection can still change it.
38
+ Safety-stop failover and sticky-model eject do not run on a pinned model.
39
+ Claude Fable, Opus, and Sonnet also stay on-model after a content/safety stop,
40
+ even without `--model` and even when skills are loaded. Those refusals are not
41
+ retried on DeepSeek or Kimi.
43
42
 
44
- ## Code
43
+ ## Failover behavior
45
44
 
46
- | Module | Role |
47
- |---|---|
48
- | `src/core/provider-resilience.ts` | Shared detectors + failover pick |
49
- | `src/core/agent-session.ts` | eject / failover / retry wiring |
50
- | `src/core/model-resolver.ts` | skip sticky on initial model pick |
51
- | `src/core/settings-manager.ts` | `providerResilience` settings |
52
- | `packages/ai/.../transform-messages.ts` | drop orphan tool results |
45
+ For a safety stop or recognized quota/billing error, OMK:
53
46
 
54
- ## How Fable is neutralized (not "jailbroken")
47
+ 1. classifies the failed provider attempt;
48
+ 2. excludes the current model and models already failed during this retry sequence;
49
+ 3. selects the first non-sticky candidate that exists and has configured authentication;
50
+ 4. switches models before retrying with a short delay.
55
51
 
56
- Server-side content/safety stops cannot be removed by OAuth RE or local patches.
57
- OMK **deletes Fable from the operational surface**:
52
+ A content/safety stop gets at most one automatic retry, including a retry that switches model, regardless of the larger transport retry budget. Other transient failures keep the configured retry policy and backoff. Plain authentication errors remain non-retryable and do not trigger failover.
58
53
 
59
- | Layer | Kill switch |
60
- |---|---|
61
- | `models.json` | `claude-fable-5` removed from anthropic catalog |
62
- | `model-registry.loadModels` | `/fable/i` filtered unless `OMK_ALLOW_STICKY_SAFETY_MODELS=1` |
63
- | `model-resolver` | sticky skipped; k3 preferred |
64
- | `setModel` | throws if sticky + block on |
65
- | `cycleModel` (scoped + available) | sticky filtered; goes through `setModel` |
66
- | prompt boundary | ejects leftover Fable session model → k3 |
67
- | safety-stop retry | failover chain before continue |
54
+ Recognized quota shapes include billing-cycle usage limits, `insufficient_quota`, exhausted balances, `GoUsageLimitError`, `FreeUsageLimitError`, and out-of-budget responses. These are classified as `provider.rate_limit`, even when a provider wraps them in HTTP 403.
68
55
 
69
- **You don't fight Fable. You never load it.**
56
+ The default candidate order is:
70
57
 
71
- ## Operator
58
+ 1. `kimi-coding/k3`
59
+ 2. `modelstudio-maas/qwen3.8-max-preview`
60
+ 3. `xai/grok-4.5`
61
+ 4. `deepseek/deepseek-v4-pro`
62
+ 5. `deepseek/deepseek-v4-flash`
63
+ 6. `modelstudio-maas/deepseek-v4-pro`
64
+ 7. `kimi-coding/kimi-for-coding`
72
65
 
73
- ```
74
- # after rebuild — restart OMK session (required)
66
+ ## Retry and termination events
75
67
 
76
- /model k3 # if still on a bad model
77
- /new # if transcript is corrupted (orphan tool ids)
68
+ Each provider attempt is journaled separately and emits `session_termination`. A retryable failure is attempt-level when an `auto_retry_start` event follows it. A recovered retry later emits a `completed` termination; an exhausted retry budget leaves the last provider failure as the final termination.
78
69
 
79
- # emergency re-enable Fable (not recommended)
80
- OMK_ALLOW_STICKY_SAFETY_MODELS=1 omk
81
- # and settings: providerResilience.blockStickySafetyModels=false
82
- ```
70
+ See [Sessions](sessions.md#retries-and-termination-events) for consumer guidance.
83
71
 
84
- ## arXiv note (2026-07)
72
+ ## Protocol recovery
85
73
 
86
- Recent cs.CL hits on refusal/jailbreak are mostly attack-ASR / weight-edit / prefill studies.
87
- No immediate ops patch beyond routing+sanitize already in-tree. Skip theory-only papers.
74
+ For orphaned `tool_call_id` errors, OMK removes the failed assistant message from the live retry context. The standard message transform then drops tool results whose originating call is absent. Persisted session history remains unchanged for auditability.
package/docs/providers.md CHANGED
@@ -18,16 +18,19 @@ Use `/login` in interactive mode, then select a provider:
18
18
  - ChatGPT Plus/Pro (Codex)
19
19
  - Claude Pro/Max
20
20
  - GitHub Copilot
21
+ - xAI Grok subscription OAuth
21
22
 
22
23
  Run `/login` and choose a configured subscription provider to open its account picker. Select an existing account by its ChatGPT, Claude, or Google email when available, or choose **Add another account** to sign in with a new one. OMK keeps and refreshes each account independently, pins the provider to the account you select, and does not silently fail over to another subscription. `/model` remains dedicated to model selection.
23
24
 
24
25
  Use `/logout` to clear all stored accounts for a provider. Tokens are stored in `~/.omk/agent/auth.json` and auto-refresh when expired.
25
26
 
26
- When the status sidebar is pinned, its **USAGE** section lists every configured subscription provider, with the active provider first. OMK reads quota windows from fixed provider endpoints for Codex, Claude, Kimi Code, and GLM/ZAI Coding Plan, caches the result, and displays each percentage and reset countdown separately. Claude also passively merges the official `anthropic-ratelimit-unified-*` response headers used by Claude Code. If Anthropic's usage endpoint is rate limited and no complete recent snapshot exists, OMK mirrors Claude Code's own startup quota check with one fixed-endpoint Haiku request capped at one output token, no more than once per OAuth credential per hour. This fallback consumes a small amount of Claude plan quota.
27
+ When the status sidebar is pinned, its **USAGE** section lists every configured subscription provider, with the active provider first. OMK reads quota windows from fixed provider endpoints for Codex, Claude, Kimi Code, GLM/ZAI Coding Plan, and native xAI SuperGrok, caches the result, and displays each percentage and reset countdown separately. Claude also passively merges the official `anthropic-ratelimit-unified-*` response headers used by Claude Code. If Anthropic's usage endpoint is rate limited and no complete recent snapshot exists, OMK mirrors Claude Code's own startup quota check with one fixed-endpoint Haiku request capped at one output token, no more than once per OAuth credential per hour. This fallback consumes a small amount of Claude plan quota.
27
28
 
28
29
  Codex streaming passively merges `x-codex-primary-*`, `x-codex-secondary-*`, and `codex.rate_limits` signals through the non-blocking `StreamOptions.onRateLimit` observer. These signals supplement missing polling windows only when the Codex service returns them; OMK does not infer a missing 5-hour value from a 7-day value.
29
30
 
30
- Alibaba Model Studio Token Plan is recognized as **QWEN TOKEN PLAN** but shows `console-only quota`. Its [official usage page](https://modelstudio.console.alibabacloud.com/ap-southeast-1?tab=plan&commonbuy=1&orderType=buy#/efm/subscription/token-plan) obtains `per5HourPercentage`, `per5HourResetTime`, `per1WeekPercentage`, and `per1WeekResetTime` through an authenticated Alibaba Cloud console gateway. The plan-specific `sk-sp-*` key does not authorize that console endpoint, and compatible-mode model responses expose token counts but no quota headers. OMK therefore does not copy browser cookies or estimate quota from token counts. Qwen OAuth and Grok remain explicit `quota API unavailable`.
31
+ Alibaba Model Studio Token Plan is recognized as **QWEN TOKEN PLAN** but shows `console-only quota`. Its [official usage page](https://modelstudio.console.alibabacloud.com/ap-southeast-1?tab=plan&commonbuy=1&orderType=buy#/efm/subscription/token-plan) obtains `per5HourPercentage`, `per5HourResetTime`, `per1WeekPercentage`, and `per1WeekResetTime` through an authenticated Alibaba Cloud console gateway. The plan-specific `sk-sp-*` key does not authorize that console endpoint, and compatible-mode model responses expose token counts but no quota headers. OMK therefore does not copy browser cookies or estimate quota from token counts. Qwen OAuth remains explicit `quota API unavailable`.
32
+
33
+ With a stored native `xai` OAuth credential, OMK reads `GET https://cli-chat-proxy.grok.com/v1/billing?format=credits` and shows the weekly SuperGrok pool from `config.creditUsagePercent` plus its reset from `config.currentPeriod.end`. `XAI_API_KEY` is a separate API-billing credential and does not authorize this subscription endpoint.
31
34
 
32
35
  ### OpenAI Codex
33
36
 
@@ -49,9 +52,11 @@ Anthropic subscription auth is active for Claude Pro/Max accounts. Third-party h
49
52
  - Press Enter for github.com, or enter your GitHub Enterprise Server domain
50
53
  - If you get "model not supported", enable it in VS Code: Copilot Chat → model selector → select model → "Enable"
51
54
 
52
- ### Grok harness presets
55
+ ### xAI Grok
56
+
57
+ Both authentication modes use the built-in `xai` provider. Run `/login` for subscription OAuth, or set `XAI_API_KEY` for xAI Platform API billing. Do not configure a second Grok provider.
53
58
 
54
- For `grok-oauth-proxy` project presets, Composer routing, and Imagine tool guidance, see [Grok harness](grok-harness.md).
59
+ For project presets, Imagine guidance, and the exact `grok-4.6`, `grok-4.5`, and `grok-4.3` thinking mappings, see [Grok harness](grok-harness.md).
55
60
 
56
61
  ## API Keys
57
62
 
@@ -99,6 +104,10 @@ omk
99
104
 
100
105
  Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/dmae97/omk/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/dmae97/omk/blob/main/packages/ai/src/env-api-keys.ts).
101
106
 
107
+ #### NVIDIA NIM
108
+
109
+ Set `NVIDIA_API_KEY` and select an NVIDIA model with `/model`. The built-in `nvidia/z-ai/glm-5.2` entry sends `reasoning_effort`, including the `max` level. Other NVIDIA models keep conservative compatibility defaults unless their model metadata explicitly enables reasoning effort.
110
+
102
111
  #### Zyloo
103
112
 
104
113
  Zyloo is an OpenAI-compatible unified API gateway. Set `ZYLOO_API_KEY` and use any Zyloo-hosted model:
@@ -0,0 +1,104 @@
1
+ # OMK Run Protocol v1
2
+
3
+ The OMK Run Protocol defines one versioned contract for task execution and evaluation:
4
+
5
+ ```text
6
+ TaskSpec -> ExecutionAttempt -> Observation -> EvaluationResult -> RuntimeDecision
7
+ ```
8
+
9
+ `omk-protocol` owns these records and the pure reducers that connect them. Tool execution, persistence, scheduling, routing, and topology remain outside the package.
10
+
11
+ ## Implemented scope
12
+
13
+ The first v1 slice is available under `packages/protocol` with schema version `omk.run.v1`.
14
+
15
+ | Contract | Purpose |
16
+ | --- | --- |
17
+ | `TaskSpec` | Goal and required or advisory `ClaimPredicate` records |
18
+ | `ExecutionAttempt` | One completed initial, retry, failover, or resumed execution |
19
+ | `Observation` | Immutable facts tied to a task and attempt |
20
+ | `ClaimEvaluation` | Derived `satisfied`, `violated`, or `inconclusive` claim result |
21
+ | `EvaluationResult` | Claim evaluations plus one semantic `pass`, `fail`, or `inconclusive` verdict |
22
+ | `RuntimeDecision` | Pure `continue`, `retry`, `failover`, or `stop` decision |
23
+ | `WaiverRecord` | Explicit, scoped, attributable, and optionally expiring exception |
24
+
25
+ Every top-level record carries `schemaVersion`. Parsers reject unsupported versions, malformed timestamps, duplicate claim IDs, invalid JSON facts, and empty logical conditions.
26
+
27
+ ## Durable goal lifecycle
28
+
29
+ A durable goal is working-directory state, not a session-file field or a `TaskSpec`. `/goal <objective>` creates or edits `.omk/goals/current.json`; `/goal` without arguments shows its status and round count.
30
+
31
+ Goals created by `/goal` use an eight-round cap. The controller queues another turn only while the goal is active, no message is pending, and the cap has not been reached. Reaching the cap stops automatic continuation; the controller does not infer or mark completion.
32
+
33
+ For programmatic lifecycle control, import `createDurableGoal`, `parseDurableGoalSnapshot`, `applyDurableGoalCommand`, and `DurableGoalStore` from `open-multi-agent-kit`. The reducer supports edit, pause, resume, block, round advancement, evidence attachment, completion, and clear transitions.
34
+
35
+ Every mutation consumes the current revisioned `GoalRef`; stale revisions are rejected. Editing the objective or round limit, or advancing a round, starts a new semantic generation and invalidates earlier completion evidence. Completion requires lowercase SHA-256 evidence captured during the current generation.
36
+
37
+ ### Seam checkpoints
38
+
39
+ A durable goal can carry one bounded `Goal / Core / Verified / Open / Next` seam checkpoint. The checkpoint is another revision in `.omk/goals/current.json`, not a separate state tree. It is bound to the goal generation and referenced evidence IDs, forced-redacted before persistence, and correlated by a content digest. The digest is unkeyed: it detects accidental mismatch but does not authenticate workspace state against a same-user editor.
40
+
41
+ Use the interactive command with strict JSON:
42
+
43
+ ```text
44
+ /goal checkpoint {"core":["Keep deterministic gates authoritative"],"verified":["focused-tests"],"open":["Historical calibration"],"next":"Run the package checks"}
45
+ ```
46
+
47
+ `verified` may name only fresh evidence already attached to the current goal generation. A round advance carries the checkpoint record forward but does not make its evidence current-round proof. The built-in controller injects checkpoint prose only when the user recorded it through `/goal checkpoint` in the current process. A checkpoint loaded from mutable workspace state is noted by digest and its prose is not promoted to user authority. Editing the objective or round limit clears it. The session stores only a `goal_checkpoint` entry containing the goal ID, revision, and checkpoint digest; complete content remains in the existing durable-goal journal.
48
+
49
+ Programmatic callers use the `record-checkpoint` command with `applyDurableGoalCommand()` or `DurableGoalStore.transition()`. `parseDurableGoalCheckpointCommand()` parses the interactive JSON shape; `formatDurableGoalCheckpoint()` renders the five fields.
50
+
51
+ ## Evaluation model
52
+
53
+ `evaluateTask()` is a pure `TaskSpec + ExecutionAttempt + Observation[] + WaiverRecord[] -> EvaluationResult` reducer. It does not mutate its inputs or stored evidence.
54
+
55
+ An observation condition selects facts by observation kind and task or attempt scope. Its expected facts are a recursive object subset; arrays match exactly.
56
+
57
+ - no candidate observation: `inconclusive`
58
+ - candidate with matching facts: `satisfied`
59
+ - candidates present but none match: `violated`
60
+ - `all`, `any`, and `not` compose conditions without adding evaluator state
61
+
62
+ Required, unwaived violations reduce to `fail`. Required, unwaived missing observations reduce to `inconclusive`. Otherwise the semantic verdict is `pass`. Advisory claims are reported but do not block. A task with no required claims is `inconclusive`.
63
+
64
+ `reduceRuntimeDecision()` then maps the semantic verdict through an explicit runtime policy. `pass` always stops successfully; fail and inconclusive behavior is supplied as `onFail` and `onInconclusive`. Retry and failover counters are not fields: consumers derive them from `ExecutionAttempt` records.
65
+
66
+ ### Advisory best-of-N judge
67
+
68
+ `chooseWithAdvisoryJudge()` is an optional selection sidecar, not a protocol verdict producer. It validates each `EvaluationResult`, admits only candidates whose semantic verdict is `pass`, and lets a judge score only that eligible set. Zero eligible candidates produce no selection; one skips the model; multiple candidates use weighted 0–4 rubric scores.
69
+
70
+ Candidate material, the task goal, and rubric descriptions are forced-redacted and bounded before the judge receives them. The model adapter uses a tool-free prompt, treats candidate text as untrusted data, disables retries and cache retention, and accepts only a complete matrix of known candidate and criterion IDs. A provider error, timeout, malformed JSON, unknown ID, or incomplete score matrix selects the existing deterministic first choice and reports a sanitized fallback reason.
71
+
72
+ The sidecar never creates an `Observation`, changes `EvaluationResult.semanticVerdict`, supplies independent-verifier evidence, waives a claim, or changes `RuntimeDecision`. Run fresh tests, integrity checks, security gates, and evidence freshness checks after applying the selected candidate.
73
+
74
+ ## Waivers
75
+
76
+ A waiver names one task and claim, the approver, approval time, rationale, and evidence references. It may be limited to one attempt and may expire. Evaluation fails closed for cross-task, unknown-claim, future-approved, expired, duplicate, or advisory-claim waivers. The underlying claim result remains visible; `waiverId` records why it did not block.
77
+
78
+ ## EvidenceReceipt v3 bridge
79
+
80
+ `EvidenceReceipt v3` remains the integrity layer. `evidenceReceiptToObservation()` from `open-multi-agent-kit` validates the immutable core digest, then projects only execution facts into an `Observation`:
81
+
82
+ - receipt schema version and claim text
83
+ - exit code, timeout flag, and abort flag
84
+ - duration and executor
85
+ - a digest-bound receipt reference
86
+
87
+ The adapter deliberately omits the legacy mutable evidence status. Receipt digest validation does not prove ledger membership, trusted attestation, runner honesty, freshness, or OS isolation; apply those checks separately before trusting the observation.
88
+
89
+ ```typescript
90
+ import { evaluateTask, reduceRuntimeDecision } from "omk-protocol";
91
+ import { evidenceReceiptToObservation } from "open-multi-agent-kit";
92
+ ```
93
+
94
+ The legacy `TaskContract`, `EvidenceStatus`, `TaskContractBuilder.setVerdict()`, and `updateEvidenceStatus()` remain for compatibility and are deprecated. New code should append observations and recompute evaluation.
95
+
96
+ ## Authority boundaries
97
+
98
+ This slice does not change runtime ownership:
99
+
100
+ - the coding-agent still owns provider retry and failover execution;
101
+ - AdaptOrch WPL still owns its existing work-packet state machine and adjudication types;
102
+ - scheduler and router separation, topology validation, background-task durability, and algorithm-isolation work remain follow-up migrations.
103
+
104
+ Those components should consume `omk-protocol` rather than define new task, attempt, observation, or semantic-verdict types.
package/docs/sdk.md CHANGED
@@ -14,6 +14,19 @@ The SDK provides programmatic access to omk's agent capabilities. Use it to embe
14
14
 
15
15
  See [examples/sdk/](../examples/sdk/) for working examples from minimal to full control.
16
16
 
17
+ ## Inspect persisted sessions from the CLI
18
+
19
+ Use `omk sdk session` to inspect or append to stored JSONL sessions without starting the TUI:
20
+
21
+ ```bash
22
+ omk sdk session status [id] [--cwd <path>] [--session-dir <path>] [--json]
23
+ omk sdk session tail [id] [--cwd <path>] [--session-dir <path>] [--limit <n>]
24
+ omk sdk session inspect [id] [--cwd <path>] [--session-dir <path>]
25
+ omk sdk session send <id> "<message>" [--cwd <path>] [--session-dir <path>]
26
+ ```
27
+
28
+ `status` without an ID lists sessions for the selected working directory. `tail` and `inspect` without an ID select the most recently modified session; `tail` defaults to 20 entries. `send` requires an exact ID, appends a user-message entry only when the session has no active owner, and does not wake or execute an agent. `status` is human-readable unless `--json` is passed; the other actions emit JSON. Exit codes are `0` for success, `1` when no target exists or the session is active, and `2` for invalid usage.
29
+
17
30
  ## Quick Start
18
31
 
19
32
  ```typescript
@@ -134,6 +147,20 @@ interface AgentSession {
134
147
 
135
148
  Session replacement APIs such as new-session, resume, fork, and import live on `AgentSessionRuntime`, not on `AgentSession`.
136
149
 
150
+ ### AgentSession policy seams
151
+
152
+ The package root exports focused policy helpers for custom runtimes and tests:
153
+
154
+ | Exports | Purpose |
155
+ | --- | --- |
156
+ | `shouldSkipCompactionCheck`, `isSessionModelOverflow` | Compaction eligibility and overflow ownership |
157
+ | `isRetryableAssistantError`, `nextRetryAttempt`, `computeRetryDelayMs`, `isFailoverTriggerError`, `failoverModelKey` | Retry and failover decisions |
158
+ | `computePromptTokenBudget`, `computeResponseReserveTokens` | Prompt and response token budgets |
159
+ | `classifyPromptCacheTransition` | Cache establishment, reuse, change, or bypass |
160
+ | `assembleSessionSystemPrompt` | System-prompt options, text, and cache boundary |
161
+
162
+ The decision and arithmetic helpers perform no I/O. `assembleSessionSystemPrompt()` delegates to the system-prompt planner, which incorporates the current date and installation paths.
163
+
137
164
  ### createAgentSessionRuntime() and AgentSessionRuntime
138
165
 
139
166
  Use the runtime API when you need to replace the active session and rebuild cwd-bound runtime state.
@@ -216,6 +243,8 @@ const executor = new VerifiedEvidenceExecutor({ store, ledger });
216
243
 
217
244
  `transcript_repaired`, `tool_timeout`, `tool_late_settlement`, and `workspace_mutation` use that ledger. A receipt at or before a later relevant workspace mutation is blocked by `EvidenceGate`.
218
245
 
246
+ New replay events declare `payloadHashAlgorithm: "jcs-rfc8785-v2"`; payload keys are canonicalized with RFC 8785 before SHA-256 hashing, and the algorithm identifier is part of the event-hash commitment. Existing events with no algorithm are verified with the original `json-stringify-v1` contract. Loading, appending to, replaying, or exporting a mixed ledger does not rewrite or relabel those legacy events. Unknown declared algorithms fail closed.
247
+
219
248
  ### Prompting and Message Queueing
220
249
 
221
250
  `PromptOptions` controls prompt expansion, queueing behavior while streaming, and prompt preflight notifications:
@@ -374,6 +403,8 @@ session.subscribe((event) => {
374
403
  });
375
404
  ```
376
405
 
406
+ `session_termination` is emitted per provider attempt, not only when the outer `prompt()` call stops. If `auto_retry_start` follows a retryable termination, wait for the recovered attempt; `session.lastTermination` is updated to the later `completed` result on success.
407
+
377
408
  ## Options Reference
378
409
 
379
410
  ### Directories
@@ -530,10 +561,12 @@ The `edit` tool returns `details.diff` for OMK's TUI display and `details.patch`
530
561
 
531
562
  The `diagnostics` tool runs the project's own checkers and normalizes the result — `tsc --noEmit` for TypeScript, `pyright`/`ruff` for Python, `go vet` for Go, `cargo check` for Rust. Missing checkers or project markers are reported as `skipped` in the tool result instead of failing. Output is capped at 50 diagnostics and cached for 5 s.
532
563
 
564
+ With default OMP seams, truncated `read` output does not create a sidecar. With `OMK_OMP_SEAMS=0`, legacy truncation may write the selected window to `<absolute-source-path>.omk-spill.txt`; `ReadToolDetails.fullOutputPath` reports the path when present. A first line that alone exceeds the byte cap is clipped without a sidecar. The exported `spillTruncatedOutput()` helper provides the preview-plus-path contract for custom tools.
565
+
533
566
  ```typescript
534
567
  import { createAgentSession } from "open-multi-agent-kit";
535
568
 
536
- // Read-only mode
569
+ // Enable inspection tools; legacy read mode may create a spill sidecar
537
570
  const { session } = await createAgentSession({
538
571
  tools: ["read", "grep", "find", "ls"],
539
572
  });
@@ -1155,9 +1188,11 @@ Execution-bound evidence records a declared verification command and reported ou
1155
1188
 
1156
1189
  **Default path (opt-out):** when an AgentSession has a replay ledger (persisted sessions create one automatically), LLM-callable `bash` and interactive/RPC `executeBash` bind through `executeVerifiedBash` with `executor: "bash-tool"` and receipts under `<sessionFile>.evidence/receipts` (or `cwd/.omk/session-evidence/<goalId>/receipts` for ephemeral sessions). Session workspace scope is git-aware: inside a worktree, the receipt binds the toplevel plus up to 32 sorted dirty file paths (1 s TTL). Git status expands ordinary untracked directories to files; untracked nested repositories remain outside the parent scope. Set `OMK_VERIFIED_BASH=0` to restore the legacy unverified path. Custom `createBashTool()` calls stay unverified unless the caller wraps operations with `createVerifiedBashOperations()`. CI still runs release-consistency through `executeVerifiedLocalBash()` with `executor: "ci-runner"`.
1157
1190
 
1158
- **Default sandbox (opt-out):** session bash defaults to `enforce`. Every built-in local spawn is wrapped by macOS `sandbox-exec` or Linux `bwrap`, writes are limited to the session workspace and OS temp directory, and network access is disabled. If the platform is unsupported or the backend is unavailable, the spawn fails closed with `sandbox.backend_missing`. Set `OMK_BASH_SANDBOX=audit` only for an unwrapped compatibility path that records each decision as a `sandbox_audit` replay event; set `OMK_BASH_SANDBOX=0` to disable the preflight entirely. Unknown values resolve to `enforce`.
1191
+ **Default AgentSession sandbox (opt-out):** built-in local bash defaults to `enforce`. Local spawns use macOS `sandbox-exec` or Linux `bwrap`, writes are limited to the session workspace and OS temp directory, and network access is disabled. Unsupported platforms and unavailable backends fail closed with `sandbox.backend_missing`. Explicit `audit` keeps the unwrapped ledger-only path; `0` or `off` disables the preflight. Unknown values resolve to `enforce`.
1159
1192
 
1160
- This boundary applies to AgentSession's built-in local bash operations. Custom `createBashTool()` calls remain unsandboxed unless they receive a `sandboxPolicy`, and injected or remote `BashOperations` own their own isolation. The default workspace-write profile is not a read-confidentiality boundary or whole-process container; use [Containerization](containerization.md) when every tool and extension must be isolated.
1193
+ Automatic backend probing is lazy and cached. An AgentSession probes at most once during its lifetime; each `createLocalBashOperations({ sandboxPolicy })` instance also probes at most once when its preflight omits `backend`. The denial reason identifies missing `bwrap` or `sandbox-exec`, disabled user namespaces, both Linux failures, or an unsupported platform.
1194
+
1195
+ This boundary applies only to AgentSession's built-in local bash operations. Custom `createBashTool()` calls remain unsandboxed unless they receive a `sandboxPolicy`; injected or remote `BashOperations` own their isolation. The profile is not read-confidentiality or whole-process containment. `executeVerifiedLocalBash()` remains an evidence adapter, not an OS sandbox. See [Containerization](containerization.md).
1161
1196
 
1162
1197
  ### Recorded and invoked inputs
1163
1198
 
@@ -1212,9 +1247,72 @@ Ledger and receipt publication are fail-closed but not one filesystem transactio
1212
1247
  - **Ledger**: `ReplayLedgerManager` verifies an existing ledger on construction (sequence order, prev-hash chain, payload hash, event hash) and **fails closed** on any violation.
1213
1248
  - **Store**: `EvidenceReceiptStore` uses an owner-only directory, symlink rejection, no-overwrite hard-link publication, and identity rechecks to detect observed path replacement. These checks assume same-UID path mutation is quiescent; they are **not** filesystem sandbox isolation.
1214
1249
 
1250
+ ### Protocol-first semantic evaluation
1251
+
1252
+ New integrations should use `TaskSpec`, `ExecutionAttempt`, `Observation`, `EvaluationResult`, `RuntimeDecision`, and `WaiverRecord` from `omk-protocol`. `evaluateTask()` derives the semantic verdict from current observations; `reduceRuntimeDecision()` derives the next runtime action. See [Run Protocol v1](run-protocol.md) for the rules and current migration boundary.
1253
+
1254
+ `evidenceReceiptToObservation(receipt, attemptId)` validates the receipt core digest and emits immutable execution facts for protocol evaluation. It does not replace ledger, attestation, freshness, or sandbox checks.
1255
+
1256
+ ### Advisory best-of-N selection
1257
+
1258
+ Use the advisory judge only after deterministic evaluation. `chooseWithAdvisoryJudge()` validates every `EvaluationResult` and excludes `fail` and `inconclusive` candidates before any model call. The judge cannot revive them or alter protocol, evidence, loop, or security gates.
1259
+
1260
+ ```typescript
1261
+ import {
1262
+ chooseWithAdvisoryJudge,
1263
+ createModelAdvisoryJudge,
1264
+ } from "open-multi-agent-kit";
1265
+
1266
+ const model = modelRegistry.find("xai", "grok-4.5");
1267
+ if (!model) throw new Error("judge model is not registered");
1268
+
1269
+ const judge = createModelAdvisoryJudge({ model, modelRegistry });
1270
+ const decision = await chooseWithAdvisoryJudge({
1271
+ taskGoal: task.goal,
1272
+ judgeId: "reviewer-v1",
1273
+ judge,
1274
+ rubric: [
1275
+ { id: "correctness", description: "Satisfies required behavior and evidence", weight: 3 },
1276
+ { id: "safety", description: "Preserves security and deterministic gates", weight: 2 },
1277
+ ],
1278
+ candidates: [
1279
+ { id: "attempt-a", deterministicRank: 0, material: outputA, evaluation: evaluationA },
1280
+ { id: "attempt-b", deterministicRank: 1, material: outputB, evaluation: evaluationB },
1281
+ ],
1282
+ });
1283
+ ```
1284
+
1285
+ The sidecar makes no call when zero or one candidate passes. For multiple passing candidates it sends only bounded, forced-redacted material through a tool-free request and requires a complete 0–4 score matrix. Invalid output or provider failure returns `status: "fallback"` with the deterministic first candidate and a sanitized reason. It never persists model prose. Re-run fresh deterministic gates after applying the selected result.
1286
+
1287
+ `createModelAdvisoryJudge()` resolves current auth through `ModelRegistry` for each explicit call, uses no cache retention, and performs no model retry. Tests can inject `AdvisoryJudgeCompletion`; production defaults to `completeSimple()`.
1288
+
1289
+ ### Durable-goal seam checkpoints
1290
+
1291
+ Use the existing durable-goal journal for `Goal / Core / Verified / Open / Next` continuity:
1292
+
1293
+ ```typescript
1294
+ const current = await goalStore.current();
1295
+ if (!current) throw new Error("durable goal is missing");
1296
+
1297
+ const now = new Date().toISOString();
1298
+ const checkpointed = await goalStore.transition({
1299
+ kind: "record-checkpoint",
1300
+ ref: current.ref,
1301
+ checkpoint: {
1302
+ core: ["Keep the protocol verdict authoritative"],
1303
+ verifiedEvidenceIds: ["focused-tests"],
1304
+ open: ["Historical calibration"],
1305
+ next: "Run the full package checks",
1306
+ capturedAt: now,
1307
+ },
1308
+ }, now);
1309
+ ```
1310
+
1311
+ The reducer rejects stale refs and evidence outside the current generation. Text is bounded and forced-redacted before persistence; the checkpoint digest correlates its content and generation but is unkeyed and does not authenticate a same-user workspace. `/goal checkpoint {"core":[],"verified":[],"open":[],"next":"..."}` exposes the same transition interactively. The built-in controller carries prose into the next round only for a checkpoint explicitly recorded through that command in the current process. On resume, mutable workspace checkpoint prose is not promoted to user authority; only its digest is noted. Editing the goal definition clears the checkpoint. No `.jspace/` or second state system is created.
1312
+
1215
1313
  ### Receipt policy
1216
1314
 
1217
- `EvidenceGate` (default `receiptMode: "prefer"`) gates a `TaskContract` against its satisfied receipts. Pass `executor.createGateOptions()` so the gate resolves receipts, ledger events, and workspace fingerprints from the same store and ledger.
1315
+ `EvidenceGate` (default `receiptMode: "prefer"`) gates the legacy `TaskContract` against its satisfied receipts. Pass `executor.createGateOptions()` so the gate resolves receipts, ledger events, and workspace fingerprints from the same store and ledger.
1218
1316
 
1219
1317
  | Mode | Soft missing data | Tamper-grade mismatch | Legacy `hash` / `command` |
1220
1318
  | ------ | ------------------- | ----------------------- | ---------------------------- |
@@ -1228,7 +1326,9 @@ Tamper-grade mismatches include: receipt ID, goal, or claim mismatch; schema ver
1228
1326
 
1229
1327
  `createGateOptions()` returns three resolvers bound to the executor's own store and ledger: `resolveReceipt` (read a stored receipt), `resolveLedgerEvent` (find a chain event by `seq`), and `captureWorkspaceFingerprint` (snapshot the selected artifact set). The gate validates every returned value.
1230
1328
 
1231
- ### Integration example
1329
+ ### Legacy gate integration example
1330
+
1331
+ This compatibility path still uses mutable `TaskContract` evidence status and verdict fields. `TaskContractBuilder.setVerdict()` and `updateEvidenceStatus()` are deprecated for new integrations.
1232
1332
 
1233
1333
  ```typescript
1234
1334
  import {
@@ -1324,11 +1424,17 @@ createContextCacheInvalidationSnapshot, serializeContextCacheSnapshot,
1324
1424
  CONTEXT_BUDGET_POLICY_VERSION_V2
1325
1425
  computeReservedTokenBudget, estimateToolResultReserve, ReservedTokenBudgetError
1326
1426
 
1427
+ // Advisory selection and durable goals
1428
+ chooseWithAdvisoryJudge, createModelAdvisoryJudge, AdvisoryJudgeInputError, AdvisoryJudgeModelError
1429
+ createDurableGoal, applyDurableGoalCommand, parseDurableGoalSnapshot, DurableGoalStore
1430
+ createDurableGoalCheckpoint, parseDurableGoalCheckpoint, formatDurableGoalCheckpoint
1431
+
1327
1432
  // Run journal and session termination
1328
1433
  RunJournalStore, appendRunJournalRecordDurably, writeQuarantineBytesDurably,
1329
1434
  classifySessionTermination, formatSessionTermination, SessionTerminationError
1330
1435
 
1331
1436
  // Execution-bound evidence (optional, application-driven verification receipts)
1437
+ evidenceReceiptToObservation
1332
1438
  EvidenceReceiptStore
1333
1439
  ReplayLedgerManager
1334
1440
  EvidenceGate
package/docs/security.md CHANGED
@@ -1,12 +1,12 @@
1
- # Extension Full-Access Threat Model
1
+ # Extension Runtime Threat Model
2
2
 
3
- > **Scope**: This document analyzes the security implications of OMK extensions that request `full-access` permissions. It applies to the OMK (Open Multi-Agent Kit) coding agent CLI and its extension runtime.
3
+ > **Scope**: This document covers every OMK extension. OMK does not currently provide extension permission tiers or an extension-specific OS sandbox.
4
4
  >
5
- > **Version**: 0.80.3
5
+ > **Version**: 0.96.1
6
6
 
7
7
  ## 1. Overview
8
8
 
9
- OMK extensions can operate at different permission levels. The `full-access` level grants an extension unrestricted access to the OMK runtime, including the ability to:
9
+ Extensions execute as trusted code inside the OMK process with the host user's permissions. Treat every loaded extension as capable of:
10
10
 
11
11
  - Read and modify the agent's configuration (`~/.omk/agent/`)
12
12
  - Intercept and mutate tool calls and their results
@@ -23,20 +23,20 @@ This document outlines the threat model for such extensions and provides guidanc
23
23
  | Malicious Extension Author | Data exfiltration, credential theft, supply-chain compromise | Distributes a seemingly benign extension with hidden malicious logic |
24
24
  | Compromised Extension Dependency | Indirect compromise via a dependency of a legitimate extension | Injects malicious code into a trusted extension's dependency tree |
25
25
  | Insider Threat | Espionage, sabotage, unauthorized data access | Installs or modifies an extension on a target's machine |
26
- | User (Self-Inflicted) | Accidental misconfiguration | Grants `full-access` to an untrusted extension without review |
26
+ | User (Self-Inflicted) | Accidental misconfiguration | Loads an untrusted extension without review |
27
27
 
28
28
  ## 3. Attack Scenarios
29
29
 
30
30
  ### 3.1 Configuration Exfiltration
31
31
 
32
- A `full-access` extension can read `~/.omk/agent/auth.json`, which contains API keys and OAuth tokens for LLM providers (e.g., `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`).
32
+ An extension can read `~/.omk/agent/auth.json`, which contains API keys and OAuth tokens for LLM providers.
33
33
 
34
34
  **Impact**: Credential theft leading to unauthorized LLM API usage, financial loss, or data leakage through the compromised API account.
35
35
 
36
36
  **Mitigation**:
37
37
  - Store auth credentials in OS keychain or encrypted vault rather than plaintext `auth.json` where possible.
38
- - Audit extensions before granting `full-access`.
39
- - Run extensions with restricted permissions if full access is not strictly required.
38
+ - Audit extensions before loading them.
39
+ - Run the whole OMK process inside an isolated environment when the extension is not fully trusted.
40
40
 
41
41
  ### 3.2 Session Hijacking
42
42
 
@@ -51,7 +51,7 @@ A malicious extension can intercept session `.jsonl` files in `~/.omk/agent/sess
51
51
 
52
52
  ### 3.3 Tool Call Interception and Mutation
53
53
 
54
- Extensions with `full-access` can wrap built-in tools (e.g., `bash`, `read`, `write`). A malicious wrapper could:
54
+ Extensions can wrap built-in tools (e.g., `bash`, `read`, `write`). A malicious wrapper could:
55
55
  - Log all `bash` commands and their outputs to a remote server.
56
56
  - Modify `write` tool calls to inject backdoors into source files.
57
57
  - Block `read` operations on sensitive files to hide evidence of tampering.
@@ -59,19 +59,19 @@ Extensions with `full-access` can wrap built-in tools (e.g., `bash`, `read`, `wr
59
59
  **Impact**: Supply-chain compromise, data integrity loss, covert surveillance.
60
60
 
61
61
  **Mitigation**:
62
- - Use the `--no-extensions` flag when working with highly sensitive codebases.
62
+ - Use `--no-extensions` to disable discovered third-party extensions when working with highly sensitive codebases.
63
63
  - Pin extension versions and review diffs on updates.
64
64
  - Run extensions in an isolated environment (container, VM) where feasible.
65
65
 
66
66
  ### 3.4 Privilege Escalation via Custom Tools
67
67
 
68
- A `full-access` extension can register new tools that appear in the agent's tool list. These tools execute with the same privileges as the OMK process.
68
+ An extension can register new tools that appear in the agent's tool list. These tools execute with the same privileges as the OMK process.
69
69
 
70
70
  **Impact**: Arbitrary code execution, system compromise if the agent process has elevated privileges.
71
71
 
72
72
  **Mitigation**:
73
73
  - Never run OMK as root or with sudo.
74
- - Use OS-level sandboxing (e.g., `sandbox-exec` on macOS, `seccomp` on Linux) for the OMK process.
74
+ - Run the whole OMK process in a container, VM, or other verified OS sandbox when containment is required.
75
75
  - Review the full source code of any extension before installation.
76
76
 
77
77
  ### 3.5 Telemetry and Data Leakage
@@ -83,40 +83,30 @@ Extensions can silently exfiltrate data via DNS queries, HTTP requests, or by wr
83
83
  **Mitigation**:
84
84
  - Block outbound network access for the OMK process using a firewall or network namespace.
85
85
  - Monitor DNS and network traffic for anomalies.
86
- - Use offline mode (`--offline`) when extensions are not required to fetch remote resources.
86
+ - Do not treat `--offline` as a network sandbox; it disables OMK startup network operations, not arbitrary extension traffic.
87
87
 
88
- ## 4. Default Sandbox Path
88
+ ## 4. Actual Isolation Boundary
89
89
 
90
- OMK provides a default sandbox path for extensions that do not explicitly request `full-access`. This path restricts the extension to:
90
+ OMK does not sandbox extension JavaScript separately. Extension code, extension tools, custom code, and the OMK process run with the host user's permissions.
91
91
 
92
- - A dedicated subdirectory under `~/.omk/agent/extensions/<extension-name>/`
93
- - Read-only access to the project workspace (current working directory)
94
- - No access to `~/.omk/agent/auth.json`, `~/.omk/agent/mcp.json`, or session files
95
- - No network access (unless explicitly granted via extension manifest)
96
-
97
- **Default Sandbox Directory**: `~/.omk/agent/extensions/<extension-id>/`
98
-
99
- Extensions operating within this sandbox cannot:
100
- - Access files outside the project workspace and their own extension directory.
101
- - Intercept tool calls from other extensions or the core agent.
102
- - Read or write global agent configuration.
92
+ AgentSession's built-in local bash sandbox wraps only built-in local bash child processes. It does not contain extension callbacks, custom tools, OMK file tools, or the OMK process. For broader isolation, run the whole process inside a container or VM, or route every relevant tool through an isolated backend. See [Containerization](containerization.md).
103
93
 
104
94
  ## 5. Security Checklist for Users
105
95
 
106
- Before installing or upgrading a `full-access` extension, verify:
96
+ Before installing or upgrading an extension, verify:
107
97
 
108
98
  - [ ] The extension source code is available and has been reviewed.
109
99
  - [ ] The extension is from a trusted author or has been audited by a third party.
110
100
  - [ ] The extension's `package.json` or manifest does not include unexpected dependencies.
111
- - [ ] The extension's network permissions (if any) are justified by its functionality.
101
+ - [ ] The extension's network behavior is justified by its functionality.
112
102
  - [ ] You have a backup of `~/.omk/agent/` (especially `auth.json` and sessions).
113
103
  - [ ] You have considered running the extension in a sandboxed environment.
114
104
 
115
105
  ## 6. Security Checklist for Extension Developers
116
106
 
117
- When building a `full-access` extension, adhere to:
107
+ When building an extension, adhere to:
118
108
 
119
- - [ ] **Principle of Least Privilege**: Only request `full-access` if absolutely necessary. Use the default sandbox for everything else.
109
+ - [ ] **Principle of Least Privilege**: Keep the extension's file, process, network, and credential access to the minimum required, even though OMK does not enforce a per-extension tier.
120
110
  - [ ] **No Credential Access**: Never read `auth.json` or environment variables containing API keys unless the extension's core purpose is authentication management.
121
111
  - [ ] **Transparent Logging**: Log all file system and network operations to a user-visible location.
122
112
  - [ ] **Minimal Dependencies**: Keep the dependency tree small to reduce supply-chain risk.
@@ -125,7 +115,7 @@ When building a `full-access` extension, adhere to:
125
115
 
126
116
  ## 7. Incident Response
127
117
 
128
- If a malicious or compromised `full-access` extension is suspected:
118
+ If a malicious or compromised extension is suspected:
129
119
 
130
120
  1. **Immediately revoke** any exposed API keys (check `auth.json` and provider dashboards).
131
121
  2. **Remove** the extension directory from `~/.omk/agent/extensions/`.
@@ -142,4 +132,4 @@ If a malicious or compromised `full-access` extension is suspected:
142
132
 
143
133
  ---
144
134
 
145
- *Last updated: 2026-06-25*
135
+ *Last updated: 2026-08-19*