open-multi-agent-kit 0.79.3 → 0.80.2
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 +38 -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 +370 -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 +111 -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 +171 -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 +138 -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 +54 -11
- 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 +5 -4
- 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/2026-06-17/critical-issues.md +19 -0
- package/docs/2026-06-17/improvements.md +15 -0
- package/docs/2026-06-17/init-checklist.md +25 -0
- package/docs/2026-06-17/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
|
@@ -262,6 +262,15 @@ export function compressDiagnostic(command, exitCode, stdout, stderr) {
|
|
|
262
262
|
/** Allowlist pattern reused from quality-gate.ts */
|
|
263
263
|
const SCRIPT_NAME_PATTERN = /^[A-Za-z0-9:_-]+$/;
|
|
264
264
|
const PACKAGE_MANAGERS = new Set(["npm", "pnpm", "yarn", "bun"]);
|
|
265
|
+
/**
|
|
266
|
+
* Agent-freedom mode (e.g. SWE-bench / DeepSWE) relaxes command-pass gate
|
|
267
|
+
* allowlisting so agents can run arbitrary test/build/lint commands.
|
|
268
|
+
*/
|
|
269
|
+
function isStrictGuardrailMode() {
|
|
270
|
+
const raw = process.env.OMK_STRICT_GUARDRAIL ?? "";
|
|
271
|
+
const normalized = raw.trim().toLowerCase();
|
|
272
|
+
return normalized === "1" || normalized === "true" || normalized === "on";
|
|
273
|
+
}
|
|
265
274
|
export const SUMMARY_ALIASES = [
|
|
266
275
|
"## Summary",
|
|
267
276
|
"## Evidence",
|
|
@@ -279,6 +288,9 @@ export const SUMMARY_ALIASES = [
|
|
|
279
288
|
function resolveSafeCommand(command) {
|
|
280
289
|
const trimmed = command.trim();
|
|
281
290
|
const parts = trimmed.split(/\s+/);
|
|
291
|
+
if (!isStrictGuardrailMode()) {
|
|
292
|
+
return { cmd: parts[0], args: parts.slice(1) };
|
|
293
|
+
}
|
|
282
294
|
if (parts.length === 1 && SCRIPT_NAME_PATTERN.test(parts[0])) {
|
|
283
295
|
return { cmd: "npm", args: ["run", parts[0]] };
|
|
284
296
|
}
|
|
@@ -5,6 +5,7 @@ import { estimateRunProgress } from "./eta.js";
|
|
|
5
5
|
import { dagNodeRoutingEnv } from "./routing.js";
|
|
6
6
|
import { getOmkResourceSettings } from "../util/resource-profile.js";
|
|
7
7
|
import { checkEvidenceGates } from "./evidence-gate.js";
|
|
8
|
+
import { checkEvidenceGate } from "../runtime/contracts/evidence.js";
|
|
8
9
|
import { invalidateTaskDagGraph } from "./task-graph.js";
|
|
9
10
|
import { resolveTimeoutMs } from "../util/timeout-config.js";
|
|
10
11
|
import { createNodeMonitorEngine } from "./node-monitor.js";
|
|
@@ -318,46 +319,141 @@ export function createExecutor(executorOptions = {}) {
|
|
|
318
319
|
}
|
|
319
320
|
}
|
|
320
321
|
async function checkNodeEvidence(node, result, options) {
|
|
321
|
-
const
|
|
322
|
+
const cwd = options.worktreeRoot ?? process.cwd();
|
|
323
|
+
const latestAttempt = node.attempts?.[node.attempts.length - 1];
|
|
324
|
+
const attemptId = latestAttempt ? `${node.id}__${latestAttempt.attempt}` : `${node.id}__1`;
|
|
325
|
+
const required = nodeRequiresEvidence(node);
|
|
326
|
+
const bridge = await legacyEvidenceBridge(node, result, { cwd, runId: options.runId, attemptId, required });
|
|
327
|
+
const metadata = {
|
|
328
|
+
...(result.metadata ?? {}),
|
|
329
|
+
...(bridge.evidenceGates.length > 0 && { evidenceGates: bridge.evidenceGates }),
|
|
330
|
+
...(bridge.diffObserved && { diff: true }),
|
|
331
|
+
};
|
|
332
|
+
const check = checkEvidenceGate(required, node.outputs, metadata, result.stdout, bridge.artifactPaths);
|
|
333
|
+
return {
|
|
334
|
+
passed: check.satisfied,
|
|
335
|
+
evidence: evidenceGateCheckToDagEvidence(check, bridge.evidence),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
async function legacyEvidenceBridge(node, result, options) {
|
|
339
|
+
const legacyGates = [];
|
|
322
340
|
for (const output of node.outputs ?? []) {
|
|
323
341
|
switch (output.gate) {
|
|
324
342
|
case "file-exists":
|
|
343
|
+
case "artifact":
|
|
325
344
|
if (output.ref)
|
|
326
|
-
|
|
345
|
+
legacyGates.push({ type: "file-exists", path: output.ref });
|
|
327
346
|
break;
|
|
328
347
|
case "test-pass":
|
|
329
|
-
|
|
348
|
+
legacyGates.push({ type: "command-pass", command: output.ref ?? "npm test" });
|
|
330
349
|
break;
|
|
331
350
|
case "command-pass":
|
|
332
|
-
|
|
351
|
+
legacyGates.push({ type: "command-pass", command: output.ref ?? "" });
|
|
352
|
+
break;
|
|
353
|
+
case "diff":
|
|
354
|
+
legacyGates.push({ type: "diff-nonempty" });
|
|
333
355
|
break;
|
|
334
356
|
case "review-pass":
|
|
335
357
|
case "summary":
|
|
336
|
-
|
|
358
|
+
legacyGates.push({ type: "summary-present", summaryMarker: output.ref ?? "## Summary" });
|
|
337
359
|
break;
|
|
338
360
|
case "none":
|
|
339
361
|
default:
|
|
340
362
|
break;
|
|
341
363
|
}
|
|
342
364
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
gates.push({ type: "summary-present", summaryMarker: "## Evidence" });
|
|
365
|
+
if (options.required && node.routing?.evidenceRequired && !legacyGates.some((gate) => gate.type === "command-pass")) {
|
|
366
|
+
legacyGates.push({ type: "summary-present", summaryMarker: "## Evidence" });
|
|
346
367
|
}
|
|
347
|
-
if (
|
|
348
|
-
return {
|
|
368
|
+
if (legacyGates.length === 0) {
|
|
369
|
+
return { evidenceGates: [], artifactPaths: [], diffObserved: false, evidence: [] };
|
|
349
370
|
}
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
return checkEvidenceGates(gates, {
|
|
353
|
-
cwd: options.worktreeRoot ?? process.cwd(),
|
|
371
|
+
const legacy = await checkEvidenceGates(legacyGates, {
|
|
372
|
+
cwd: options.cwd,
|
|
354
373
|
stdout: result.stdout,
|
|
355
374
|
nodeId: node.id,
|
|
356
375
|
runId: options.runId,
|
|
357
|
-
attemptId,
|
|
376
|
+
attemptId: options.attemptId,
|
|
358
377
|
});
|
|
378
|
+
const evidenceGates = [];
|
|
379
|
+
const artifactPaths = [];
|
|
380
|
+
let diffObserved = false;
|
|
381
|
+
for (const item of legacy.evidence) {
|
|
382
|
+
if (!item.passed)
|
|
383
|
+
continue;
|
|
384
|
+
if (item.gate === "command-pass")
|
|
385
|
+
evidenceGates.push("command-pass");
|
|
386
|
+
else if (item.gate === "summary-present")
|
|
387
|
+
evidenceGates.push("summary");
|
|
388
|
+
else if (item.gate === "file-exists") {
|
|
389
|
+
evidenceGates.push("artifact");
|
|
390
|
+
if (item.ref)
|
|
391
|
+
artifactPaths.push(item.ref);
|
|
392
|
+
}
|
|
393
|
+
else if (item.gate === "diff-nonempty") {
|
|
394
|
+
evidenceGates.push("diff");
|
|
395
|
+
diffObserved = true;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return { evidenceGates, artifactPaths, diffObserved, evidence: legacy.evidence };
|
|
399
|
+
}
|
|
400
|
+
function evidenceGateCheckToDagEvidence(check, bridgeEvidence) {
|
|
401
|
+
const evidence = [...bridgeEvidence];
|
|
402
|
+
for (const observation of check.observations ?? []) {
|
|
403
|
+
evidence.push({
|
|
404
|
+
gate: observation.kind,
|
|
405
|
+
passed: check.satisfied,
|
|
406
|
+
ref: observation.ref ?? observation.artifactPath,
|
|
407
|
+
message: `Evidence observation ${observation.kind} from ${observation.source} confidence=${observation.confidence}`,
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
for (const missing of check.missing) {
|
|
411
|
+
evidence.push({
|
|
412
|
+
gate: missing,
|
|
413
|
+
passed: false,
|
|
414
|
+
failureKind: "missing-evidence-observation",
|
|
415
|
+
message: check.reason,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
return evidence;
|
|
419
|
+
}
|
|
420
|
+
function hasRequiredEvidenceOutput(node) {
|
|
421
|
+
return (node.outputs ?? []).some((output) => output.required !== false && output.gate !== undefined && output.gate !== "none");
|
|
422
|
+
}
|
|
423
|
+
function nodeRequiresEvidence(node) {
|
|
424
|
+
const highRisk = nodeHasHighRiskCapabilities(node);
|
|
425
|
+
const outputs = node.outputs ?? [];
|
|
426
|
+
const explicitlyNoEvidence = outputs.length > 0 && outputs.every((output) => output.required === false || output.gate === undefined || output.gate === "none");
|
|
427
|
+
if (explicitlyNoEvidence && !highRisk)
|
|
428
|
+
return false;
|
|
429
|
+
return hasRequiredEvidenceOutput(node) || highRisk;
|
|
430
|
+
}
|
|
431
|
+
function nodeHasHighRiskCapabilities(node) {
|
|
432
|
+
return node.routing?.assignedProviderCapabilities?.some((cap) => ["write", "patch", "shell", "merge"].includes(cap)) ?? false;
|
|
359
433
|
}
|
|
360
434
|
async function runNode(node, dag, runner, options, state, signal, outAbort) {
|
|
435
|
+
if (nodeRequiresEvidence(node)) {
|
|
436
|
+
const hasGate = (node.outputs ?? []).some((output) => ["file-exists", "test-pass", "review-pass", "command-pass", "summary", "artifact", "diff"].includes(output.gate ?? ""));
|
|
437
|
+
if (!hasGate) {
|
|
438
|
+
scheduler.updateNodeStatus(dag, node.id, "failed", options.runId);
|
|
439
|
+
markNodeStarted(node);
|
|
440
|
+
const completedAt = new Date().toISOString();
|
|
441
|
+
const startedAtMs = Date.parse(node.startedAt ?? completedAt);
|
|
442
|
+
const durationMs = Math.max(0, Date.parse(completedAt) - startedAtMs);
|
|
443
|
+
const latestAttempt = { attempt: node.retries + 1, startedAt: node.startedAt ?? completedAt, completedAt, durationMs, status: "failed", error: "[omk] Evidence gate required but missing: high-risk node has no command-pass, test-pass, review-pass, file-exists, or summary output gate" };
|
|
444
|
+
node.attempts = [...(node.attempts ?? []), latestAttempt];
|
|
445
|
+
node.evidence = [
|
|
446
|
+
...(node.evidence ?? []),
|
|
447
|
+
{ gate: "evidence-required", passed: false, message: latestAttempt.error, failureKind: "missing-evidence-gate" },
|
|
448
|
+
];
|
|
449
|
+
markNodeFinished(node, "failed");
|
|
450
|
+
refreshState(state, dag, options);
|
|
451
|
+
await commitState(state);
|
|
452
|
+
emit(cloneState(state));
|
|
453
|
+
emitTelemetry({ type: "lane.failed", runId: options.runId, nodeId: node.id, laneId: node.id, status: "failed", data: { success: false, exitCode: 78 } });
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
361
457
|
scheduler.updateNodeStatus(dag, node.id, "running", options.runId);
|
|
362
458
|
markNodeStarted(node);
|
|
363
459
|
bumpActivity(state);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EvaluateLoopDecisionInput, LoopDecision } from "./loop-state.js";
|
|
2
|
+
import type { HeadroomDecisionHistoryEntry } from "../runtime/headroom-loop-risk.js";
|
|
3
|
+
export interface HeadroomAwareLoopControllerInput extends EvaluateLoopDecisionInput {
|
|
4
|
+
readonly headroomHistory: readonly HeadroomDecisionHistoryEntry[];
|
|
5
|
+
}
|
|
6
|
+
export declare function evaluateHeadroomAwareLoopController(input: HeadroomAwareLoopControllerInput): LoopDecision;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { evaluateLoopDecision } from "./loop-controller.js";
|
|
2
|
+
import { evaluateHeadroomAwareLoopDecision } from "../runtime/headroom-aware-loop-decision.js";
|
|
3
|
+
function toHeadroomAction(action) {
|
|
4
|
+
switch (action) {
|
|
5
|
+
case "close":
|
|
6
|
+
return "continue";
|
|
7
|
+
case "verify-only":
|
|
8
|
+
return "continue";
|
|
9
|
+
case "handoff":
|
|
10
|
+
return "block";
|
|
11
|
+
default:
|
|
12
|
+
return action;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function evaluateHeadroomAwareLoopController(input) {
|
|
16
|
+
const baseDecision = evaluateLoopDecision(input);
|
|
17
|
+
const headroomAware = evaluateHeadroomAwareLoopDecision({
|
|
18
|
+
baseAction: toHeadroomAction(baseDecision.action),
|
|
19
|
+
baseReason: baseDecision.reason,
|
|
20
|
+
baseConfidence: baseDecision.confidence,
|
|
21
|
+
headroomHistory: input.headroomHistory,
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
...baseDecision,
|
|
25
|
+
action: headroomAware.action === "context-adjustment" ? "continue" : headroomAware.action,
|
|
26
|
+
reason: headroomAware.reason,
|
|
27
|
+
confidence: headroomAware.confidence,
|
|
28
|
+
risk: {
|
|
29
|
+
...baseDecision.risk,
|
|
30
|
+
headroom: headroomAware.risk?.headroom,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Dag, DagNode, TaskStatus } from "./dag.js";
|
|
2
|
+
import type { RunnableNodePlan } from "./task-graph.js";
|
|
2
3
|
export interface Scheduler {
|
|
3
4
|
getRunnableNodes(dag: Dag): DagNode[];
|
|
5
|
+
getRunnablePlan(dag: Dag): RunnableNodePlan[];
|
|
4
6
|
updateNodeStatus(dag: Dag, id: string, status: TaskStatus, runId?: string): void;
|
|
5
7
|
isComplete(dag: Dag): boolean;
|
|
6
8
|
isFailed(dag: Dag): boolean;
|
|
@@ -6,6 +6,9 @@ export function createScheduler() {
|
|
|
6
6
|
getRunnableNodes(dag) {
|
|
7
7
|
return getTaskDagGraph(dag).runnableNodes().slice();
|
|
8
8
|
},
|
|
9
|
+
getRunnablePlan(dag) {
|
|
10
|
+
return getTaskDagGraph(dag).runnablePlan();
|
|
11
|
+
},
|
|
9
12
|
updateNodeStatus(dag, id, status, runId) {
|
|
10
13
|
const node = getTaskDagGraph(dag).getNode(id);
|
|
11
14
|
if (!node)
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { type Dag, type DagNode } from "./dag.js";
|
|
2
|
+
export interface RunnableNodePlan {
|
|
3
|
+
readonly node: DagNode;
|
|
4
|
+
readonly nodeId: string;
|
|
5
|
+
readonly rank: number;
|
|
6
|
+
readonly score: number;
|
|
7
|
+
readonly criticalPathDepth: number;
|
|
8
|
+
readonly downstreamCount: number;
|
|
9
|
+
readonly priority: number;
|
|
10
|
+
readonly cost: number;
|
|
11
|
+
readonly evidenceProducer: boolean;
|
|
12
|
+
readonly evidenceRequired: boolean;
|
|
13
|
+
readonly reason: string;
|
|
14
|
+
}
|
|
2
15
|
export declare class TaskDagGraph {
|
|
3
16
|
private readonly nodeById;
|
|
4
17
|
private readonly predecessorIds;
|
|
@@ -19,8 +32,12 @@ export declare class TaskDagGraph {
|
|
|
19
32
|
findCycle(): string[];
|
|
20
33
|
findAllCycles(limit?: number): string[][];
|
|
21
34
|
getCriticalPathDepth(id: string): number;
|
|
35
|
+
getDownstreamCount(id: string): number;
|
|
36
|
+
getRunnableScore(id: string): number;
|
|
37
|
+
runnablePlan(): RunnableNodePlan[];
|
|
22
38
|
private compareOrder;
|
|
23
39
|
private compareRunnable;
|
|
40
|
+
private describeRunnableNode;
|
|
24
41
|
private runnableScore;
|
|
25
42
|
private criticalPathDepth;
|
|
26
43
|
private downstreamCount;
|
|
@@ -190,12 +190,50 @@ export class TaskDagGraph {
|
|
|
190
190
|
getCriticalPathDepth(id) {
|
|
191
191
|
return this.criticalPathDepth(id);
|
|
192
192
|
}
|
|
193
|
+
getDownstreamCount(id) {
|
|
194
|
+
return this.downstreamCount(id);
|
|
195
|
+
}
|
|
196
|
+
getRunnableScore(id) {
|
|
197
|
+
return this.runnableScore(id);
|
|
198
|
+
}
|
|
199
|
+
runnablePlan() {
|
|
200
|
+
return this.runnableNodes().map((node, index) => this.describeRunnableNode(node, index));
|
|
201
|
+
}
|
|
193
202
|
compareOrder(a, b) {
|
|
194
203
|
return (this.order.get(a) ?? 0) - (this.order.get(b) ?? 0);
|
|
195
204
|
}
|
|
196
205
|
compareRunnable(a, b) {
|
|
197
206
|
return this.runnableScore(b) - this.runnableScore(a) || this.compareOrder(a, b);
|
|
198
207
|
}
|
|
208
|
+
describeRunnableNode(node, index) {
|
|
209
|
+
const criticalPathDepth = this.criticalPathDepth(node.id);
|
|
210
|
+
const downstreamCount = this.downstreamCount(node.id);
|
|
211
|
+
const evidenceProducer = (node.outputs ?? []).some((output) => output.gate && output.gate !== "none");
|
|
212
|
+
const evidenceRequired = node.routing?.evidenceRequired === true;
|
|
213
|
+
const priority = Number.isFinite(node.priority) ? node.priority ?? 0 : 0;
|
|
214
|
+
const cost = node.cost ?? 1;
|
|
215
|
+
const score = this.runnableScore(node.id);
|
|
216
|
+
return {
|
|
217
|
+
node,
|
|
218
|
+
nodeId: node.id,
|
|
219
|
+
rank: index + 1,
|
|
220
|
+
score,
|
|
221
|
+
criticalPathDepth,
|
|
222
|
+
downstreamCount,
|
|
223
|
+
priority,
|
|
224
|
+
cost,
|
|
225
|
+
evidenceProducer,
|
|
226
|
+
evidenceRequired,
|
|
227
|
+
reason: [
|
|
228
|
+
`criticalDepth=${criticalPathDepth}`,
|
|
229
|
+
`downstream=${downstreamCount}`,
|
|
230
|
+
`priority=${priority}`,
|
|
231
|
+
`cost=${cost}`,
|
|
232
|
+
evidenceProducer ? "evidenceProducer" : "noEvidenceGate",
|
|
233
|
+
evidenceRequired ? "evidenceRequired" : "evidenceOptional",
|
|
234
|
+
].join("; "),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
199
237
|
runnableScore(id) {
|
|
200
238
|
const node = this.nodeById.get(id);
|
|
201
239
|
if (!node)
|
|
@@ -56,8 +56,8 @@ export function createCodexCliAdvisoryTaskRunner(options) {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
const prompt = preflight.input;
|
|
59
|
-
const sandboxMode = risk
|
|
60
|
-
const approvalPolicy =
|
|
59
|
+
const sandboxMode = resolveCodexCliSandboxMode(risk, advisoryMode, env);
|
|
60
|
+
const approvalPolicy = codexCliApprovalPolicy(env.OMK_APPROVAL_POLICY ?? env.OMK_EXECUTION, sandboxMode);
|
|
61
61
|
const childEnv = buildChildEnv({
|
|
62
62
|
overrideEnv: {
|
|
63
63
|
...env,
|
|
@@ -101,6 +101,21 @@ export function createCodexCliAdvisoryTaskRunner(options) {
|
|
|
101
101
|
};
|
|
102
102
|
return runner;
|
|
103
103
|
}
|
|
104
|
+
function resolveCodexCliSandboxMode(risk, advisoryMode, env) {
|
|
105
|
+
if (risk === "read" || advisoryMode)
|
|
106
|
+
return "read-only";
|
|
107
|
+
if (env.OMK_PROVIDER_AUTHORITY === "advisory")
|
|
108
|
+
return "read-only";
|
|
109
|
+
return "workspace-write";
|
|
110
|
+
}
|
|
111
|
+
function codexCliApprovalPolicy(value, sandboxMode) {
|
|
112
|
+
if (sandboxMode !== "read-only")
|
|
113
|
+
return "on-request";
|
|
114
|
+
const normalized = value?.trim().toLowerCase();
|
|
115
|
+
if (normalized === "never" || normalized === "yolo")
|
|
116
|
+
return "never";
|
|
117
|
+
return "on-request";
|
|
118
|
+
}
|
|
104
119
|
function buildCodexPrompt(node, env) {
|
|
105
120
|
return [
|
|
106
121
|
"You are a Codex CLI advisory/read-only lane inside OMK.",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { TaskResult } from "../contracts/orchestration.js";
|
|
7
7
|
import type { ContextCapsule } from "./context-capsule.js";
|
|
8
|
-
import type { RuntimeCapabilities as SharedRuntimeCapabilities, RuntimeHealth as SharedRuntimeHealth, RuntimeId, RuntimeKind } from "./contracts/shared.js";
|
|
8
|
+
import type { RuntimeCapabilities as SharedRuntimeCapabilities, RuntimeHealth as SharedRuntimeHealth, RuntimeHealthProbeRequest, RuntimeId, RuntimeKind } from "./contracts/shared.js";
|
|
9
9
|
export type { RuntimeAuthority, RuntimeId, RuntimeKind } from "./contracts/shared.js";
|
|
10
10
|
export interface TokenUsage {
|
|
11
11
|
readonly inputTokens: number;
|
|
@@ -58,6 +58,29 @@ export interface ToolManifest {
|
|
|
58
58
|
readonly skills?: readonly string[];
|
|
59
59
|
readonly hooks?: readonly string[];
|
|
60
60
|
}
|
|
61
|
+
export interface AgentTaskSafety {
|
|
62
|
+
readonly risk: string;
|
|
63
|
+
readonly riskTrace?: unknown;
|
|
64
|
+
readonly approvalPolicy: string;
|
|
65
|
+
readonly sandboxMode: string;
|
|
66
|
+
readonly evidenceRequired: boolean;
|
|
67
|
+
readonly authorityMode: string;
|
|
68
|
+
}
|
|
69
|
+
export interface AgentTaskSovereignty {
|
|
70
|
+
readonly mode: "freedomd" | "standard";
|
|
71
|
+
readonly dataBoundary: "public" | "internal" | "customer" | "secret";
|
|
72
|
+
readonly retentionDecision: "allow" | "redact" | "downgrade" | "block";
|
|
73
|
+
readonly jurisdictionDecision: "allow" | "downgrade" | "block";
|
|
74
|
+
readonly providerCutoffRisk: number;
|
|
75
|
+
readonly localFallbackAvailable: boolean;
|
|
76
|
+
readonly reason: string;
|
|
77
|
+
}
|
|
78
|
+
export interface AgentContextCompaction {
|
|
79
|
+
readonly schemaVersion: "omk.task-compaction.v1";
|
|
80
|
+
readonly contract: unknown;
|
|
81
|
+
readonly diagnostics: Readonly<Record<string, unknown>>;
|
|
82
|
+
readonly artifactRef?: string;
|
|
83
|
+
}
|
|
61
84
|
export interface AgentContext {
|
|
62
85
|
readonly runId: string;
|
|
63
86
|
readonly nodeId: string;
|
|
@@ -72,6 +95,9 @@ export interface AgentContext {
|
|
|
72
95
|
}>;
|
|
73
96
|
readonly goalContext?: unknown;
|
|
74
97
|
readonly workerManifest?: unknown;
|
|
98
|
+
readonly compaction?: AgentContextCompaction;
|
|
99
|
+
/** Freedomd sovereignty decision surfaced to runtime adapters. */
|
|
100
|
+
readonly sovereignty?: AgentTaskSovereignty;
|
|
75
101
|
readonly abortSignal?: AbortSignal;
|
|
76
102
|
readonly cwd?: string;
|
|
77
103
|
readonly env?: Record<string, string>;
|
|
@@ -105,8 +131,11 @@ export interface AgentTask {
|
|
|
105
131
|
readonly tools: ToolManifest;
|
|
106
132
|
readonly providerPolicy: ProviderPolicy;
|
|
107
133
|
readonly capabilities: CapabilityManifest;
|
|
134
|
+
readonly safety: AgentTaskSafety;
|
|
108
135
|
/** Images/files attached to this task (clipboard paste, --image, drag). */
|
|
109
136
|
readonly attachments?: readonly AgentTaskAttachment[];
|
|
137
|
+
/** Freedomd sovereignty decision attached by retention/jurisdiction gates. */
|
|
138
|
+
readonly sovereignty?: AgentTaskSovereignty;
|
|
110
139
|
}
|
|
111
140
|
export interface AgentResult {
|
|
112
141
|
readonly output: string;
|
|
@@ -122,11 +151,11 @@ export interface AgentRuntime {
|
|
|
122
151
|
readonly displayName?: string;
|
|
123
152
|
readonly kind?: RuntimeKind;
|
|
124
153
|
readonly legacy?: boolean;
|
|
125
|
-
readonly runtimeMode
|
|
154
|
+
readonly runtimeMode: string;
|
|
126
155
|
readonly priority: number;
|
|
127
156
|
readonly capabilities?: RuntimeCapabilities;
|
|
128
157
|
supports(capsule: ContextCapsule): boolean;
|
|
129
|
-
health?(): Promise<RuntimeHealth>;
|
|
158
|
+
health?(input?: RuntimeHealthProbeRequest): Promise<RuntimeHealth>;
|
|
130
159
|
runNode(capsule: ContextCapsule, signal: AbortSignal): Promise<AgentRunResult>;
|
|
131
160
|
execute?(task: AgentTask): Promise<AgentResult>;
|
|
132
161
|
}
|
|
@@ -3,16 +3,29 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Each runtime wraps a specific Kimi/provider invocation mode.
|
|
5
5
|
*/
|
|
6
|
+
import { sanitizeRuntimeStderrResult } from "./private-stderr.js";
|
|
6
7
|
export function toTaskResult(result) {
|
|
8
|
+
const runtimeId = typeof result.metadata?.selectedRuntime === "string"
|
|
9
|
+
? result.metadata.selectedRuntime
|
|
10
|
+
: typeof result.metadata?.runtime === "string"
|
|
11
|
+
? result.metadata.runtime
|
|
12
|
+
: undefined;
|
|
13
|
+
const sanitized = sanitizeRuntimeStderrResult(result, {
|
|
14
|
+
runId: typeof result.metadata?.runId === "string" ? result.metadata.runId : process.env.OMK_RUN_ID,
|
|
15
|
+
nodeId: typeof result.metadata?.nodeId === "string" ? result.metadata.nodeId : process.env.OMK_NODE_ID,
|
|
16
|
+
runtimeId,
|
|
17
|
+
root: process.env.OMK_PROJECT_ROOT ?? process.cwd(),
|
|
18
|
+
env: process.env,
|
|
19
|
+
});
|
|
7
20
|
return {
|
|
8
|
-
success:
|
|
9
|
-
exitCode:
|
|
10
|
-
stdout:
|
|
11
|
-
stderr:
|
|
21
|
+
success: sanitized.success,
|
|
22
|
+
exitCode: sanitized.exitCode,
|
|
23
|
+
stdout: sanitized.stdout,
|
|
24
|
+
stderr: sanitized.stderr,
|
|
12
25
|
metadata: {
|
|
13
|
-
...
|
|
14
|
-
...(
|
|
15
|
-
...(
|
|
26
|
+
...sanitized.metadata,
|
|
27
|
+
...(sanitized.tokenUsage != null && { tokenUsage: sanitized.tokenUsage }),
|
|
28
|
+
...(sanitized.toolCalls != null && sanitized.toolCalls.length > 0 && { toolCalls: sanitized.toolCalls }),
|
|
16
29
|
},
|
|
17
30
|
};
|
|
18
31
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AgentRuntime, AgentTask } from "./agent-runtime.js";
|
|
2
|
+
export type RuntimeMode = "api" | "cli" | "wire" | "mcp" | "local" | "composite" | string;
|
|
3
|
+
export type AuthorityOperation = "read" | "review" | "write" | "patch" | "shell" | "mcp" | "merge" | "vision" | "toolCalling";
|
|
4
|
+
export interface RuntimeAuthorityMatrixEntry {
|
|
5
|
+
readonly providerId: string;
|
|
6
|
+
readonly runtimeMode: RuntimeMode;
|
|
7
|
+
readonly authorities: readonly AuthorityOperation[];
|
|
8
|
+
readonly advisory: boolean;
|
|
9
|
+
readonly notes?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const RUNTIME_AUTHORITY_MATRIX: readonly RuntimeAuthorityMatrixEntry[];
|
|
12
|
+
export declare function runtimeProviderId(runtime: Pick<AgentRuntime, "providerId" | "id">): string;
|
|
13
|
+
export declare function runtimeModeOf(runtime: Pick<AgentRuntime, "runtimeMode" | "kind" | "id">): RuntimeMode;
|
|
14
|
+
export declare function getRuntimeAuthorityEntry(runtime: Pick<AgentRuntime, "providerId" | "runtimeMode" | "kind" | "id">): RuntimeAuthorityMatrixEntry | undefined;
|
|
15
|
+
export declare function authoritiesForRuntime(runtime: Pick<AgentRuntime, "providerId" | "runtimeMode" | "kind" | "id" | "capabilities">): readonly AuthorityOperation[];
|
|
16
|
+
export declare function runtimeIsAdvisory(runtime: Pick<AgentRuntime, "providerId" | "runtimeMode" | "kind" | "id" | "capabilities">): boolean;
|
|
17
|
+
export declare function requiredAuthorityForTask(task: Pick<AgentTask, "capabilities">): readonly AuthorityOperation[];
|
|
18
|
+
export declare function runtimeSatisfiesAuthority(runtime: AgentRuntime, task: AgentTask): {
|
|
19
|
+
ok: boolean;
|
|
20
|
+
missing: readonly AuthorityOperation[];
|
|
21
|
+
reason?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function authorityCapableProviderIds(required: readonly AuthorityOperation[]): string[];
|