open-multi-agent-kit 0.78.0 → 0.78.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 +56 -15
- package/MATURITY.md +6 -2
- package/README.md +125 -26
- package/ROADMAP.md +36 -28
- package/dist/cli/register-basic-commands.js +3 -2
- package/dist/cli/register-mcp-dag-cron-screenshot-commands.js +2 -0
- package/dist/cli/register-spec-agent-goal-commands.js +45 -0
- package/dist/cli/register-tool-commands.js +11 -0
- package/dist/cli/register-workflow-commands.js +1 -0
- package/dist/cli/registry/tooling.js +3 -2
- package/dist/cli/release-promotion-gate.d.ts +14 -0
- package/dist/cli/release-promotion-gate.js +71 -0
- package/dist/cli/v2/release-commands.d.ts +29 -0
- package/dist/cli/v2/release-commands.js +95 -0
- package/dist/commands/chat/core.js +5 -0
- package/dist/commands/chat/native-root-loop.js +74 -1
- package/dist/commands/chat/slash/commands/session.js +19 -1
- package/dist/commands/dag-from-spec.d.ts +1 -0
- package/dist/commands/dag-from-spec.js +61 -1
- package/dist/commands/goal-interview.d.ts +18 -0
- package/dist/commands/goal-interview.js +396 -0
- package/dist/commands/graph.d.ts +62 -0
- package/dist/commands/graph.js +182 -0
- package/dist/commands/merge.d.ts +1 -0
- package/dist/commands/merge.js +88 -0
- package/dist/commands/parallel/core.js +3 -3
- package/dist/commands/provider.js +5 -3
- package/dist/commands/star.js +6 -1
- package/dist/commands/summary.d.ts +4 -1
- package/dist/commands/summary.js +103 -1
- package/dist/commands/team.d.ts +1 -0
- package/dist/commands/team.js +38 -0
- package/dist/contracts/interview.d.ts +106 -0
- package/dist/contracts/interview.js +9 -0
- package/dist/contracts/provider-health.d.ts +42 -0
- package/dist/contracts/provider-health.js +9 -0
- package/dist/evidence/index.d.ts +4 -0
- package/dist/evidence/index.js +2 -0
- package/dist/evidence/proof-trust-cli.d.ts +8 -0
- package/dist/evidence/proof-trust-cli.js +27 -0
- package/dist/evidence/proof-trust.d.ts +14 -0
- package/dist/evidence/proof-trust.js +381 -0
- package/dist/evidence/regression-proof-matrix.d.ts +42 -0
- package/dist/evidence/regression-proof-matrix.js +72 -0
- package/dist/goal/intent-frame.d.ts +30 -0
- package/dist/goal/intent-frame.js +39 -9
- package/dist/goal/interview-assimilation.d.ts +13 -0
- package/dist/goal/interview-assimilation.js +383 -0
- package/dist/goal/interview-question-bank.d.ts +11 -0
- package/dist/goal/interview-question-bank.js +225 -0
- package/dist/goal/interview-scoring.d.ts +31 -0
- package/dist/goal/interview-scoring.js +187 -0
- package/dist/goal/interview-session.d.ts +25 -0
- package/dist/goal/interview-session.js +116 -0
- package/dist/input/input-envelope.d.ts +22 -0
- package/dist/input/input-envelope.js +1 -0
- package/dist/memory/local-graph-memory-store.d.ts +15 -0
- package/dist/memory/local-graph-memory-store.js +176 -0
- package/dist/memory/memory-store.d.ts +18 -0
- package/dist/memory/memory-store.js +18 -0
- package/dist/orchestration/adaptorch-topology.d.ts +59 -0
- package/dist/orchestration/adaptorch-topology.js +194 -0
- package/dist/orchestration/capability-routing.d.ts +23 -0
- package/dist/orchestration/capability-routing.js +56 -0
- package/dist/orchestration/dag-compiler-types.d.ts +3 -0
- package/dist/orchestration/dag-compiler.js +14 -1
- package/dist/orchestration/parallel-orchestrator.d.ts +6 -0
- package/dist/orchestration/parallel-orchestrator.js +31 -0
- package/dist/providers/provider-health.d.ts +39 -0
- package/dist/providers/provider-health.js +161 -0
- package/dist/runtime/advanced-control-loop.d.ts +60 -0
- package/dist/runtime/advanced-control-loop.js +136 -0
- package/dist/runtime/agent-runtime.d.ts +10 -0
- package/dist/runtime/blast-radius.d.ts +10 -0
- package/dist/runtime/blast-radius.js +14 -0
- package/dist/runtime/context-broker.d.ts +13 -4
- package/dist/runtime/context-broker.js +14 -1
- package/dist/runtime/contracts/evidence.d.ts +87 -0
- package/dist/runtime/contracts/evidence.js +7 -0
- package/dist/runtime/contracts/router-v2.d.ts +44 -0
- package/dist/runtime/contracts/router-v2.js +4 -0
- package/dist/runtime/contracts/weakness-remediation.d.ts +67 -0
- package/dist/runtime/contracts/weakness-remediation.js +36 -0
- package/dist/runtime/headroom-policy.d.ts +37 -0
- package/dist/runtime/headroom-policy.js +122 -0
- package/dist/runtime/kimi-api-runtime.js +59 -1
- package/dist/runtime/ouroboros-policy.d.ts +57 -0
- package/dist/runtime/ouroboros-policy.js +134 -0
- package/dist/runtime/proof-bundle-trust.d.ts +74 -0
- package/dist/runtime/proof-bundle-trust.js +100 -0
- package/dist/runtime/provider-maturity-gate.d.ts +41 -0
- package/dist/runtime/provider-maturity-gate.js +101 -0
- package/dist/runtime/public-surface.d.ts +93 -0
- package/dist/runtime/public-surface.js +146 -0
- package/dist/runtime/router-v2-scoring.d.ts +11 -0
- package/dist/runtime/router-v2-scoring.js +151 -0
- package/dist/runtime/runtime-backed-task-runner.js +9 -1
- package/dist/runtime/tool-dispatch-contracts.d.ts +57 -1
- package/dist/runtime/tool-dispatch-contracts.js +79 -3
- package/dist/runtime/weakness-remediation-index.d.ts +27 -0
- package/dist/runtime/weakness-remediation-index.js +37 -0
- package/dist/safety/tool-authority-gate.d.ts +62 -0
- package/dist/safety/tool-authority-gate.js +108 -0
- package/dist/schema/proof-bundle.schema.d.ts +26 -26
- package/dist/schema/provider.schema.d.ts +4 -4
- package/dist/util/clipboard-image.d.ts +49 -0
- package/dist/util/clipboard-image.js +263 -0
- package/dist/util/first-run-star.d.ts +9 -0
- package/dist/util/first-run-star.js +42 -1
- package/dist/util/terminal-input.d.ts +20 -0
- package/dist/util/terminal-input.js +32 -0
- package/dist/util/update-check.d.ts +6 -1
- package/dist/util/update-check.js +35 -1
- package/docs/2026-06-08/critical-issues.md +20 -0
- package/docs/2026-06-08/improvements.md +14 -0
- package/docs/2026-06-08/init-checklist.md +25 -0
- package/docs/2026-06-08/plan.md +20 -0
- package/docs/2026-06-09/critical-issues.md +20 -0
- package/docs/2026-06-09/improvements.md +14 -0
- package/docs/2026-06-09/init-checklist.md +25 -0
- package/docs/2026-06-09/plan.md +20 -0
- package/docs/getting-started.md +31 -3
- package/docs/github-organic-promotion.md +127 -0
- package/docs/integrations/ouroboros.md +96 -0
- package/docs/native-root-runtime-algorithms.md +301 -0
- package/docs/provider-maturity.md +1 -1
- package/docs/versioning.md +3 -3
- package/package.json +4 -3
- package/readmeasset/ASSET_INDEX.md +1 -0
- package/templates/skills/agents/omk-agent-reach-websearch/SKILL.md +55 -0
- package/templates/skills/kimi/omk-agent-reach-websearch/SKILL.md +55 -0
- package/dist/native/linux-x64/omk-safety +0 -0
package/dist/commands/merge.js
CHANGED
|
@@ -9,7 +9,95 @@ import { runQualityGate } from "../mcp/quality-gate.js";
|
|
|
9
9
|
import { readTextFile } from "../util/fs.js";
|
|
10
10
|
import { getOmkResourceSettings } from "../util/resource-profile.js";
|
|
11
11
|
import { defaultScopedRoleAgentFile, writeScopedAgentFile } from "../util/scoped-agent-file.js";
|
|
12
|
+
import { createOmkJsonEnvelope } from "../util/json-envelope.js";
|
|
13
|
+
import { emitJson } from "../util/cli-contract.js";
|
|
14
|
+
/**
|
|
15
|
+
* JSON path for `omk merge --json`.
|
|
16
|
+
* Read-only preview: resolves the run, collects worktree diffs (git diff +
|
|
17
|
+
* `git apply --check`) and selects a winner by strategy, but does NOT run the
|
|
18
|
+
* reviewer, tests, patch apply, or quality gate. Emits exactly one
|
|
19
|
+
* omk.contract.v1 envelope (no banner, no ANSI) and never calls process.exit.
|
|
20
|
+
*/
|
|
21
|
+
async function emitMergeJson(options) {
|
|
22
|
+
const started = Date.now();
|
|
23
|
+
const root = getProjectRoot();
|
|
24
|
+
const strategy = (options.strategy ?? "first").trim().toLowerCase();
|
|
25
|
+
const dryRun = Boolean(options.dryRun);
|
|
26
|
+
const emitNotApplicable = (runId, code, message) => {
|
|
27
|
+
emitJson(createOmkJsonEnvelope({
|
|
28
|
+
command: "merge",
|
|
29
|
+
status: "not-applicable",
|
|
30
|
+
ok: false,
|
|
31
|
+
...(runId ? { runId } : {}),
|
|
32
|
+
data: { runId, strategy, dryRun, merged: null, conflicts: [], applied: 0 },
|
|
33
|
+
warnings: [{ code, message, recoverable: true, severity: "warning" }],
|
|
34
|
+
durationMs: Date.now() - started,
|
|
35
|
+
}));
|
|
36
|
+
};
|
|
37
|
+
if (!(await isGitRepo())) {
|
|
38
|
+
emitNotApplicable(null, "INTERNAL_ERROR", "Not a git repository.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const runsDir = getOmkPath("runs");
|
|
42
|
+
if (!(await pathExists(runsDir))) {
|
|
43
|
+
emitNotApplicable(null, "RUN_ARTIFACT_MISSING", "No runs found.");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
let runId = options.run ?? options.runId ?? "latest";
|
|
47
|
+
if (runId === "latest") {
|
|
48
|
+
const entries = await readdir(runsDir, { withFileTypes: true });
|
|
49
|
+
const runs = entries.filter((e) => e.isDirectory()).sort().reverse();
|
|
50
|
+
if (runs.length === 0) {
|
|
51
|
+
emitNotApplicable(null, "RUN_ARTIFACT_MISSING", "No runs found.");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
runId = runs[0].name;
|
|
55
|
+
}
|
|
56
|
+
const worktreesDir = getOmkPath(`worktrees/${runId}`);
|
|
57
|
+
if (!(await pathExists(worktreesDir))) {
|
|
58
|
+
emitNotApplicable(runId, "RUN_ARTIFACT_MISSING", "No worktrees found for run.");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const workerNames = await readdir(worktreesDir, { withFileTypes: true }).then((e) => e.filter((d) => d.isDirectory()).map((d) => d.name));
|
|
62
|
+
const currentBranch = await getCurrentBranch();
|
|
63
|
+
if (!currentBranch) {
|
|
64
|
+
emitNotApplicable(runId, "INTERNAL_ERROR", "Could not determine current branch.");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const workers = [];
|
|
68
|
+
for (const name of workerNames) {
|
|
69
|
+
const wtPath = join(worktreesDir, name);
|
|
70
|
+
const diffResult = await runShell("git", ["-C", wtPath, "diff", currentBranch], { timeout: 15000 });
|
|
71
|
+
if (diffResult.failed || !diffResult.stdout.trim())
|
|
72
|
+
continue;
|
|
73
|
+
const diff = diffResult.stdout;
|
|
74
|
+
const diffLines = diff.split("\n").length;
|
|
75
|
+
const applyCheck = await runShell("git", ["apply", "--check"], { cwd: root, input: diff, timeout: 15000 });
|
|
76
|
+
workers.push({ name, path: wtPath, diff, diffLines, canApply: !applyCheck.failed });
|
|
77
|
+
}
|
|
78
|
+
const winner = selectWinner(workers, strategy);
|
|
79
|
+
const data = {
|
|
80
|
+
runId,
|
|
81
|
+
strategy,
|
|
82
|
+
dryRun,
|
|
83
|
+
merged: winner?.name ?? null,
|
|
84
|
+
conflicts: workers.filter((w) => !w.canApply).map((w) => w.name),
|
|
85
|
+
applied: 0,
|
|
86
|
+
};
|
|
87
|
+
emitJson(createOmkJsonEnvelope({
|
|
88
|
+
command: "merge",
|
|
89
|
+
status: workers.length === 0 ? "not-applicable" : "dry-run",
|
|
90
|
+
ok: workers.length > 0,
|
|
91
|
+
runId,
|
|
92
|
+
data,
|
|
93
|
+
durationMs: Date.now() - started,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
12
96
|
export async function mergeCommand(options) {
|
|
97
|
+
if (options.json === true || process.argv.includes("--json")) {
|
|
98
|
+
await emitMergeJson(options);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
13
101
|
const root = getProjectRoot();
|
|
14
102
|
const strategy = (options.strategy ?? "first").trim().toLowerCase();
|
|
15
103
|
const dryRun = Boolean(options.dryRun);
|
|
@@ -11,7 +11,7 @@ import { writeMemoryRecallSummary } from "../../util/chat-startup.js";
|
|
|
11
11
|
import { normalizeProviderPolicy, parseProviderModelArg } from "../../providers/model-registry.js";
|
|
12
12
|
import { parseExecutionPromptPolicy } from "../../util/execution-selection.js";
|
|
13
13
|
import { analyzeUserIntent } from "../../goal/intake.js";
|
|
14
|
-
import { buildIntentFrame } from "../../goal/intent-frame.js";
|
|
14
|
+
import { buildIntentFrame, buildIntentFrameWithOuroboros } from "../../goal/intent-frame.js";
|
|
15
15
|
import { renderCapabilityRoutingArtifact } from "../../orchestration/capability-routing.js";
|
|
16
16
|
import { ensureCompletionArtifactContract } from "../../orchestration/completion-artifacts.js";
|
|
17
17
|
import { buildParallelRouteDecision, resolveParallelCommandExecutionDecision, createInteractiveRunState, createExecutableDagFromState } from "./orchestrator.js";
|
|
@@ -70,7 +70,7 @@ export async function parallelCommand(goal, options = {}) {
|
|
|
70
70
|
const { loadSpecDag } = await import("../dag-from-spec.js");
|
|
71
71
|
const specDag = await loadSpecDag(options.fromSpec, { parallel: true });
|
|
72
72
|
effectiveGoal = goal ?? `spec: ${specDag.nodes[0]?.name ?? options.fromSpec}`;
|
|
73
|
-
intentFrame =
|
|
73
|
+
intentFrame = await buildIntentFrameWithOuroboros(effectiveGoal);
|
|
74
74
|
specNodes = specDag.nodes.map((node) => {
|
|
75
75
|
const { status: _status, retries: _retries, ...def } = node;
|
|
76
76
|
void _status;
|
|
@@ -79,7 +79,7 @@ export async function parallelCommand(goal, options = {}) {
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
else {
|
|
82
|
-
intentFrame = intentFrame ??
|
|
82
|
+
intentFrame = intentFrame ?? (await buildIntentFrameWithOuroboros(effectiveGoal));
|
|
83
83
|
}
|
|
84
84
|
const resolvedIntent = options.intent ?? analyzeUserIntent(effectiveGoal);
|
|
85
85
|
const executionDecision = options.executionDecision ?? await resolveParallelCommandExecutionDecision({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { checkDeepSeekBalance } from "../providers/deepseek/deepseek-balance.js";
|
|
2
2
|
import { forceDisableDeepSeek, getDeepSeekProviderStatus, resolveDeepSeekApiKey, setDeepSeekApiKey, setDeepSeekEnabled, } from "../providers/deepseek/deepseek-config.js";
|
|
3
3
|
import { normalizeProviderId, providerDoctorStatus, readProviderRegistry, setProviderDefaults, setProviderConfig, setProviderEnabled, } from "../providers/model-registry.js";
|
|
4
|
+
import { toProviderHealth } from "../providers/provider-health.js";
|
|
4
5
|
import { maskSensitiveText } from "../util/secret-mask.js";
|
|
5
6
|
import { status, label, header, style } from "../util/theme.js";
|
|
6
7
|
const PROVIDER_PROFILES = [
|
|
@@ -95,7 +96,7 @@ export async function providerDoctorCommand(provider, options = {}) {
|
|
|
95
96
|
const normalized = normalizeProviderId(target);
|
|
96
97
|
const payload = await providerDoctorStatus(normalized === "auto" ? "kimi" : normalized);
|
|
97
98
|
if (options.json) {
|
|
98
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
99
|
+
console.log(JSON.stringify({ ...payload, health: toProviderHealth(payload) }, null, 2));
|
|
99
100
|
}
|
|
100
101
|
else {
|
|
101
102
|
console.log(header("Provider doctor"));
|
|
@@ -125,13 +126,14 @@ export async function providerDoctorCommand(provider, options = {}) {
|
|
|
125
126
|
disableForRun: true,
|
|
126
127
|
};
|
|
127
128
|
if (options.json) {
|
|
128
|
-
|
|
129
|
+
const deepseekDoctor = {
|
|
129
130
|
...result,
|
|
130
131
|
enabled: providerStatus.enabled,
|
|
131
132
|
disabledBy: providerStatus.disabledBy,
|
|
132
133
|
apiKeySet: providerStatus.apiKeySet,
|
|
133
134
|
apiKeySource: providerStatus.apiKeySource,
|
|
134
|
-
}
|
|
135
|
+
};
|
|
136
|
+
console.log(JSON.stringify({ ...deepseekDoctor, health: toProviderHealth(deepseekDoctor) }, null, 2));
|
|
135
137
|
}
|
|
136
138
|
else {
|
|
137
139
|
console.log(header("Provider doctor"));
|
package/dist/commands/star.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { starGitHubRepo, getStarPromptSummary } from "../util/first-run-star.js";
|
|
1
|
+
import { starGitHubRepo, getStarPromptSummary, openRepoInBrowser, parseGitHubRepoSlug } from "../util/first-run-star.js";
|
|
2
2
|
import { OMK_REPO_URL } from "../util/version.js";
|
|
3
|
+
import { style } from "../util/theme.js";
|
|
3
4
|
export async function starCommand(options = {}) {
|
|
4
5
|
if (options.status) {
|
|
5
6
|
const summary = await getStarPromptSummary();
|
|
@@ -25,6 +26,10 @@ export async function starCommand(options = {}) {
|
|
|
25
26
|
}
|
|
26
27
|
catch (e) {
|
|
27
28
|
console.error("Failed to star:", e instanceof Error ? e.message : String(e));
|
|
29
|
+
const slug = parseGitHubRepoSlug(OMK_REPO_URL);
|
|
30
|
+
if (slug)
|
|
31
|
+
console.error(style.gray(`Visit ${style.cream(`https://github.com/${slug}`)} to star manually.`));
|
|
32
|
+
await openRepoInBrowser(OMK_REPO_URL);
|
|
28
33
|
process.exit(1);
|
|
29
34
|
}
|
|
30
35
|
}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface SummaryLatestCommandOptions {
|
|
2
|
+
json?: boolean;
|
|
3
|
+
}
|
|
4
|
+
export declare function summaryLatestCommand(options?: SummaryLatestCommandOptions): Promise<void>;
|
|
2
5
|
export declare function summaryShowCommand(runId?: string): Promise<void>;
|
package/dist/commands/summary.js
CHANGED
|
@@ -2,6 +2,8 @@ import { readFile, writeFile, readdir, stat } from "fs/promises";
|
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
import { getProjectRoot, pathExists, getRunsDir, getRunPath } from "../util/fs.js";
|
|
4
4
|
import { style, header, status, label } from "../util/theme.js";
|
|
5
|
+
import { createOmkJsonEnvelope } from "../util/json-envelope.js";
|
|
6
|
+
import { emitJson } from "../util/cli-contract.js";
|
|
5
7
|
function computeProviderRouting(nodes) {
|
|
6
8
|
const byProvider = {};
|
|
7
9
|
const fallbacks = [];
|
|
@@ -257,7 +259,107 @@ function generateReportMd(s) {
|
|
|
257
259
|
lines.push("");
|
|
258
260
|
return lines.join("\n");
|
|
259
261
|
}
|
|
260
|
-
|
|
262
|
+
function deriveRunRollupStatus(s) {
|
|
263
|
+
if (s.failed > 0)
|
|
264
|
+
return "failed";
|
|
265
|
+
if (s.blocked > 0)
|
|
266
|
+
return "blocked";
|
|
267
|
+
if (s.running > 0 || s.pending > 0)
|
|
268
|
+
return "running";
|
|
269
|
+
if (s.totalNodes > 0 && s.done === s.totalNodes)
|
|
270
|
+
return "passed";
|
|
271
|
+
return "partial";
|
|
272
|
+
}
|
|
273
|
+
function buildSummaryJsonData(summary) {
|
|
274
|
+
const data = {
|
|
275
|
+
runId: summary.runId,
|
|
276
|
+
status: deriveRunRollupStatus(summary),
|
|
277
|
+
nodes: { total: summary.totalNodes, passed: summary.done, failed: summary.failed },
|
|
278
|
+
successRate: summary.successRate,
|
|
279
|
+
durationMs: summary.durationMs,
|
|
280
|
+
startedAt: summary.startedAt,
|
|
281
|
+
};
|
|
282
|
+
if (summary.completedAt)
|
|
283
|
+
data.completedAt = summary.completedAt;
|
|
284
|
+
if (summary.providerRouting.attempts > 0) {
|
|
285
|
+
data.providerRoute = {
|
|
286
|
+
attempts: summary.providerRouting.attempts,
|
|
287
|
+
byProvider: summary.providerRouting.byProvider,
|
|
288
|
+
fallbacks: summary.providerRouting.fallbacks.length,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
const evidenceRefs = summary.nodes.flatMap((node) => (node.evidence ?? []).map((e) => ({ nodeId: node.id, gate: e.gate, passed: e.passed })));
|
|
292
|
+
if (evidenceRefs.length > 0)
|
|
293
|
+
data.evidenceRefs = evidenceRefs;
|
|
294
|
+
return data;
|
|
295
|
+
}
|
|
296
|
+
function emptySummaryJsonData(runId) {
|
|
297
|
+
return {
|
|
298
|
+
runId,
|
|
299
|
+
status: "no-runs",
|
|
300
|
+
nodes: { total: 0, passed: 0, failed: 0 },
|
|
301
|
+
successRate: 0,
|
|
302
|
+
durationMs: 0,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Read-only JSON path for `omk summary --json`.
|
|
307
|
+
* Emits EXACTLY ONE omk.contract.v1 envelope to stdout (no banner, no ANSI),
|
|
308
|
+
* never calls process.exit, and never writes summary.md/report.md side effects.
|
|
309
|
+
*/
|
|
310
|
+
async function emitSummaryJson() {
|
|
311
|
+
const started = Date.now();
|
|
312
|
+
const root = getProjectRoot();
|
|
313
|
+
const latestId = await findLatestRunId(root);
|
|
314
|
+
if (!latestId) {
|
|
315
|
+
emitJson(createOmkJsonEnvelope({
|
|
316
|
+
command: "summary",
|
|
317
|
+
status: "not-applicable",
|
|
318
|
+
ok: false,
|
|
319
|
+
data: emptySummaryJsonData(null),
|
|
320
|
+
warnings: [
|
|
321
|
+
{ code: "RUN_ARTIFACT_MISSING", message: "No runs found.", recoverable: true, severity: "warning" },
|
|
322
|
+
],
|
|
323
|
+
durationMs: Date.now() - started,
|
|
324
|
+
}));
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const state = await loadRunState(root, latestId);
|
|
328
|
+
if (!state) {
|
|
329
|
+
emitJson(createOmkJsonEnvelope({
|
|
330
|
+
command: "summary",
|
|
331
|
+
status: "not-applicable",
|
|
332
|
+
ok: false,
|
|
333
|
+
runId: latestId,
|
|
334
|
+
data: emptySummaryJsonData(latestId),
|
|
335
|
+
warnings: [
|
|
336
|
+
{
|
|
337
|
+
code: "RUN_ARTIFACT_MISSING",
|
|
338
|
+
message: `Run state not found for ${latestId}`,
|
|
339
|
+
recoverable: true,
|
|
340
|
+
severity: "warning",
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
durationMs: Date.now() - started,
|
|
344
|
+
}));
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const summary = computeSummary(state);
|
|
348
|
+
emitJson(createOmkJsonEnvelope({
|
|
349
|
+
command: "summary",
|
|
350
|
+
status: "passed",
|
|
351
|
+
ok: true,
|
|
352
|
+
runId: summary.runId,
|
|
353
|
+
data: buildSummaryJsonData(summary),
|
|
354
|
+
durationMs: Date.now() - started,
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
export async function summaryLatestCommand(options = {}) {
|
|
358
|
+
const jsonMode = options.json === true || process.argv.includes("--json");
|
|
359
|
+
if (jsonMode) {
|
|
360
|
+
await emitSummaryJson();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
261
363
|
const root = await getProjectRoot();
|
|
262
364
|
const latestId = await findLatestRunId(root);
|
|
263
365
|
if (!latestId) {
|
package/dist/commands/team.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { TeamRuntimeStatus } from "../contracts/orchestration.js";
|
|
|
2
2
|
export declare function teamCommand(options?: {
|
|
3
3
|
workers?: string;
|
|
4
4
|
runId?: string;
|
|
5
|
+
json?: boolean;
|
|
5
6
|
}): Promise<void>;
|
|
6
7
|
export declare function writeTeamRunState(root: string, runId: string, workerCount: number, session?: string, profile?: string): Promise<string>;
|
|
7
8
|
export declare function buildExpectedTeamRuntimeStatus(session: string, statePath: string, workerCount: number, runtimeStatus: TeamRuntimeStatus["status"], presentWindows?: Map<string, number>): TeamRuntimeStatus;
|
package/dist/commands/team.js
CHANGED
|
@@ -8,7 +8,45 @@ import { join } from "path";
|
|
|
8
8
|
import { refreshRunStateEstimate } from "../orchestration/run-state.js";
|
|
9
9
|
import { createInteractiveRunState as createParallelRunState } from "./parallel/orchestrator.js";
|
|
10
10
|
import { ensureCompletionArtifactContract } from "../orchestration/completion-artifacts.js";
|
|
11
|
+
import { createOmkJsonEnvelope } from "../util/json-envelope.js";
|
|
12
|
+
import { emitJson } from "../util/cli-contract.js";
|
|
13
|
+
/**
|
|
14
|
+
* JSON path for `omk team --json`.
|
|
15
|
+
* Read-only describe: reports the expected team layout for the resolved run
|
|
16
|
+
* WITHOUT spawning or attaching tmux, so stdout stays exactly one
|
|
17
|
+
* omk.contract.v1 envelope (no banner, no ANSI) and never blocks/exits.
|
|
18
|
+
*/
|
|
19
|
+
async function emitTeamJson(options) {
|
|
20
|
+
const started = Date.now();
|
|
21
|
+
const root = getProjectRoot();
|
|
22
|
+
const resources = await getOmkResourceSettings();
|
|
23
|
+
const workerCount = normalizeWorkerCount(options.workers, resources.maxWorkers);
|
|
24
|
+
const runId = options.runId ?? `team-${new Date().toISOString().replace(/[:.]/g, "-")}`;
|
|
25
|
+
const statePath = getRunPath(runId, "state.json", root);
|
|
26
|
+
const expected = buildExpectedTeamRuntimeStatus("omk-team", statePath, workerCount, "starting");
|
|
27
|
+
const data = {
|
|
28
|
+
teamId: runId,
|
|
29
|
+
members: expected.windows.map((window) => ({
|
|
30
|
+
name: window.name,
|
|
31
|
+
role: window.role,
|
|
32
|
+
nodeId: window.nodeId,
|
|
33
|
+
})),
|
|
34
|
+
statePath,
|
|
35
|
+
};
|
|
36
|
+
emitJson(createOmkJsonEnvelope({
|
|
37
|
+
command: "team",
|
|
38
|
+
status: "passed",
|
|
39
|
+
ok: true,
|
|
40
|
+
runId,
|
|
41
|
+
data,
|
|
42
|
+
durationMs: Date.now() - started,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
11
45
|
export async function teamCommand(options = {}) {
|
|
46
|
+
if (options.json === true || process.argv.includes("--json")) {
|
|
47
|
+
await emitTeamJson(options);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
12
50
|
const root = getProjectRoot();
|
|
13
51
|
const resources = await getOmkResourceSettings();
|
|
14
52
|
const workerCount = normalizeWorkerCount(options.workers, resources.maxWorkers);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { GoalSpec, RiskLevel } from "./goal.js";
|
|
2
|
+
export declare const INTERVIEW_SCHEMA_VERSION: "omk.interview.v1";
|
|
3
|
+
export declare const INTERVIEW_DELTA_SCHEMA_VERSION: "omk.interview-delta.v1";
|
|
4
|
+
export type InterviewDepth = "light" | "standard" | "deep";
|
|
5
|
+
export type InterviewMode = "create" | "refine";
|
|
6
|
+
export type InterviewQuestionKind = "objective" | "success-criteria" | "artifact" | "constraint" | "non-goal" | "risk" | "authority" | "evidence" | "dependency" | "rollback";
|
|
7
|
+
/**
|
|
8
|
+
* Field on GoalSpec (or a derived structure) that an answer is meant to fill.
|
|
9
|
+
* A question without a targetField is low quality and must be dropped.
|
|
10
|
+
*/
|
|
11
|
+
export type InterviewTargetField = "objective" | "successCriteria" | "expectedArtifacts" | "constraints" | "nonGoals" | "risks" | "riskLevel" | "intentFrame" | "actionAtoms";
|
|
12
|
+
export interface InterviewQuestion {
|
|
13
|
+
id: string;
|
|
14
|
+
kind: InterviewQuestionKind;
|
|
15
|
+
prompt: string;
|
|
16
|
+
required: boolean;
|
|
17
|
+
targetField: InterviewTargetField;
|
|
18
|
+
/** 0..1 — how much answering reduces uncertainty about the goal. */
|
|
19
|
+
informationGain: number;
|
|
20
|
+
/** 0..1 — how much answering reduces execution risk. */
|
|
21
|
+
riskReduction: number;
|
|
22
|
+
/** 0..1 — how strongly the answer reshapes the execution DAG. */
|
|
23
|
+
dagImpact: number;
|
|
24
|
+
/** 0..1 — how strongly the answer strengthens evidence gates. */
|
|
25
|
+
evidenceImpact: number;
|
|
26
|
+
/** 0..1 — burden on the user (penalty). */
|
|
27
|
+
userCost: number;
|
|
28
|
+
/** Derived ranking score, 0..1, rounded to 2 decimals. */
|
|
29
|
+
score: number;
|
|
30
|
+
}
|
|
31
|
+
export interface InterviewAnswer {
|
|
32
|
+
questionId: string;
|
|
33
|
+
answer: string;
|
|
34
|
+
answeredAt: string;
|
|
35
|
+
skipped?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface InterviewFinding {
|
|
38
|
+
field: InterviewTargetField | string;
|
|
39
|
+
value: unknown;
|
|
40
|
+
sourceQuestionId: string;
|
|
41
|
+
/** 0..1 confidence that this finding is correct and explicit. */
|
|
42
|
+
confidence: number;
|
|
43
|
+
/** True when this finding contradicts an existing explicit value. */
|
|
44
|
+
conflict?: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface InterviewCompleteness {
|
|
47
|
+
/** Weighted overall completeness, 0..1. */
|
|
48
|
+
overall: number;
|
|
49
|
+
objective: number;
|
|
50
|
+
successCriteria: number;
|
|
51
|
+
evidence: number;
|
|
52
|
+
artifacts: number;
|
|
53
|
+
constraints: number;
|
|
54
|
+
risks: number;
|
|
55
|
+
authority: number;
|
|
56
|
+
/** Required fields with no usable value yet. */
|
|
57
|
+
criticalMissing: string[];
|
|
58
|
+
/** Unresolved contradictions between answers and existing values. */
|
|
59
|
+
contradictions: string[];
|
|
60
|
+
}
|
|
61
|
+
export type InterviewDeltaField = keyof GoalSpec | "successCriteria" | "expectedArtifacts" | "riskLevel";
|
|
62
|
+
export interface InterviewSpecChange {
|
|
63
|
+
field: InterviewDeltaField;
|
|
64
|
+
op: "add" | "replace" | "remove";
|
|
65
|
+
value: unknown;
|
|
66
|
+
sourceQuestionId: string;
|
|
67
|
+
/** 0..1 confidence used by the conflict resolver. */
|
|
68
|
+
confidence: number;
|
|
69
|
+
}
|
|
70
|
+
export interface InterviewSpecDelta {
|
|
71
|
+
schemaVersion: typeof INTERVIEW_DELTA_SCHEMA_VERSION;
|
|
72
|
+
goalId?: string;
|
|
73
|
+
changes: InterviewSpecChange[];
|
|
74
|
+
}
|
|
75
|
+
export type InterviewStatus = "open" | "complete" | "blocked";
|
|
76
|
+
export interface InterviewSession {
|
|
77
|
+
schemaVersion: typeof INTERVIEW_SCHEMA_VERSION;
|
|
78
|
+
sessionId: string;
|
|
79
|
+
goalId?: string;
|
|
80
|
+
mode: InterviewMode;
|
|
81
|
+
depth: InterviewDepth;
|
|
82
|
+
createdAt: string;
|
|
83
|
+
updatedAt: string;
|
|
84
|
+
rawPrompt?: string;
|
|
85
|
+
/** Ambiguity score 0..1; higher means more interview is needed. */
|
|
86
|
+
ambiguity: number;
|
|
87
|
+
questions: InterviewQuestion[];
|
|
88
|
+
answers: InterviewAnswer[];
|
|
89
|
+
findings: InterviewFinding[];
|
|
90
|
+
completeness: InterviewCompleteness;
|
|
91
|
+
specDelta: InterviewSpecDelta;
|
|
92
|
+
status: InterviewStatus;
|
|
93
|
+
}
|
|
94
|
+
/** Inputs the question bank needs to derive candidate questions. */
|
|
95
|
+
export interface InterviewSeed {
|
|
96
|
+
rawPrompt: string;
|
|
97
|
+
riskLevel?: RiskLevel;
|
|
98
|
+
goal?: GoalSpec;
|
|
99
|
+
}
|
|
100
|
+
/** Result of applying a spec delta to a GoalSpec. */
|
|
101
|
+
export interface InterviewApplyResult {
|
|
102
|
+
goal: GoalSpec;
|
|
103
|
+
appliedChanges: InterviewSpecChange[];
|
|
104
|
+
skippedChanges: InterviewSpecChange[];
|
|
105
|
+
contradictions: string[];
|
|
106
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Contract: src/contracts/interview.ts
|
|
2
|
+
// Owner: Contract Worker (Deep Interview phase 0)
|
|
3
|
+
// OMK Deep Interview — uncertainty reducer for goal-driven agent runs.
|
|
4
|
+
//
|
|
5
|
+
// Read-only for downstream interview modules. These types are the shared
|
|
6
|
+
// language for question banking, scoring, assimilation, session building,
|
|
7
|
+
// and the `omk goal interview` / `omk goal refine` CLI commands.
|
|
8
|
+
export const INTERVIEW_SCHEMA_VERSION = "omk.interview.v1";
|
|
9
|
+
export const INTERVIEW_DELTA_SCHEMA_VERSION = "omk.interview-delta.v1";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, provider-neutral health shape.
|
|
3
|
+
*
|
|
4
|
+
* This contract is intentionally additive: it is embedded alongside the
|
|
5
|
+
* existing `omk provider doctor <x> --json` payloads without removing or
|
|
6
|
+
* renaming any pre-existing keys. It never carries secret values — only
|
|
7
|
+
* boolean signals (e.g. `authOk`) and non-sensitive remediation hints.
|
|
8
|
+
*/
|
|
9
|
+
/** Classified failure category for a provider health check. */
|
|
10
|
+
export type ProviderFailureKind = "none" | "runtime" | "auth" | "model" | "quota" | "policy" | "transient" | "unknown";
|
|
11
|
+
/** Authority level a provider holds for a given capability lane. */
|
|
12
|
+
export type ProviderAuthorityLevel = "none" | "advisory" | "direct" | "full";
|
|
13
|
+
/**
|
|
14
|
+
* Normalized provider health snapshot.
|
|
15
|
+
*
|
|
16
|
+
* All fields are required so consumers can rely on a stable shape regardless
|
|
17
|
+
* of which provider produced it.
|
|
18
|
+
*/
|
|
19
|
+
export interface ProviderHealth {
|
|
20
|
+
/** Provider id (e.g. "kimi", "deepseek", "codex"). */
|
|
21
|
+
provider: string;
|
|
22
|
+
/** ISO-8601 timestamp of when the health snapshot was produced. */
|
|
23
|
+
checkedAt: string;
|
|
24
|
+
/** Runtime/transport reachable and enabled. */
|
|
25
|
+
runtimeOk: boolean;
|
|
26
|
+
/** Authentication satisfied (API key present or externally managed auth). */
|
|
27
|
+
authOk: boolean;
|
|
28
|
+
/** A resolvable default model is configured. */
|
|
29
|
+
modelOk: boolean;
|
|
30
|
+
/** No known quota/balance/rate-limit blocker. */
|
|
31
|
+
quotaOk: boolean;
|
|
32
|
+
/** Authority to perform write/merge work. */
|
|
33
|
+
writeAuthority: ProviderAuthorityLevel;
|
|
34
|
+
/** Authority to run shell/CLI work. */
|
|
35
|
+
shellAuthority: ProviderAuthorityLevel;
|
|
36
|
+
/** Authority to drive MCP tools. */
|
|
37
|
+
mcpAuthority: ProviderAuthorityLevel;
|
|
38
|
+
/** Classified failure category ("none" when healthy). */
|
|
39
|
+
failureKind: ProviderFailureKind;
|
|
40
|
+
/** Non-sensitive remediation hints (never includes secret values). */
|
|
41
|
+
remediation: string[];
|
|
42
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, provider-neutral health shape.
|
|
3
|
+
*
|
|
4
|
+
* This contract is intentionally additive: it is embedded alongside the
|
|
5
|
+
* existing `omk provider doctor <x> --json` payloads without removing or
|
|
6
|
+
* renaming any pre-existing keys. It never carries secret values — only
|
|
7
|
+
* boolean signals (e.g. `authOk`) and non-sensitive remediation hints.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
package/dist/evidence/index.d.ts
CHANGED
|
@@ -13,3 +13,7 @@ export { decideRepair } from "../orchestration/repair-policy.js";
|
|
|
13
13
|
export type { RepairContext } from "../orchestration/repair-policy.js";
|
|
14
14
|
export type { DecisionTraceStore } from "./decision-trace.js";
|
|
15
15
|
export { createDecisionTraceStore } from "./decision-trace.js";
|
|
16
|
+
export type { ProofTrustMvpEngine, ProofTrustResult } from "./proof-trust.js";
|
|
17
|
+
export { createProofTrustMvpEngine } from "./proof-trust.js";
|
|
18
|
+
export type { AlgorithmSpec, ReleaseCandidate, RegressionProofMatrixResult, RegressionProofMatrixEngine, RegressionProofMatrixOptions, } from "./regression-proof-matrix.js";
|
|
19
|
+
export { createRegressionProofMatrixEngine } from "./regression-proof-matrix.js";
|
package/dist/evidence/index.js
CHANGED
|
@@ -5,3 +5,5 @@ export { createDiagnosisEngine } from "./diagnosis.js";
|
|
|
5
5
|
export { createRunTraceStore } from "./run-trace.js";
|
|
6
6
|
export { decideRepair } from "../orchestration/repair-policy.js";
|
|
7
7
|
export { createDecisionTraceStore } from "./decision-trace.js";
|
|
8
|
+
export { createProofTrustMvpEngine } from "./proof-trust.js";
|
|
9
|
+
export { createRegressionProofMatrixEngine } from "./regression-proof-matrix.js";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Proof Trust CLI — thin wrapper around ProofTrustMvpEngine.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node dist/evidence/proof-trust-cli.js <runDir> <bundlePath>
|
|
7
|
+
*/
|
|
8
|
+
import { readFile } from "node:fs/promises";
|
|
9
|
+
import { createProofTrustMvpEngine } from "./proof-trust.js";
|
|
10
|
+
async function main() {
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const runDir = args[0] ?? ".omk/runs";
|
|
13
|
+
const bundlePath = args[1];
|
|
14
|
+
if (!bundlePath) {
|
|
15
|
+
console.error("Usage: proof-trust-cli <runDir> <bundlePath>");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const bundle = JSON.parse(await readFile(bundlePath, "utf8"));
|
|
19
|
+
const engine = createProofTrustMvpEngine();
|
|
20
|
+
const result = await engine.evaluate(runDir, bundle);
|
|
21
|
+
console.log(JSON.stringify(result, null, 2));
|
|
22
|
+
process.exit(result.missingFields.length > 0 ? 1 : 0);
|
|
23
|
+
}
|
|
24
|
+
main().catch((err) => {
|
|
25
|
+
console.error(err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proof Trust MVP — Algorithm 3
|
|
3
|
+
*
|
|
4
|
+
* Evaluates a proof bundle against a run directory, computing a trust score
|
|
5
|
+
* based on weighted field presence and validity.
|
|
6
|
+
*/
|
|
7
|
+
export interface ProofTrustMvpEngine {
|
|
8
|
+
evaluate(runDir: string, bundle: unknown): Promise<ProofTrustResult>;
|
|
9
|
+
}
|
|
10
|
+
export interface ProofTrustResult {
|
|
11
|
+
readonly trustScore: number;
|
|
12
|
+
readonly missingFields: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function createProofTrustMvpEngine(schemas?: Readonly<Record<string, unknown>>): ProofTrustMvpEngine;
|