open-multi-agent-kit 0.79.3 → 0.80.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.
- package/CHANGELOG.md +22 -0
- package/MATURITY.md +2 -2
- package/README.md +86 -39
- package/ROADMAP.md +20 -17
- package/dist/brand/night-city.theme.json +122 -24
- package/dist/brand/rust-forge.theme.json +1 -1
- package/dist/commands/chat/native-root-loop.d.ts +27 -3
- package/dist/commands/chat/native-root-loop.js +375 -49
- package/dist/commands/dag.js +45 -0
- package/dist/commands/init/content.d.ts +1 -1
- package/dist/commands/init/content.js +3 -3
- package/dist/commands/init.js +3 -3
- package/dist/commands/verify.js +59 -1
- package/dist/contracts/dag.d.ts +9 -1
- package/dist/evidence/graph-ontology-relation-gate.d.ts +10 -0
- package/dist/evidence/graph-ontology-relation-gate.js +46 -0
- package/dist/evidence/headroom-replay-verifier.d.ts +19 -0
- package/dist/evidence/headroom-replay-verifier.js +86 -0
- package/dist/memory/local-graph-memory-store.d.ts +75 -0
- package/dist/memory/local-graph-memory-store.js +570 -0
- package/dist/orchestration/dag.d.ts +22 -1
- package/dist/orchestration/evidence-gate.js +12 -0
- package/dist/orchestration/executor.js +108 -15
- package/dist/orchestration/loop-controller-headroom.d.ts +6 -0
- package/dist/orchestration/loop-controller-headroom.js +33 -0
- package/dist/orchestration/scheduler.d.ts +2 -0
- package/dist/orchestration/scheduler.js +3 -0
- package/dist/orchestration/task-graph.d.ts +17 -0
- package/dist/orchestration/task-graph.js +38 -0
- package/dist/providers/codex-cli-runner.js +17 -2
- package/dist/runtime/agent-runtime.d.ts +32 -3
- package/dist/runtime/agent-runtime.js +20 -7
- package/dist/runtime/authority-matrix.d.ts +23 -0
- package/dist/runtime/authority-matrix.js +159 -0
- package/dist/runtime/chat-advisory-runtime.js +3 -0
- package/dist/runtime/codex-cli-runtime.js +2 -0
- package/dist/runtime/codex-runtime.d.ts +4 -1
- package/dist/runtime/codex-runtime.js +34 -12
- package/dist/runtime/context-broker-converter.js +32 -2
- package/dist/runtime/context-broker.js +18 -0
- package/dist/runtime/contracts/evidence.d.ts +52 -0
- package/dist/runtime/contracts/evidence.js +128 -1
- package/dist/runtime/contracts/shared.d.ts +27 -0
- package/dist/runtime/data-retention-gate.d.ts +42 -0
- package/dist/runtime/data-retention-gate.js +123 -0
- package/dist/runtime/deepseek-runtime.d.ts +5 -1
- package/dist/runtime/deepseek-runtime.js +13 -7
- package/dist/runtime/external-cli-adapter.js +20 -7
- package/dist/runtime/freedomd-evidence-envelope.d.ts +57 -0
- package/dist/runtime/freedomd-evidence-envelope.js +110 -0
- package/dist/runtime/freedomd-exception.d.ts +32 -0
- package/dist/runtime/freedomd-exception.js +95 -0
- package/dist/runtime/freedomd-incidents.d.ts +23 -0
- package/dist/runtime/freedomd-incidents.js +103 -0
- package/dist/runtime/freedomd-policy.d.ts +35 -0
- package/dist/runtime/freedomd-policy.js +114 -0
- package/dist/runtime/freedomd-router.d.ts +66 -0
- package/dist/runtime/freedomd-router.js +433 -0
- package/dist/runtime/headroom-aware-loop-decision.d.ts +21 -0
- package/dist/runtime/headroom-aware-loop-decision.js +67 -0
- package/dist/runtime/headroom-loop-risk.d.ts +19 -0
- package/dist/runtime/headroom-loop-risk.js +43 -0
- package/dist/runtime/headroom-policy.d.ts +14 -1
- package/dist/runtime/headroom-policy.js +74 -12
- package/dist/runtime/kimi-api-runtime.d.ts +4 -1
- package/dist/runtime/kimi-api-runtime.js +35 -11
- package/dist/runtime/kimi-print-runtime.js +21 -0
- package/dist/runtime/kimi-wire-protocol-runtime.js +17 -1
- package/dist/runtime/local-llm-runtime.d.ts +5 -1
- package/dist/runtime/local-llm-runtime.js +14 -23
- package/dist/runtime/private-stderr.d.ts +13 -0
- package/dist/runtime/private-stderr.js +69 -0
- package/dist/runtime/prompt-envelope.d.ts +1 -1
- package/dist/runtime/provider-sovereignty.d.ts +81 -0
- package/dist/runtime/provider-sovereignty.js +285 -0
- package/dist/runtime/runtime-backed-task-runner.d.ts +1 -0
- package/dist/runtime/runtime-backed-task-runner.js +282 -10
- package/dist/runtime/runtime-bootstrap.d.ts +12 -0
- package/dist/runtime/runtime-bootstrap.js +56 -3
- package/dist/runtime/runtime-failure-classifier.d.ts +15 -0
- package/dist/runtime/runtime-failure-classifier.js +107 -0
- package/dist/runtime/runtime-health-probes.d.ts +30 -0
- package/dist/runtime/runtime-health-probes.js +102 -0
- package/dist/runtime/runtime-router.d.ts +6 -2
- package/dist/runtime/runtime-router.js +575 -53
- package/dist/runtime/structured-compaction.d.ts +107 -0
- package/dist/runtime/structured-compaction.js +414 -0
- package/dist/runtime/tool-dispatch-contracts.d.ts +7 -5
- package/dist/runtime/tool-dispatch-contracts.js +15 -4
- package/dist/runtime/tool-plane.d.ts +1 -1
- package/dist/runtime/tool-plane.js +49 -1
- package/dist/runtime/worker-manifest.js +1 -1
- package/dist/schema/evidence-bundle.schema.d.ts +8 -8
- package/dist/schema/proof-bundle.schema.d.ts +2 -2
- package/dist/util/hash.d.ts +2 -0
- package/dist/util/hash.js +13 -0
- package/dist/util/session.js +6 -5
- package/docs/2026-06-16/critical-issues.md +19 -0
- package/docs/2026-06-16/improvements.md +15 -0
- package/docs/2026-06-16/init-checklist.md +25 -0
- package/docs/2026-06-16/plan.md +20 -0
- package/docs/ARCHITECTURE_ANALYSIS_CODEGRAPH.md +2 -1
- package/docs/GSTACK_MIGRATION.md +1 -1
- package/docs/algorithm-hardening-playbook.md +219 -0
- package/docs/claims.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/native-root-runtime-hardening.md +42 -32
- package/docs/post-0793-hardening-roadmap.md +123 -0
- package/docs/provider-maturity.md +18 -16
- package/docs/versioning.md +3 -3
- package/docs/what-is-omk.md +1 -1
- package/package.json +8 -4
- package/readmeasset/.npmignore +2 -0
- package/readmeasset/ASSET_INDEX.md +2 -0
- package/readmeasset/ASSET_PROVENANCE.md +40 -20
- package/readmeasset/omk-adaptorch-ouroboros-supermemory.svg +1 -1
- package/readmeasset/omk-control-surfaces.svg +1 -1
- package/readmeasset/omk-core-loop.svg +1 -1
- package/readmeasset/omk-freedomd-control-plane.svg +59 -0
- package/readmeasset/omk-freedomd-control-plane.webp +0 -0
- package/readmeasset/omk-init-control-loop.svg +1 -1
- package/readmeasset/omk-logo-mark.svg +1 -1
- package/readmeasset/omk-parallel-subagents.svg +1 -1
- package/readmeasset/omk-release-assertions.svg +1 -1
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider sovereignty scoring for Freedomd.
|
|
3
|
+
*
|
|
4
|
+
* Translates provider jurisdiction, retention, cutoff/portability, and locality
|
|
5
|
+
* properties into a normalized score that feeds runtime routing. The score is
|
|
6
|
+
* intentionally conservative: unknowns are treated as risk.
|
|
7
|
+
*/
|
|
8
|
+
import { runtimeProviderId, runtimeModeOf } from "./authority-matrix.js";
|
|
9
|
+
const EXPORT_POLICY_RISK = {
|
|
10
|
+
open: 0.0,
|
|
11
|
+
restricted: 0.4,
|
|
12
|
+
controlled: 0.8,
|
|
13
|
+
unknown: 0.6,
|
|
14
|
+
};
|
|
15
|
+
function clamp01(value) {
|
|
16
|
+
return Math.max(0, Math.min(1, value));
|
|
17
|
+
}
|
|
18
|
+
export function assessJurisdictionRisk(options) {
|
|
19
|
+
let risk = EXPORT_POLICY_RISK[options.exportPolicy] ?? 0.6;
|
|
20
|
+
if (options.userCountry && options.providerCountry !== options.userCountry) {
|
|
21
|
+
risk = Math.max(risk, 0.3);
|
|
22
|
+
}
|
|
23
|
+
if (options.taskRisk === "shell" || options.taskRisk === "merge") {
|
|
24
|
+
risk = Math.min(1, risk * 1.3 + 0.1);
|
|
25
|
+
}
|
|
26
|
+
const incident = (options.incidents ?? []).find((i) => i.kind === "export-control" || i.kind === "jurisdiction" || i.kind === "policy");
|
|
27
|
+
if (incident) {
|
|
28
|
+
const severityMultiplier = incident.severity === "block" ? 1.0 : incident.severity === "warn" ? 0.5 : 0.2;
|
|
29
|
+
risk = Math.min(1, risk + severityMultiplier * 0.3);
|
|
30
|
+
}
|
|
31
|
+
return clamp01(risk);
|
|
32
|
+
}
|
|
33
|
+
export function assessRetentionRisk(options) {
|
|
34
|
+
if (options.zeroDataRetention)
|
|
35
|
+
return 0.0;
|
|
36
|
+
if (!Number.isFinite(options.retentionDays) || options.retentionDays <= 0)
|
|
37
|
+
return 0.5;
|
|
38
|
+
let risk = clamp01(options.retentionDays / 365);
|
|
39
|
+
if (options.trainingUse) {
|
|
40
|
+
risk = Math.min(1, risk + 0.3);
|
|
41
|
+
}
|
|
42
|
+
if (options.maxRetentionDays !== undefined && options.maxRetentionDays >= 0) {
|
|
43
|
+
if (options.retentionDays > options.maxRetentionDays) {
|
|
44
|
+
risk = Math.min(1, risk + 0.4);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return risk;
|
|
48
|
+
}
|
|
49
|
+
export function assessCutoffRisk(options) {
|
|
50
|
+
let risk = 0;
|
|
51
|
+
risk += clamp01(options.policyInstabilityScore) * 0.35;
|
|
52
|
+
risk += clamp01(options.exportControlExposure) * 0.35;
|
|
53
|
+
risk += clamp01(options.accountDependency) * 0.30;
|
|
54
|
+
if (options.health?.available === false) {
|
|
55
|
+
risk = Math.min(1, risk + 0.5);
|
|
56
|
+
}
|
|
57
|
+
const incident = (options.incidents ?? []).find((i) => i.kind === "availability" || i.kind === "export-control" || i.kind === "policy");
|
|
58
|
+
if (incident) {
|
|
59
|
+
const bump = incident.severity === "block" ? 0.6 : incident.severity === "warn" ? 0.3 : 0.1;
|
|
60
|
+
risk = Math.min(1, risk + bump);
|
|
61
|
+
}
|
|
62
|
+
return clamp01(risk);
|
|
63
|
+
}
|
|
64
|
+
export function assessPortability(options) {
|
|
65
|
+
let score = 0.4;
|
|
66
|
+
if (options.supportsOpenApiCompat)
|
|
67
|
+
score += 0.25;
|
|
68
|
+
if (options.supportsToolContract)
|
|
69
|
+
score += 0.15;
|
|
70
|
+
if (options.supportsEvidenceReturn)
|
|
71
|
+
score += 0.20;
|
|
72
|
+
return clamp01(score);
|
|
73
|
+
}
|
|
74
|
+
export function computeProviderSovereigntyScore(runtime, task, options) {
|
|
75
|
+
const profile = options.profile;
|
|
76
|
+
const providerId = runtimeProviderId(runtime);
|
|
77
|
+
const runtimeMode = runtimeModeOf(runtime);
|
|
78
|
+
const incidents = (options.incidents ?? []).filter((i) => i.providerId === providerId &&
|
|
79
|
+
(!i.runtimeMode || i.runtimeMode === runtimeMode));
|
|
80
|
+
const jurisdictionRisk = assessJurisdictionRisk({
|
|
81
|
+
providerCountry: profile.providerCountry,
|
|
82
|
+
userCountry: options.userCountry,
|
|
83
|
+
taskRisk: options.taskRisk ?? task.safety?.risk,
|
|
84
|
+
exportPolicy: profile.exportPolicy,
|
|
85
|
+
incidents,
|
|
86
|
+
});
|
|
87
|
+
const retentionRisk = assessRetentionRisk({
|
|
88
|
+
retentionDays: profile.retentionDays,
|
|
89
|
+
zeroDataRetention: profile.zeroDataRetention,
|
|
90
|
+
trainingUse: profile.trainingUse,
|
|
91
|
+
});
|
|
92
|
+
const cutoffRisk = assessCutoffRisk({
|
|
93
|
+
policyInstabilityScore: profile.policyInstabilityScore,
|
|
94
|
+
exportControlExposure: profile.exportControlExposure,
|
|
95
|
+
accountDependency: profile.accountDependency,
|
|
96
|
+
incidents,
|
|
97
|
+
});
|
|
98
|
+
const localityScore = options.localAvailable
|
|
99
|
+
? 1.0
|
|
100
|
+
: profile.supportsSelfHosted
|
|
101
|
+
? 0.8
|
|
102
|
+
: 0.4;
|
|
103
|
+
const portabilityScore = assessPortability({
|
|
104
|
+
supportsOpenApiCompat: profile.openApiCompatible,
|
|
105
|
+
supportsToolContract: runtime.capabilities?.toolCalling === true || runtime.capabilities?.supportsToolCalling === true,
|
|
106
|
+
supportsEvidenceReturn: profile.metadataEvidenceSupport,
|
|
107
|
+
});
|
|
108
|
+
const score = 0.25 * (1 - jurisdictionRisk) +
|
|
109
|
+
0.25 * (1 - retentionRisk) +
|
|
110
|
+
0.20 * (1 - cutoffRisk) +
|
|
111
|
+
0.15 * localityScore +
|
|
112
|
+
0.15 * portabilityScore;
|
|
113
|
+
const diagnostics = {
|
|
114
|
+
jurisdictionRisk,
|
|
115
|
+
retentionRisk,
|
|
116
|
+
cutoffRisk,
|
|
117
|
+
localityScore,
|
|
118
|
+
portabilityScore,
|
|
119
|
+
incidentSeverity: incidents.length > 0 ? incidents[0].severity : undefined,
|
|
120
|
+
reason: `jurisdiction=${jurisdictionRisk.toFixed(2)} retention=${retentionRisk.toFixed(2)} cutoff=${cutoffRisk.toFixed(2)} locality=${localityScore.toFixed(2)} portability=${portabilityScore.toFixed(2)}`,
|
|
121
|
+
};
|
|
122
|
+
return { score: clamp01(score), diagnostics };
|
|
123
|
+
}
|
|
124
|
+
export function buildProviderSovereigntyProfiles() {
|
|
125
|
+
const now = new Date().toISOString();
|
|
126
|
+
const profiles = {
|
|
127
|
+
"local-llm": {
|
|
128
|
+
providerId: "local-llm",
|
|
129
|
+
runtimeMode: "api",
|
|
130
|
+
providerCountry: "user-device",
|
|
131
|
+
exportPolicy: "open",
|
|
132
|
+
retentionDays: 0,
|
|
133
|
+
zeroDataRetention: true,
|
|
134
|
+
trainingUse: false,
|
|
135
|
+
supportsSelfHosted: true,
|
|
136
|
+
openApiCompatible: true,
|
|
137
|
+
policyInstabilityScore: 0.05,
|
|
138
|
+
exportControlExposure: 0.0,
|
|
139
|
+
accountDependency: 0.0,
|
|
140
|
+
metadataEvidenceSupport: true,
|
|
141
|
+
},
|
|
142
|
+
codex: {
|
|
143
|
+
providerId: "codex",
|
|
144
|
+
runtimeMode: "cli",
|
|
145
|
+
providerCountry: "US",
|
|
146
|
+
exportPolicy: "restricted",
|
|
147
|
+
retentionDays: 0,
|
|
148
|
+
zeroDataRetention: true,
|
|
149
|
+
trainingUse: false,
|
|
150
|
+
supportsSelfHosted: false,
|
|
151
|
+
openApiCompatible: false,
|
|
152
|
+
policyInstabilityScore: 0.2,
|
|
153
|
+
exportControlExposure: 0.3,
|
|
154
|
+
accountDependency: 0.4,
|
|
155
|
+
metadataEvidenceSupport: true,
|
|
156
|
+
},
|
|
157
|
+
kimi: {
|
|
158
|
+
providerId: "kimi",
|
|
159
|
+
runtimeMode: "api",
|
|
160
|
+
providerCountry: "CN",
|
|
161
|
+
exportPolicy: "restricted",
|
|
162
|
+
retentionDays: 30,
|
|
163
|
+
zeroDataRetention: false,
|
|
164
|
+
trainingUse: false,
|
|
165
|
+
supportsSelfHosted: false,
|
|
166
|
+
openApiCompatible: true,
|
|
167
|
+
policyInstabilityScore: 0.25,
|
|
168
|
+
exportControlExposure: 0.35,
|
|
169
|
+
accountDependency: 0.5,
|
|
170
|
+
metadataEvidenceSupport: true,
|
|
171
|
+
},
|
|
172
|
+
mimo: {
|
|
173
|
+
providerId: "mimo",
|
|
174
|
+
runtimeMode: "api",
|
|
175
|
+
providerCountry: "CN",
|
|
176
|
+
exportPolicy: "restricted",
|
|
177
|
+
retentionDays: 30,
|
|
178
|
+
zeroDataRetention: false,
|
|
179
|
+
trainingUse: false,
|
|
180
|
+
supportsSelfHosted: false,
|
|
181
|
+
openApiCompatible: true,
|
|
182
|
+
policyInstabilityScore: 0.25,
|
|
183
|
+
exportControlExposure: 0.35,
|
|
184
|
+
accountDependency: 0.5,
|
|
185
|
+
metadataEvidenceSupport: true,
|
|
186
|
+
},
|
|
187
|
+
deepseek: {
|
|
188
|
+
providerId: "deepseek",
|
|
189
|
+
runtimeMode: "api",
|
|
190
|
+
providerCountry: "CN",
|
|
191
|
+
exportPolicy: "restricted",
|
|
192
|
+
retentionDays: 30,
|
|
193
|
+
zeroDataRetention: false,
|
|
194
|
+
trainingUse: false,
|
|
195
|
+
supportsSelfHosted: false,
|
|
196
|
+
openApiCompatible: true,
|
|
197
|
+
policyInstabilityScore: 0.3,
|
|
198
|
+
exportControlExposure: 0.4,
|
|
199
|
+
accountDependency: 0.5,
|
|
200
|
+
metadataEvidenceSupport: true,
|
|
201
|
+
},
|
|
202
|
+
opencode: {
|
|
203
|
+
providerId: "opencode",
|
|
204
|
+
runtimeMode: "cli",
|
|
205
|
+
providerCountry: "KR",
|
|
206
|
+
exportPolicy: "open",
|
|
207
|
+
retentionDays: 0,
|
|
208
|
+
zeroDataRetention: true,
|
|
209
|
+
trainingUse: false,
|
|
210
|
+
supportsSelfHosted: false,
|
|
211
|
+
openApiCompatible: false,
|
|
212
|
+
policyInstabilityScore: 0.2,
|
|
213
|
+
exportControlExposure: 0.1,
|
|
214
|
+
accountDependency: 0.3,
|
|
215
|
+
metadataEvidenceSupport: true,
|
|
216
|
+
},
|
|
217
|
+
commandcode: {
|
|
218
|
+
providerId: "commandcode",
|
|
219
|
+
runtimeMode: "cli",
|
|
220
|
+
providerCountry: "US",
|
|
221
|
+
exportPolicy: "open",
|
|
222
|
+
retentionDays: 0,
|
|
223
|
+
zeroDataRetention: true,
|
|
224
|
+
trainingUse: false,
|
|
225
|
+
supportsSelfHosted: false,
|
|
226
|
+
openApiCompatible: false,
|
|
227
|
+
policyInstabilityScore: 0.2,
|
|
228
|
+
exportControlExposure: 0.1,
|
|
229
|
+
accountDependency: 0.3,
|
|
230
|
+
metadataEvidenceSupport: true,
|
|
231
|
+
},
|
|
232
|
+
glm: {
|
|
233
|
+
providerId: "glm",
|
|
234
|
+
runtimeMode: "api",
|
|
235
|
+
providerCountry: "CN",
|
|
236
|
+
exportPolicy: "restricted",
|
|
237
|
+
retentionDays: 30,
|
|
238
|
+
zeroDataRetention: false,
|
|
239
|
+
trainingUse: false,
|
|
240
|
+
supportsSelfHosted: false,
|
|
241
|
+
openApiCompatible: true,
|
|
242
|
+
policyInstabilityScore: 0.3,
|
|
243
|
+
exportControlExposure: 0.4,
|
|
244
|
+
accountDependency: 0.5,
|
|
245
|
+
metadataEvidenceSupport: true,
|
|
246
|
+
},
|
|
247
|
+
openrouter: {
|
|
248
|
+
providerId: "openrouter",
|
|
249
|
+
runtimeMode: "api",
|
|
250
|
+
providerCountry: "US",
|
|
251
|
+
exportPolicy: "restricted",
|
|
252
|
+
retentionDays: 30,
|
|
253
|
+
zeroDataRetention: false,
|
|
254
|
+
trainingUse: false,
|
|
255
|
+
supportsSelfHosted: false,
|
|
256
|
+
openApiCompatible: true,
|
|
257
|
+
policyInstabilityScore: 0.25,
|
|
258
|
+
exportControlExposure: 0.3,
|
|
259
|
+
accountDependency: 0.6,
|
|
260
|
+
metadataEvidenceSupport: true,
|
|
261
|
+
},
|
|
262
|
+
qwen: {
|
|
263
|
+
providerId: "qwen",
|
|
264
|
+
runtimeMode: "api",
|
|
265
|
+
providerCountry: "CN",
|
|
266
|
+
exportPolicy: "restricted",
|
|
267
|
+
retentionDays: 30,
|
|
268
|
+
zeroDataRetention: false,
|
|
269
|
+
trainingUse: false,
|
|
270
|
+
supportsSelfHosted: false,
|
|
271
|
+
openApiCompatible: true,
|
|
272
|
+
policyInstabilityScore: 0.3,
|
|
273
|
+
exportControlExposure: 0.4,
|
|
274
|
+
accountDependency: 0.5,
|
|
275
|
+
metadataEvidenceSupport: true,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
void now;
|
|
279
|
+
return profiles;
|
|
280
|
+
}
|
|
281
|
+
export function lookupSovereigntyProfile(runtime, profiles) {
|
|
282
|
+
const map = profiles ?? buildProviderSovereigntyProfiles();
|
|
283
|
+
const providerId = runtimeProviderId(runtime);
|
|
284
|
+
return map[providerId] ?? map[runtime.id];
|
|
285
|
+
}
|
|
@@ -16,5 +16,6 @@ export interface RuntimeBackedTaskRunnerOptions {
|
|
|
16
16
|
runId?: string;
|
|
17
17
|
goal?: string;
|
|
18
18
|
onOutput?: (text: string) => void;
|
|
19
|
+
headroomCompactor?: (text: string) => Promise<string | null>;
|
|
19
20
|
}
|
|
20
21
|
export declare function createRuntimeBackedTaskRunner(options: RuntimeBackedTaskRunnerOptions): Promise<TaskRunner>;
|
|
@@ -6,15 +6,24 @@
|
|
|
6
6
|
* 2. Route to best AgentRuntime via RuntimeRouter
|
|
7
7
|
* 3. Convert AgentRunResult -> TaskResult
|
|
8
8
|
*/
|
|
9
|
-
import { readFileSync } from "node:fs";
|
|
9
|
+
import { appendFileSync, mkdirSync, readFileSync } from "node:fs";
|
|
10
10
|
import { join } from "node:path";
|
|
11
11
|
import { toTaskResult } from "./agent-runtime.js";
|
|
12
|
+
import { checkEvidenceGate, hasDeclaredEvidenceRequirement } from "./contracts/evidence.js";
|
|
13
|
+
function isStrictGuardrailMode() {
|
|
14
|
+
const raw = process.env.OMK_STRICT_GUARDRAIL ?? "";
|
|
15
|
+
const normalized = raw.trim().toLowerCase();
|
|
16
|
+
return normalized === "1" || normalized === "true" || normalized === "on";
|
|
17
|
+
}
|
|
12
18
|
import { capsuleToTask } from "./context-broker-converter.js";
|
|
13
19
|
import { applyTaskRunContextToAgentTask, envFromWorkerManifest } from "./worker-manifest.js";
|
|
14
20
|
import { createRuntimeRegistry } from "./runtime-registry.js";
|
|
15
21
|
import { createRuntimeRouter } from "./runtime-router.js";
|
|
22
|
+
import { createFreedomdRuntimeRouter } from "./freedomd-router.js";
|
|
16
23
|
import { createContextBroker } from "./context-broker.js";
|
|
24
|
+
import { estimateCapsuleTokens } from "./context-capsule.js";
|
|
17
25
|
import { maybeCompactWithHeadroom } from "./headroom-policy.js";
|
|
26
|
+
import { DEFAULT_STRUCTURED_COMPACTION_CONTRACT, buildStructuredCompactionText, buildTypedStructuredCompactionContract, computeCompactionQualityScore, estimateTextTokens, structuredCompactionGuardNote, structuredCompactionInstruction, validateStructuredCompaction, } from "./structured-compaction.js";
|
|
18
27
|
import { DeepSeekRuntime } from "./deepseek-runtime.js";
|
|
19
28
|
import { CodexRuntime } from "./codex-runtime.js";
|
|
20
29
|
import { createOpencodeCliAdapter } from "../adapters/opencode/opencode-cli-adapter.js";
|
|
@@ -26,6 +35,7 @@ import { createMimoApiRuntime } from "./mimo-api-runtime.js";
|
|
|
26
35
|
import { createKimiApiRuntime } from "./kimi-api-runtime.js";
|
|
27
36
|
import { createGlmApiRuntime } from "./glm-api-runtime.js";
|
|
28
37
|
import { getUserHome } from "../util/fs.js";
|
|
38
|
+
import { LocalGraphMemoryStore } from "../memory/local-graph-memory-store.js";
|
|
29
39
|
async function createDefaultRuntimeRegistry(options) {
|
|
30
40
|
const registry = createRuntimeRegistry();
|
|
31
41
|
// ── MiMo API runtime (Xiaomi MiMo — OpenAI-compatible, highest priority) ──
|
|
@@ -115,15 +125,182 @@ function readProviderConfig(configDir) {
|
|
|
115
125
|
function escapeRegExp(value) {
|
|
116
126
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
117
127
|
}
|
|
128
|
+
function applyCompactedTextToCapsule(capsule, compactedText) {
|
|
129
|
+
const trimmed = compactedText.trim();
|
|
130
|
+
const beforeChars = JSON.stringify(capsule).length;
|
|
131
|
+
const beforeTokens = estimateCapsuleTokens(capsule);
|
|
132
|
+
const baseDiagnostics = {
|
|
133
|
+
beforeChars,
|
|
134
|
+
beforeTokens,
|
|
135
|
+
compactedTextProduced: trimmed.length > 0,
|
|
136
|
+
};
|
|
137
|
+
if (trimmed.length === 0) {
|
|
138
|
+
return {
|
|
139
|
+
capsule,
|
|
140
|
+
diagnostics: {
|
|
141
|
+
...baseDiagnostics,
|
|
142
|
+
afterChars: 0,
|
|
143
|
+
afterTokens: 0,
|
|
144
|
+
validated: false,
|
|
145
|
+
applied: false,
|
|
146
|
+
missingSections: [],
|
|
147
|
+
reason: "empty compacted text",
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const afterChars = trimmed.length;
|
|
152
|
+
const afterTokens = estimateTextTokens(trimmed);
|
|
153
|
+
if (afterChars >= beforeChars) {
|
|
154
|
+
return {
|
|
155
|
+
capsule,
|
|
156
|
+
diagnostics: {
|
|
157
|
+
...baseDiagnostics,
|
|
158
|
+
afterChars,
|
|
159
|
+
afterTokens,
|
|
160
|
+
validated: false,
|
|
161
|
+
applied: false,
|
|
162
|
+
missingSections: [],
|
|
163
|
+
reason: "compacted text is not smaller than original capsule",
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// If compaction stripped required structural context, keep original but note the guard.
|
|
168
|
+
const validation = validateStructuredCompaction(trimmed, capsule);
|
|
169
|
+
if (!validation.ok) {
|
|
170
|
+
return {
|
|
171
|
+
capsule: {
|
|
172
|
+
...capsule,
|
|
173
|
+
system: [
|
|
174
|
+
capsule.system,
|
|
175
|
+
"",
|
|
176
|
+
"[OMK headroom compacted context]",
|
|
177
|
+
structuredCompactionGuardNote(validation),
|
|
178
|
+
].filter(Boolean).join("\n"),
|
|
179
|
+
budget: { ...capsule.budget, compression: "summary" },
|
|
180
|
+
},
|
|
181
|
+
diagnostics: {
|
|
182
|
+
...baseDiagnostics,
|
|
183
|
+
afterChars,
|
|
184
|
+
afterTokens,
|
|
185
|
+
validated: false,
|
|
186
|
+
applied: false,
|
|
187
|
+
missingSections: validation.missing,
|
|
188
|
+
contract: validation.contract.schemaVersion,
|
|
189
|
+
reason: "structured compaction contract validation failed",
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
capsule: {
|
|
195
|
+
...capsule,
|
|
196
|
+
system: [
|
|
197
|
+
capsule.system,
|
|
198
|
+
"",
|
|
199
|
+
"[OMK headroom compacted context]",
|
|
200
|
+
structuredCompactionInstruction(validation.contract),
|
|
201
|
+
trimmed,
|
|
202
|
+
].filter(Boolean).join("\n"),
|
|
203
|
+
dependencySummaries: [],
|
|
204
|
+
relevantFiles: [],
|
|
205
|
+
graphMemory: [],
|
|
206
|
+
priorAttempts: [],
|
|
207
|
+
budget: { ...capsule.budget, compression: "summary" },
|
|
208
|
+
},
|
|
209
|
+
diagnostics: {
|
|
210
|
+
...baseDiagnostics,
|
|
211
|
+
afterChars,
|
|
212
|
+
afterTokens,
|
|
213
|
+
validated: true,
|
|
214
|
+
applied: true,
|
|
215
|
+
missingSections: [],
|
|
216
|
+
contract: validation.contract.schemaVersion,
|
|
217
|
+
reason: "compaction applied",
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function persistHeadroomDecisionArtifact(input) {
|
|
222
|
+
const rawRunId = input.runId?.trim() || "runtime-backed-task-runner";
|
|
223
|
+
const runId = sanitizeArtifactSegment(rawRunId);
|
|
224
|
+
const nodeId = sanitizeArtifactSegment(input.nodeId || "node");
|
|
225
|
+
const relativePath = `.omk/runs/${runId}/headroom-decisions.jsonl`;
|
|
226
|
+
try {
|
|
227
|
+
const dir = join(input.cwd, ".omk", "runs", runId);
|
|
228
|
+
mkdirSync(dir, { recursive: true });
|
|
229
|
+
const record = {
|
|
230
|
+
schemaVersion: "omk.headroom-decision.v1",
|
|
231
|
+
runId,
|
|
232
|
+
nodeId,
|
|
233
|
+
timestamp: new Date().toISOString(),
|
|
234
|
+
...input.metadata,
|
|
235
|
+
artifactRef: undefined,
|
|
236
|
+
};
|
|
237
|
+
appendFileSync(join(input.cwd, relativePath), `${JSON.stringify(record)}\n`, "utf-8");
|
|
238
|
+
return relativePath;
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async function materializeHeadroomDecisionGraph(input) {
|
|
245
|
+
const runId = input.runId?.trim();
|
|
246
|
+
if (!runId || runId.startsWith("local-"))
|
|
247
|
+
return;
|
|
248
|
+
try {
|
|
249
|
+
const store = await LocalGraphMemoryStore.create({ projectRoot: input.cwd, sessionId: runId, source: "headroom-compaction" });
|
|
250
|
+
await store?.materializeHeadroomDecision({
|
|
251
|
+
runId,
|
|
252
|
+
nodeId: input.nodeId,
|
|
253
|
+
metadata: input.metadata,
|
|
254
|
+
artifactRef: input.metadata.artifactRef,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
// Best-effort graph materialization must never block runtime dispatch.
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function buildAgentContextCompaction(input) {
|
|
262
|
+
if (!input.metadata?.applied)
|
|
263
|
+
return undefined;
|
|
264
|
+
return {
|
|
265
|
+
schemaVersion: "omk.task-compaction.v1",
|
|
266
|
+
contract: buildTypedStructuredCompactionContract(input.capsule),
|
|
267
|
+
diagnostics: {
|
|
268
|
+
backend: input.metadata.backend,
|
|
269
|
+
beforeTokens: input.metadata.beforeTokens,
|
|
270
|
+
afterTokens: input.metadata.afterTokens,
|
|
271
|
+
validated: input.metadata.validated,
|
|
272
|
+
applied: input.metadata.applied,
|
|
273
|
+
qualityScore: input.metadata.qualityScore,
|
|
274
|
+
compressionRatio: input.metadata.compressionRatio,
|
|
275
|
+
contract: input.metadata.contract,
|
|
276
|
+
reason: input.metadata.reason,
|
|
277
|
+
},
|
|
278
|
+
artifactRef: input.metadata.artifactRef,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function sanitizeArtifactSegment(value) {
|
|
282
|
+
return value.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 128) || "unknown";
|
|
283
|
+
}
|
|
118
284
|
export async function createRuntimeBackedTaskRunner(options) {
|
|
119
285
|
const registry = await createDefaultRuntimeRegistry(options);
|
|
120
286
|
const runtimes = registry.list();
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
287
|
+
const freedomdEnabled = (process.env.OMK_FREEDOMD_MODE ?? "off").trim().toLowerCase() !== "off";
|
|
288
|
+
const runtimeRouter = freedomdEnabled
|
|
289
|
+
? await createFreedomdRuntimeRouter({
|
|
290
|
+
runtimes,
|
|
291
|
+
fallbackChain: options.fallbackChain,
|
|
292
|
+
projectRoot: options.cwd,
|
|
293
|
+
autoLoadIncidents: true,
|
|
294
|
+
isTty: process.stdin.isTTY,
|
|
295
|
+
})
|
|
296
|
+
: createRuntimeRouter({
|
|
297
|
+
runtimes,
|
|
298
|
+
fallbackChain: options.fallbackChain,
|
|
299
|
+
});
|
|
125
300
|
registry.onChange((nextRuntimes) => {
|
|
126
|
-
runtimeRouter
|
|
301
|
+
if ("setRuntimes" in runtimeRouter) {
|
|
302
|
+
runtimeRouter.setRuntimes?.(nextRuntimes);
|
|
303
|
+
}
|
|
127
304
|
});
|
|
128
305
|
const contextBroker = createContextBroker({
|
|
129
306
|
projectRoot: options.cwd,
|
|
@@ -140,14 +317,67 @@ export async function createRuntimeBackedTaskRunner(options) {
|
|
|
140
317
|
}
|
|
141
318
|
: undefined;
|
|
142
319
|
const { capsule, headroomDecision } = await contextBroker.buildCapsule(node, runState);
|
|
320
|
+
let effectiveCapsule = capsule;
|
|
321
|
+
let headroomCompaction;
|
|
143
322
|
// CTX guard: compact via headroom before the context window crosses the threshold (~90%).
|
|
144
323
|
if (headroomDecision?.shouldCompact) {
|
|
145
|
-
await maybeCompactWithHeadroom({
|
|
324
|
+
const compactResult = await maybeCompactWithHeadroom({
|
|
146
325
|
decision: headroomDecision,
|
|
147
326
|
text: JSON.stringify(capsule),
|
|
327
|
+
runHeadroom: options.headroomCompactor,
|
|
328
|
+
fallbackText: () => buildStructuredCompactionText(capsule),
|
|
148
329
|
}).catch(() => undefined);
|
|
330
|
+
if (compactResult) {
|
|
331
|
+
let applyDiagnostics;
|
|
332
|
+
if (compactResult.compactedText) {
|
|
333
|
+
const applied = applyCompactedTextToCapsule(capsule, compactResult.compactedText);
|
|
334
|
+
effectiveCapsule = applied.capsule;
|
|
335
|
+
applyDiagnostics = applied.diagnostics;
|
|
336
|
+
}
|
|
337
|
+
const quality = computeCompactionQualityScore({
|
|
338
|
+
applied: applyDiagnostics?.applied ?? false,
|
|
339
|
+
validated: applyDiagnostics?.validated ?? false,
|
|
340
|
+
beforeTokens: applyDiagnostics?.beforeTokens,
|
|
341
|
+
afterTokens: applyDiagnostics?.afterTokens,
|
|
342
|
+
missingSections: applyDiagnostics?.missingSections ?? [],
|
|
343
|
+
});
|
|
344
|
+
headroomCompaction = {
|
|
345
|
+
attempted: compactResult.attempted,
|
|
346
|
+
compacted: compactResult.compacted,
|
|
347
|
+
via: compactResult.via,
|
|
348
|
+
backend: compactResult.backend,
|
|
349
|
+
compactedTextProduced: compactResult.compactedTextProduced,
|
|
350
|
+
validated: applyDiagnostics?.validated ?? false,
|
|
351
|
+
applied: applyDiagnostics?.applied ?? false,
|
|
352
|
+
beforeChars: applyDiagnostics?.beforeChars,
|
|
353
|
+
afterChars: applyDiagnostics?.afterChars,
|
|
354
|
+
beforeTokens: applyDiagnostics?.beforeTokens,
|
|
355
|
+
afterTokens: applyDiagnostics?.afterTokens,
|
|
356
|
+
threshold: headroomDecision.threshold,
|
|
357
|
+
utilization: headroomDecision.utilization,
|
|
358
|
+
contract: applyDiagnostics?.contract ?? DEFAULT_STRUCTURED_COMPACTION_CONTRACT.schemaVersion,
|
|
359
|
+
missingSections: applyDiagnostics?.missingSections ?? [],
|
|
360
|
+
reason: applyDiagnostics?.reason ?? compactResult.reason,
|
|
361
|
+
...quality,
|
|
362
|
+
};
|
|
363
|
+
const materializedRunId = options.runId ?? capsule.runId;
|
|
364
|
+
const artifactRef = persistHeadroomDecisionArtifact({
|
|
365
|
+
cwd: options.cwd,
|
|
366
|
+
runId: materializedRunId,
|
|
367
|
+
nodeId: capsule.nodeId,
|
|
368
|
+
metadata: headroomCompaction,
|
|
369
|
+
});
|
|
370
|
+
if (artifactRef)
|
|
371
|
+
headroomCompaction = { ...headroomCompaction, artifactRef };
|
|
372
|
+
await materializeHeadroomDecisionGraph({
|
|
373
|
+
cwd: options.cwd,
|
|
374
|
+
runId: materializedRunId,
|
|
375
|
+
nodeId: capsule.nodeId,
|
|
376
|
+
metadata: headroomCompaction,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
149
379
|
}
|
|
150
|
-
const routing =
|
|
380
|
+
const routing = effectiveCapsule.node.routing;
|
|
151
381
|
const providerFallbackChain = options.fallbackChain
|
|
152
382
|
?? (routing?.fallbackProvider ? [routing.fallbackProvider] : []);
|
|
153
383
|
const abortSignal = signal ?? new AbortController().signal;
|
|
@@ -156,22 +386,61 @@ export async function createRuntimeBackedTaskRunner(options) {
|
|
|
156
386
|
...(env ?? {}),
|
|
157
387
|
...(runContext ? envFromWorkerManifest(runContext.worker) : {}),
|
|
158
388
|
};
|
|
159
|
-
const
|
|
389
|
+
const rawTask = applyTaskRunContextToAgentTask(await capsuleToTask(effectiveCapsule, {
|
|
160
390
|
signal: abortSignal,
|
|
161
391
|
cwd: options.cwd,
|
|
162
392
|
env: taskEnv,
|
|
163
393
|
fallbackChain: providerFallbackChain,
|
|
164
394
|
}), runContext);
|
|
395
|
+
const compactionContext = buildAgentContextCompaction({ capsule, metadata: headroomCompaction });
|
|
396
|
+
const baseTask = compactionContext
|
|
397
|
+
? { ...rawTask, context: { ...rawTask.context, compaction: compactionContext } }
|
|
398
|
+
: rawTask;
|
|
165
399
|
const task = options.onOutput
|
|
166
400
|
? { ...baseTask, context: { ...baseTask.context, onOutput: options.onOutput } }
|
|
167
401
|
: baseTask;
|
|
168
|
-
const
|
|
402
|
+
const strictGuardrailMode = isStrictGuardrailMode();
|
|
403
|
+
const evidenceRequired = strictGuardrailMode && (task.safety.evidenceRequired || effectiveCapsule.node.routing?.evidenceRequired === true || isHighRiskTask(task));
|
|
404
|
+
const declaredEvidenceOk = !evidenceRequired || hasDeclaredEvidenceRequirement(effectiveCapsule.node.outputs);
|
|
405
|
+
if (evidenceRequired && !declaredEvidenceOk) {
|
|
406
|
+
return {
|
|
407
|
+
success: false,
|
|
408
|
+
exitCode: 78,
|
|
409
|
+
stdout: "",
|
|
410
|
+
stderr: "[omk] Evidence gate required but missing: high-risk task declares no required evidence output gate",
|
|
411
|
+
metadata: {
|
|
412
|
+
evidenceRequired,
|
|
413
|
+
evidenceDeclarationMissing: true,
|
|
414
|
+
fallbackChain: task.providerPolicy.fallbackChain,
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const agentResult = await runtimeRouter.executeTask(task, effectiveCapsule, abortSignal);
|
|
169
419
|
const taskResult = toTaskResult(agentResult);
|
|
420
|
+
// Post-execution evidence check for tasks that produced no metadata gate
|
|
421
|
+
if (evidenceRequired && agentResult.success && strictGuardrailMode) {
|
|
422
|
+
const postCheck = checkEvidenceGate(true, effectiveCapsule.node.outputs, taskResult.metadata ?? null, taskResult.stdout);
|
|
423
|
+
if (!postCheck.satisfied) {
|
|
424
|
+
return {
|
|
425
|
+
success: false,
|
|
426
|
+
exitCode: 78,
|
|
427
|
+
stdout: taskResult.stdout,
|
|
428
|
+
stderr: `[omk] Evidence gate required but task produced no replayable evidence: ${postCheck.reason}`,
|
|
429
|
+
metadata: {
|
|
430
|
+
...taskResult.metadata,
|
|
431
|
+
evidenceRequired,
|
|
432
|
+
evidenceCheck: postCheck,
|
|
433
|
+
},
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
}
|
|
170
437
|
// Ensure routing metadata is present even if the router failed to attach it
|
|
171
438
|
taskResult.metadata = {
|
|
172
439
|
...(taskResult.metadata ?? {}),
|
|
173
440
|
fallbackChain: task.providerPolicy.fallbackChain,
|
|
441
|
+
...(headroomCompaction && { headroomCompaction }),
|
|
174
442
|
...(runContext && { workerOwner: runContext.worker.owner }),
|
|
443
|
+
...(evidenceRequired && { evidenceRequired }),
|
|
175
444
|
};
|
|
176
445
|
return taskResult;
|
|
177
446
|
},
|
|
@@ -182,3 +451,6 @@ export async function createRuntimeBackedTaskRunner(options) {
|
|
|
182
451
|
runner._registry = registry;
|
|
183
452
|
return runner;
|
|
184
453
|
}
|
|
454
|
+
function isHighRiskTask(task) {
|
|
455
|
+
return task.capabilities.write === true || task.capabilities.patch === true || task.capabilities.shell === true || task.capabilities.merge === true;
|
|
456
|
+
}
|
|
@@ -19,3 +19,15 @@ export declare function resolveRuntimeBootstrap(options: {
|
|
|
19
19
|
cwd?: string;
|
|
20
20
|
env?: Record<string, string | undefined>;
|
|
21
21
|
}): Promise<RuntimeBootstrap>;
|
|
22
|
+
export type ResolvedProviderPolicy = {
|
|
23
|
+
ok: true;
|
|
24
|
+
provider: string;
|
|
25
|
+
runtimeId?: string;
|
|
26
|
+
reason?: string;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
provider: string;
|
|
30
|
+
reason: string;
|
|
31
|
+
remediation: string[];
|
|
32
|
+
};
|
|
33
|
+
export declare function resolveProviderPolicy(providerPolicy: string, env: Record<string, string | undefined>): Promise<ResolvedProviderPolicy>;
|