openmerit 0.1.5 → 0.1.6-preview.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 +14 -0
- package/README.md +33 -9
- package/dist/core/src/index.d.ts +12 -1
- package/dist/core/src/index.js +552 -40
- package/dist/pi/src/index.d.ts +17 -0
- package/dist/pi/src/index.js +448 -77
- package/dist/pi/src/scheduler.d.ts +11 -0
- package/dist/pi/src/scheduler.js +137 -0
- package/dist/pi/src/wakeup.d.ts +2 -0
- package/dist/pi/src/wakeup.js +108 -0
- package/dist/protocol/src/index.d.ts +86 -4
- package/dist/protocol/src/index.js +1 -1
- package/dist/protocol/src/schemas.d.ts +128 -2
- package/dist/protocol/src/schemas.js +57 -1
- package/dist/terminal/public/app.js +297 -0
- package/dist/terminal/public/brands/anthropic.png +0 -0
- package/dist/terminal/public/brands/baai.png +0 -0
- package/dist/terminal/public/brands/baseten.png +0 -0
- package/dist/terminal/public/brands/cerebras.png +0 -0
- package/dist/terminal/public/brands/cohere.png +0 -0
- package/dist/terminal/public/brands/deepseek.ico +0 -0
- package/dist/terminal/public/brands/google.png +0 -0
- package/dist/terminal/public/brands/groq.ico +0 -0
- package/dist/terminal/public/brands/lm-studio.png +0 -0
- package/dist/terminal/public/brands/meta.ico +0 -0
- package/dist/terminal/public/brands/mistral.png +0 -0
- package/dist/terminal/public/brands/nomic.png +0 -0
- package/dist/terminal/public/brands/ollama.png +0 -0
- package/dist/terminal/public/brands/openai.png +0 -0
- package/dist/terminal/public/brands/openrouter.png +0 -0
- package/dist/terminal/public/brands/qwen.png +0 -0
- package/dist/terminal/public/brands/vllm.ico +0 -0
- package/dist/terminal/public/brands/vllm.png +0 -0
- package/dist/terminal/public/favicon.svg +1 -0
- package/dist/terminal/public/flow.css +1 -0
- package/dist/terminal/public/flow.js +770 -0
- package/dist/terminal/public/index.html +21 -0
- package/dist/terminal/public/styles.css +779 -0
- package/dist/terminal/src/activity-merge.mjs +64 -0
- package/dist/terminal/src/browser.mjs +29 -0
- package/dist/terminal/src/cli.mjs +60 -0
- package/dist/terminal/src/collect.mjs +311 -0
- package/dist/terminal/src/discovery.mjs +93 -0
- package/dist/terminal/src/hardware.mjs +57 -0
- package/dist/terminal/src/project-activity.mjs +156 -0
- package/dist/terminal/src/sample.mjs +171 -0
- package/dist/terminal/src/server.mjs +56 -0
- package/dist/terminal/src/services.mjs +62 -0
- package/dist/terminal/src/topology.mjs +30 -0
- package/docs/adapter-guide.md +24 -7
- package/docs/architecture.md +8 -4
- package/docs/automation.md +10 -2
- package/docs/budgets.md +37 -0
- package/docs/commands.md +85 -0
- package/docs/demo-backfill.md +29 -0
- package/docs/demo-fieldkit.md +47 -0
- package/docs/demo-placement.md +30 -0
- package/docs/demo-spam.md +15 -0
- package/docs/demo-support.md +42 -0
- package/docs/demo.md +57 -0
- package/docs/first-trial.md +60 -0
- package/docs/getting-started.md +18 -8
- package/docs/index.md +40 -0
- package/docs/inference-terminal.md +439 -0
- package/docs/lifecycle.md +9 -9
- package/docs/memo.md +126 -0
- package/docs/metrics-and-evidence.md +11 -3
- package/docs/operations.md +12 -3
- package/docs/pi-extension.md +17 -7
- package/docs/roadmap.md +4 -2
- package/docs/security.md +15 -1
- package/docs/site-artwork-linocut.md +23 -0
- package/docs/site-artwork-miniature-diverse.md +28 -0
- package/docs/site-artwork-miniature.md +26 -0
- package/docs/site-demo.md +177 -0
- package/docs/site-design.md +94 -0
- package/docs/site-documentation.md +83 -0
- package/docs/site-dynamic-og.md +35 -0
- package/docs/site-faq-maintenance.md +115 -0
- package/docs/site-hero-resolution.md +60 -0
- package/docs/site-illustration-sequences.md +227 -0
- package/docs/site-inference-terminal.md +203 -0
- package/docs/site-memo.md +39 -0
- package/docs/site-og-image.md +38 -0
- package/docs/site-og-workshop.md +21 -0
- package/docs/site-section-artwork.md +56 -0
- package/docs/site-skill-review.md +57 -0
- package/docs/site-terminal-preview.md +85 -0
- package/docs/testing.md +85 -3
- package/docs/troubleshooting.md +55 -0
- package/package.json +48 -7
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PiWakeupOptions {
|
|
2
|
+
readonly projectRoot: string;
|
|
3
|
+
readonly extensionPath: string;
|
|
4
|
+
readonly provider: string;
|
|
5
|
+
readonly modelId: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function piWakeupLabel(projectRoot: string): string;
|
|
8
|
+
export declare function piWakeupPlistPath(projectRoot: string): string;
|
|
9
|
+
export declare function renderPiWakeupPlist(options: PiWakeupOptions, piPath: string, runnerPath: string): string;
|
|
10
|
+
export declare function provisionPiWakeup(options: PiWakeupOptions): Promise<string>;
|
|
11
|
+
export declare function removePiWakeup(projectRoot: string): Promise<boolean>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { access, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
const POLL_SECONDS = 300;
|
|
10
|
+
function projectHash(projectRoot) {
|
|
11
|
+
return createHash("sha256").update(resolve(projectRoot)).digest("hex").slice(0, 16);
|
|
12
|
+
}
|
|
13
|
+
export function piWakeupLabel(projectRoot) {
|
|
14
|
+
return `com.openmerit.pi.${projectHash(projectRoot)}`;
|
|
15
|
+
}
|
|
16
|
+
export function piWakeupPlistPath(projectRoot) {
|
|
17
|
+
return join(homedir(), "Library", "LaunchAgents", `${piWakeupLabel(projectRoot)}.plist`);
|
|
18
|
+
}
|
|
19
|
+
function managedMarker(projectRoot) {
|
|
20
|
+
return `<!-- openmerit-managed:${projectHash(projectRoot)} -->`;
|
|
21
|
+
}
|
|
22
|
+
function xml(value) {
|
|
23
|
+
return value.replaceAll("&", "&").replaceAll("<", "<")
|
|
24
|
+
.replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
25
|
+
}
|
|
26
|
+
async function executable(name) {
|
|
27
|
+
for (const directory of (process.env.PATH ?? "").split(":")) {
|
|
28
|
+
if (!directory)
|
|
29
|
+
continue;
|
|
30
|
+
const path = join(directory, name);
|
|
31
|
+
try {
|
|
32
|
+
await access(path, constants.X_OK);
|
|
33
|
+
return path;
|
|
34
|
+
}
|
|
35
|
+
catch { /* try the next PATH entry */ }
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`${name} is not on PATH`);
|
|
38
|
+
}
|
|
39
|
+
export function renderPiWakeupPlist(options, piPath, runnerPath) {
|
|
40
|
+
const args = [process.execPath, runnerPath, resolve(options.projectRoot), piPath,
|
|
41
|
+
resolve(options.extensionPath), options.provider, options.modelId];
|
|
42
|
+
const argumentsXml = args.map((argument) => ` <string>${xml(argument)}</string>`).join("\n");
|
|
43
|
+
const path = [dirname(process.execPath), dirname(piPath), "/usr/bin", "/bin", "/usr/sbin", "/sbin"].join(":");
|
|
44
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
45
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
46
|
+
${managedMarker(options.projectRoot)}
|
|
47
|
+
<plist version="1.0">
|
|
48
|
+
<dict>
|
|
49
|
+
<key>Label</key><string>${xml(piWakeupLabel(options.projectRoot))}</string>
|
|
50
|
+
<key>ProgramArguments</key><array>
|
|
51
|
+
${argumentsXml}
|
|
52
|
+
</array>
|
|
53
|
+
<key>WorkingDirectory</key><string>${xml(resolve(options.projectRoot))}</string>
|
|
54
|
+
<key>EnvironmentVariables</key><dict>
|
|
55
|
+
<key>PATH</key><string>${xml(path)}</string>
|
|
56
|
+
</dict>
|
|
57
|
+
<key>RunAtLoad</key><true/>
|
|
58
|
+
<key>StartInterval</key><integer>${POLL_SECONDS}</integer>
|
|
59
|
+
</dict>
|
|
60
|
+
</plist>
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
async function loaded(label) {
|
|
64
|
+
try {
|
|
65
|
+
await execFileAsync("launchctl", ["print", `gui/${process.getuid?.()}/${label}`]);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export async function provisionPiWakeup(options) {
|
|
73
|
+
if (process.platform !== "darwin" || process.getuid === undefined) {
|
|
74
|
+
throw new Error("Persistent Pi wakeups require a macOS user LaunchAgent.");
|
|
75
|
+
}
|
|
76
|
+
if (!options.provider || !options.modelId)
|
|
77
|
+
throw new Error("Select an authenticated Pi model before scheduling.");
|
|
78
|
+
const piPath = await executable("pi");
|
|
79
|
+
const auth = await execFileAsync(piPath, ["auth", "check", "--model", `${options.provider}/${options.modelId}`], {
|
|
80
|
+
env: {
|
|
81
|
+
HOME: homedir(),
|
|
82
|
+
PATH: [dirname(process.execPath), dirname(piPath), "/usr/bin", "/bin", "/usr/sbin", "/sbin"].join(":"),
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
if (auth.stdout.trim() !== "ready") {
|
|
86
|
+
throw new Error(`Pi authentication is not ready for ${options.provider}/${options.modelId} in the background environment.`);
|
|
87
|
+
}
|
|
88
|
+
const extensionPath = resolve(options.extensionPath);
|
|
89
|
+
const runnerPath = join(dirname(extensionPath), `wakeup${extname(extensionPath)}`);
|
|
90
|
+
await access(runnerPath, constants.R_OK);
|
|
91
|
+
const path = piWakeupPlistPath(options.projectRoot);
|
|
92
|
+
const content = renderPiWakeupPlist({ ...options, extensionPath }, piPath, runnerPath);
|
|
93
|
+
let prior;
|
|
94
|
+
try {
|
|
95
|
+
prior = await readFile(path, "utf8");
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
if (error.code !== "ENOENT")
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
if (prior && !prior.includes(managedMarker(options.projectRoot))) {
|
|
102
|
+
throw new Error(`Refusing to replace unmanaged LaunchAgent ${basename(path)}.`);
|
|
103
|
+
}
|
|
104
|
+
const label = piWakeupLabel(options.projectRoot);
|
|
105
|
+
if (prior === content && await loaded(label))
|
|
106
|
+
return path;
|
|
107
|
+
if (await loaded(label))
|
|
108
|
+
await execFileAsync("launchctl", ["bootout", `gui/${process.getuid()}/${label}`]);
|
|
109
|
+
await mkdir(dirname(path), { recursive: true });
|
|
110
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
111
|
+
await writeFile(temporary, content, { mode: 0o600 });
|
|
112
|
+
await rename(temporary, path);
|
|
113
|
+
await execFileAsync("launchctl", ["bootstrap", `gui/${process.getuid()}`, path]);
|
|
114
|
+
return path;
|
|
115
|
+
}
|
|
116
|
+
export async function removePiWakeup(projectRoot) {
|
|
117
|
+
if (process.platform !== "darwin" || process.getuid === undefined)
|
|
118
|
+
return false;
|
|
119
|
+
const path = piWakeupPlistPath(projectRoot);
|
|
120
|
+
let content;
|
|
121
|
+
try {
|
|
122
|
+
content = await readFile(path, "utf8");
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (error.code === "ENOENT")
|
|
126
|
+
return false;
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
if (!content.includes(managedMarker(projectRoot))) {
|
|
130
|
+
throw new Error(`Refusing to remove unmanaged LaunchAgent ${basename(path)}.`);
|
|
131
|
+
}
|
|
132
|
+
const label = piWakeupLabel(projectRoot);
|
|
133
|
+
if (await loaded(label))
|
|
134
|
+
await execFileAsync("launchctl", ["bootout", `gui/${process.getuid()}/${label}`]);
|
|
135
|
+
await unlink(path);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { writeFile } from "node:fs/promises";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { buildAutomationPlan, OpenMeritCoordinator, ProjectStore } from "../../core/src/index.js";
|
|
6
|
+
const wakeupDescriptor = {
|
|
7
|
+
id: "pi-launchagent", name: "Pi LaunchAgent", version: "0.87", protocolVersions: ["0.1"],
|
|
8
|
+
capabilities: [], executionModes: ["non_interactive"],
|
|
9
|
+
structuredOutput: { schemaDialect: "https://json-schema.org/draft/2020-12/schema", presentation: "adapter_validation", enforcement: "adapter" },
|
|
10
|
+
automation: {
|
|
11
|
+
supportedSignals: ["product_task_completed", "metric_window_available", "scheduled_tick", "model_catalog_changed", "verification_window_completed"],
|
|
12
|
+
persistentScheduling: true, backgroundExecution: true, wakeupProvisioning: "infrastructure_change",
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
export function isPiWakeupDue(state, now = new Date().toISOString()) {
|
|
16
|
+
const execution = state.cycle.policy?.checkPolicy.execution;
|
|
17
|
+
if (execution?.mode !== "persistent" || !execution.infrastructureChangesAllowed || state.activeIntent || state.automation.paused)
|
|
18
|
+
return false;
|
|
19
|
+
if (state.automation.pendingIntentKind)
|
|
20
|
+
return true;
|
|
21
|
+
const at = buildAutomationPlan(state, wakeupDescriptor).nextWakeupAt;
|
|
22
|
+
return at !== undefined && Date.parse(at) <= Date.parse(now);
|
|
23
|
+
}
|
|
24
|
+
async function run() {
|
|
25
|
+
const [projectRoot, piPath, extensionPath, provider, modelId] = process.argv.slice(2);
|
|
26
|
+
if (!projectRoot || !piPath || !extensionPath || !provider || !modelId)
|
|
27
|
+
process.exitCode = 2;
|
|
28
|
+
if (process.exitCode)
|
|
29
|
+
return;
|
|
30
|
+
const store = new ProjectStore(projectRoot);
|
|
31
|
+
const state = await store.readState();
|
|
32
|
+
if (!state || !isPiWakeupDue(state))
|
|
33
|
+
return;
|
|
34
|
+
const startedAt = new Date().toISOString();
|
|
35
|
+
const coordinator = new OpenMeritCoordinator(store, {
|
|
36
|
+
descriptor: wakeupDescriptor,
|
|
37
|
+
async dispatch() { return { accepted: false, reason: "The wakeup runner does not dispatch harness work directly." }; },
|
|
38
|
+
});
|
|
39
|
+
const check = state.automation.pendingIntentKind === "run_assessment"
|
|
40
|
+
? await coordinator.assessBaseline(startedAt)
|
|
41
|
+
: state.automation.pendingIntentKind
|
|
42
|
+
? undefined
|
|
43
|
+
: await coordinator.recordAutomationSignal({
|
|
44
|
+
protocolVersion: "0.1", id: `wakeup-${crypto.randomUUID()}`,
|
|
45
|
+
type: "scheduled_tick", occurredAt: startedAt, targetId: state.cycle.targetId,
|
|
46
|
+
});
|
|
47
|
+
if (check && check.decision.action !== "issue_intent") {
|
|
48
|
+
await writeFile(join(store.directory, "scheduler-status.json"), JSON.stringify({
|
|
49
|
+
schemaVersion: 1, startedAt, completedAt: new Date().toISOString(), exitCode: 0,
|
|
50
|
+
decision: check.decision.reason,
|
|
51
|
+
}, null, 2) + "\n", { mode: 0o600 });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const configuredTimeout = Number(process.env.OPENMERIT_WAKEUP_TIMEOUT_MS);
|
|
55
|
+
const runLimitMs = Number.isFinite(configuredTimeout) && configuredTimeout >= 5_000
|
|
56
|
+
? Math.min(configuredTimeout, 15 * 60_000)
|
|
57
|
+
: 15 * 60_000;
|
|
58
|
+
const deadline = Date.now() + runLimitMs;
|
|
59
|
+
const invokePi = async (prompt) => {
|
|
60
|
+
const child = spawn(piPath, [
|
|
61
|
+
"--no-extensions", "--extension", extensionPath, "--provider", provider, "--model", modelId,
|
|
62
|
+
...(process.env.OPENMERIT_WAKEUP_DEBUG === "1" ? ["--mode", "json"] : []),
|
|
63
|
+
"--no-session", "--print", prompt,
|
|
64
|
+
], { cwd: projectRoot, stdio: process.env.OPENMERIT_WAKEUP_DEBUG === "1" ? "inherit" : "ignore", env: process.env });
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
let timedOut = false;
|
|
67
|
+
const timeout = setTimeout(() => {
|
|
68
|
+
timedOut = true;
|
|
69
|
+
child.kill("SIGTERM");
|
|
70
|
+
setTimeout(() => child.kill("SIGKILL"), 5_000).unref();
|
|
71
|
+
}, Math.max(1, deadline - Date.now()));
|
|
72
|
+
child.once("error", (error) => { clearTimeout(timeout); reject(error); });
|
|
73
|
+
child.once("exit", (code) => { clearTimeout(timeout); resolve(timedOut ? 124 : code ?? 1); });
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
let exitCode = await invokePi("Run the due OpenMerit scheduled check for this configured project. " +
|
|
77
|
+
"On startup, OpenMerit may create an active intent in .openmerit/state.json. Read that intent and .openmerit/config.json, " +
|
|
78
|
+
"perform only its authorized work, and call openmerit_complete_intent exactly once with verified evidence. " +
|
|
79
|
+
"For baseline assessment, if no application metric windows exist, report insufficiency promptly; do not wait for new data or invent samples. " +
|
|
80
|
+
"If evidence is unavailable, report failure honestly. Never change Pi's model or an unauthorized application route.");
|
|
81
|
+
const issued = await store.readState();
|
|
82
|
+
if (exitCode === 0 && issued?.activeIntent && !state.activeIntent && Date.now() < deadline) {
|
|
83
|
+
const intent = issued.activeIntent;
|
|
84
|
+
exitCode = await invokePi(`Complete the already active OpenMerit ${intent.kind} intent ${intent.id}. ` +
|
|
85
|
+
"Read .openmerit/config.json and the project evidence. Follow the requested outcome and constraints below. " +
|
|
86
|
+
"Use the registered openmerit_complete_intent tool exactly once, with verified evidence; if evidence is unavailable, report failure honestly. " +
|
|
87
|
+
"Never change Pi's model or the application model unless this intent explicitly authorizes that target-bound change.\n\n" +
|
|
88
|
+
JSON.stringify(intent));
|
|
89
|
+
if ((await store.readState())?.activeIntent?.id === intent.id)
|
|
90
|
+
exitCode = 1;
|
|
91
|
+
}
|
|
92
|
+
const finalState = await store.readState();
|
|
93
|
+
if (finalState?.activeIntent && exitCode === 0)
|
|
94
|
+
exitCode = 1;
|
|
95
|
+
if (finalState?.automation.pendingIntentKind && exitCode === 0)
|
|
96
|
+
exitCode = 1;
|
|
97
|
+
await writeFile(join(store.directory, "scheduler-status.json"), JSON.stringify({
|
|
98
|
+
schemaVersion: 1, startedAt, completedAt: new Date().toISOString(), exitCode,
|
|
99
|
+
...(finalState?.activeIntent ? { activeIntentId: finalState.activeIntent.id } : {}),
|
|
100
|
+
}, null, 2) + "\n", { mode: 0o600 });
|
|
101
|
+
process.exitCode = exitCode;
|
|
102
|
+
}
|
|
103
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
|
|
104
|
+
run().catch((error) => {
|
|
105
|
+
process.stderr.write(`OpenMerit Pi wakeup failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
106
|
+
process.exitCode = 1;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const PROTOCOL_VERSION: "0.1";
|
|
2
|
-
export { CandidateAssessmentSchema, CandidateDescriptorSchema, completionToolSchemaFor, EvidenceReferenceSchema, FrontierRecommendationSchema, FrontierSnapshotSchema, INTENT_OUTPUT_SCHEMAS, intentOutputSchemaFor, MetricObjectiveSchema, MetricRecordSchema, ObservabilityCoverageSchema, OPENMERIT_RESULT_SCHEMA_VERSION, OPENMERIT_SCHEMA_DIALECT, SupervisedGraduationPolicySchema, TaskProfileSchema, validateIntentOutputSchema, } from "./schemas.ts";
|
|
2
|
+
export { ApplicationLlmTargetSchema, CandidateAssessmentSchema, CandidateDescriptorSchema, completionToolSchemaFor, EvidenceReferenceSchema, FrontierRecommendationSchema, FrontierSnapshotSchema, INTENT_OUTPUT_SCHEMAS, intentOutputSchemaFor, MetricObjectiveSchema, MetricRecordSchema, ObservabilityCoverageSchema, OPENMERIT_RESULT_SCHEMA_VERSION, OPENMERIT_SCHEMA_DIALECT, SupervisedGraduationPolicySchema, TaskProfileSchema, validateIntentOutputSchema, } from "./schemas.ts";
|
|
3
3
|
export type JsonPrimitive = string | number | boolean | null;
|
|
4
4
|
export type JsonValue = JsonPrimitive | {
|
|
5
5
|
readonly [key: string]: JsonValue;
|
|
@@ -88,6 +88,7 @@ export interface OpenMeritIntent {
|
|
|
88
88
|
readonly protocolVersion: typeof PROTOCOL_VERSION;
|
|
89
89
|
readonly id: string;
|
|
90
90
|
readonly kind: IntentKind;
|
|
91
|
+
readonly targetId?: string;
|
|
91
92
|
readonly taskProfileId: string;
|
|
92
93
|
readonly authorizationPolicyId: string;
|
|
93
94
|
readonly requestedOutcome: string;
|
|
@@ -161,11 +162,13 @@ export interface MetricDefinition {
|
|
|
161
162
|
}
|
|
162
163
|
export declare const METRIC_CATALOG: readonly MetricDefinition[];
|
|
163
164
|
export interface MetricRecord {
|
|
165
|
+
readonly targetId: string;
|
|
164
166
|
readonly metricId: MetricId;
|
|
165
167
|
readonly state: MetricState;
|
|
166
168
|
readonly scope: MetricScope;
|
|
167
169
|
readonly direction: MetricDirection;
|
|
168
170
|
readonly method: MeasurementMethod;
|
|
171
|
+
readonly aggregation: "single_value" | "sum" | "mean" | "rate" | "distribution" | "percentile";
|
|
169
172
|
readonly value?: number;
|
|
170
173
|
readonly unit: string;
|
|
171
174
|
readonly sampleCount: number;
|
|
@@ -186,22 +189,41 @@ export interface MetricObjective {
|
|
|
186
189
|
readonly required: boolean;
|
|
187
190
|
readonly minimumSamples: number;
|
|
188
191
|
readonly tolerance: number;
|
|
192
|
+
readonly samplingPlan: {
|
|
193
|
+
readonly strategy: "single_run" | "repeated_same_input" | "representative_task_set" | "repeated_representative_task_set" | "load_test";
|
|
194
|
+
readonly representativeCaseCount: number;
|
|
195
|
+
readonly repetitionsPerCase: number;
|
|
196
|
+
readonly aggregation: "single_value" | "mean" | "rate" | "distribution" | "percentile";
|
|
197
|
+
readonly rationale: string;
|
|
198
|
+
};
|
|
189
199
|
readonly constraint?: {
|
|
190
200
|
readonly operator: "at_least" | "at_most";
|
|
191
201
|
readonly value: number;
|
|
192
202
|
};
|
|
193
203
|
}
|
|
204
|
+
/** A user-confirmed application LLM route. The coding harness itself is never an evaluation target. */
|
|
205
|
+
export interface ApplicationLlmTarget {
|
|
206
|
+
readonly id: string;
|
|
207
|
+
readonly kind: "application_llm_call";
|
|
208
|
+
readonly name: string;
|
|
209
|
+
readonly applicationId: string;
|
|
210
|
+
readonly callSites: readonly string[];
|
|
211
|
+
readonly routeKey: string;
|
|
212
|
+
readonly confirmedAt: string;
|
|
213
|
+
}
|
|
194
214
|
export interface TaskProfile {
|
|
195
215
|
readonly id: string;
|
|
196
216
|
readonly revision: number;
|
|
197
217
|
readonly name: string;
|
|
198
218
|
readonly goal: string;
|
|
219
|
+
readonly applicationTarget: ApplicationLlmTarget;
|
|
199
220
|
readonly objectives: readonly MetricObjective[];
|
|
200
221
|
readonly createdAt: string;
|
|
201
222
|
readonly confirmedAt?: string;
|
|
202
223
|
}
|
|
203
224
|
export type ObservabilityReadinessStatus = "ready" | "incomplete";
|
|
204
225
|
export interface ObservabilityCoverage {
|
|
226
|
+
readonly targetId: string;
|
|
205
227
|
readonly status: ObservabilityReadinessStatus;
|
|
206
228
|
readonly requiredMetricIds: readonly MetricId[];
|
|
207
229
|
readonly coveredMetricIds: readonly MetricId[];
|
|
@@ -210,6 +232,7 @@ export interface ObservabilityCoverage {
|
|
|
210
232
|
}
|
|
211
233
|
export interface CandidateAssessment {
|
|
212
234
|
readonly id: string;
|
|
235
|
+
readonly targetId: string;
|
|
213
236
|
readonly taskProfileId: string;
|
|
214
237
|
readonly taskProfileRevision: number;
|
|
215
238
|
readonly candidateId: string;
|
|
@@ -230,6 +253,7 @@ export interface DominanceComparison {
|
|
|
230
253
|
}
|
|
231
254
|
export interface FrontierSnapshot {
|
|
232
255
|
readonly id: string;
|
|
256
|
+
readonly targetId: string;
|
|
233
257
|
readonly taskProfileId: string;
|
|
234
258
|
readonly taskProfileRevision: number;
|
|
235
259
|
readonly productRevision: string;
|
|
@@ -243,6 +267,7 @@ export interface FrontierSnapshot {
|
|
|
243
267
|
readonly calculationEvidence: readonly EvidenceReference[];
|
|
244
268
|
}
|
|
245
269
|
export interface FrontierRecommendation {
|
|
270
|
+
readonly targetId: string;
|
|
246
271
|
readonly frontierSnapshotId: string;
|
|
247
272
|
readonly selectedCandidateId: string;
|
|
248
273
|
readonly currentCandidateId: string;
|
|
@@ -250,50 +275,82 @@ export interface FrontierRecommendation {
|
|
|
250
275
|
readonly preferenceEvidence: readonly EvidenceReference[];
|
|
251
276
|
}
|
|
252
277
|
export interface CandidateDescriptor {
|
|
278
|
+
readonly targetId: string;
|
|
253
279
|
readonly candidateId: string;
|
|
254
280
|
readonly modelId: string;
|
|
255
281
|
readonly modelVersion?: string;
|
|
256
282
|
readonly reasons: readonly string[];
|
|
257
283
|
}
|
|
284
|
+
/** Research priors only. These are never MetricRecords or frontier evidence. */
|
|
285
|
+
export interface PreliminaryModelLead {
|
|
286
|
+
readonly targetId: string;
|
|
287
|
+
readonly modelId: string;
|
|
288
|
+
readonly modelVersion?: string;
|
|
289
|
+
readonly estimatedPrice: {
|
|
290
|
+
readonly currency: string;
|
|
291
|
+
readonly inputPerMillionTokens: number;
|
|
292
|
+
readonly outputPerMillionTokens: number;
|
|
293
|
+
readonly sourceUri: string;
|
|
294
|
+
readonly checkedAt: string;
|
|
295
|
+
};
|
|
296
|
+
readonly reputation: {
|
|
297
|
+
readonly summary: string;
|
|
298
|
+
readonly sourceUri: string;
|
|
299
|
+
readonly checkedAt: string;
|
|
300
|
+
};
|
|
301
|
+
}
|
|
258
302
|
export interface IntentOutputMap {
|
|
259
303
|
readonly establish_evals: {
|
|
260
304
|
readonly taskProfile: TaskProfile;
|
|
305
|
+
/** The application model configured before any challenger trial. */
|
|
306
|
+
readonly incumbent: CandidateDescriptor;
|
|
261
307
|
readonly policy: SupervisedGraduationPolicy;
|
|
262
308
|
readonly observability: ObservabilityCoverage;
|
|
309
|
+
readonly preliminaryModelLeads?: readonly PreliminaryModelLead[];
|
|
263
310
|
};
|
|
264
311
|
readonly instrument_observability: {
|
|
312
|
+
readonly targetId: string;
|
|
265
313
|
readonly coveredMetricIds: readonly MetricId[];
|
|
266
314
|
readonly missingMetricIds: readonly MetricId[];
|
|
267
315
|
};
|
|
268
316
|
readonly run_assessment: {
|
|
317
|
+
readonly targetId: string;
|
|
269
318
|
readonly baselineEvidenceSufficient: boolean;
|
|
270
|
-
readonly metrics
|
|
319
|
+
readonly metrics: readonly MetricRecord[];
|
|
271
320
|
};
|
|
272
321
|
readonly discover_candidates: {
|
|
322
|
+
readonly targetId: string;
|
|
273
323
|
readonly candidates: readonly CandidateDescriptor[];
|
|
274
324
|
};
|
|
275
325
|
readonly run_challenger_trials: {
|
|
326
|
+
readonly targetId: string;
|
|
276
327
|
readonly assessments: readonly CandidateAssessment[];
|
|
328
|
+
readonly experimentManifest: EvidenceReference;
|
|
277
329
|
};
|
|
278
330
|
readonly calculate_frontier: {
|
|
331
|
+
readonly targetId: string;
|
|
279
332
|
readonly assessments: readonly CandidateAssessment[];
|
|
280
333
|
readonly frontierSnapshot: FrontierSnapshot;
|
|
281
334
|
readonly recommendation?: FrontierRecommendation;
|
|
282
335
|
};
|
|
283
336
|
readonly investigate_regression: {
|
|
337
|
+
readonly targetId: string;
|
|
284
338
|
readonly regressionDetected: boolean;
|
|
285
339
|
readonly affectedMetricIds: readonly MetricId[];
|
|
286
340
|
readonly likelyCause?: string;
|
|
287
341
|
};
|
|
288
342
|
readonly apply_model_swap: {
|
|
343
|
+
readonly targetId: string;
|
|
289
344
|
readonly appliedCandidateId: string;
|
|
290
345
|
readonly previousCandidateId?: string;
|
|
291
346
|
};
|
|
292
347
|
readonly verify_model_swap: {
|
|
348
|
+
readonly targetId: string;
|
|
293
349
|
readonly verified: boolean;
|
|
294
350
|
readonly regressionDetected: boolean;
|
|
295
351
|
};
|
|
296
352
|
readonly rollback_model_swap: {
|
|
353
|
+
readonly targetId: string;
|
|
297
354
|
readonly restoredCandidateId: string;
|
|
298
355
|
};
|
|
299
356
|
}
|
|
@@ -304,6 +361,7 @@ export declare const REQUIRED_CAPABILITIES: Readonly<Record<IntentKind, readonly
|
|
|
304
361
|
export type ImprovementStage = "unconfigured" | "establishing_evidence" | "collecting_baseline" | "baseline_ready" | "discovering_candidates" | "candidates_ready" | "running_challenger_trials" | "challengers_ready" | "calculating_frontier" | "frontier_ready" | "awaiting_swap_approval" | "swap_approved" | "applying_swap" | "swap_applied" | "verifying_swap" | "swap_verified" | "verification_failed" | "rolling_back" | "monitoring";
|
|
305
362
|
export interface ImprovementCycleState {
|
|
306
363
|
readonly id: string;
|
|
364
|
+
readonly targetId?: string;
|
|
307
365
|
readonly taskProfileId?: string;
|
|
308
366
|
readonly stage: ImprovementStage;
|
|
309
367
|
readonly activeCandidateId?: string;
|
|
@@ -319,14 +377,20 @@ export interface OpenMeritProjectConfig {
|
|
|
319
377
|
readonly activeTaskProfileId?: string;
|
|
320
378
|
readonly taskProfiles: readonly TaskProfile[];
|
|
321
379
|
readonly policy?: SupervisedGraduationPolicy;
|
|
380
|
+
readonly preliminaryModelLeads?: readonly PreliminaryModelLead[];
|
|
322
381
|
}
|
|
323
382
|
export interface OpenMeritProjectState {
|
|
324
383
|
readonly schemaVersion: 1;
|
|
325
384
|
readonly cycle: ImprovementCycleState;
|
|
326
385
|
readonly activeIntent?: OpenMeritIntent;
|
|
327
386
|
readonly lastResult?: IntentResult;
|
|
387
|
+
/** Durable handoffs between discovery, trials, and frontier calculation. */
|
|
388
|
+
readonly candidates?: readonly CandidateDescriptor[];
|
|
389
|
+
readonly assessments?: readonly CandidateAssessment[];
|
|
390
|
+
readonly experimentManifest?: EvidenceReference;
|
|
328
391
|
readonly observability?: ObservabilityCoverage;
|
|
329
392
|
readonly automation: {
|
|
393
|
+
readonly paused?: boolean;
|
|
330
394
|
readonly setupNudgeShown: boolean;
|
|
331
395
|
readonly observedCompletedTasks: number;
|
|
332
396
|
readonly lastAssessmentTaskCount: number;
|
|
@@ -336,6 +400,7 @@ export interface OpenMeritProjectState {
|
|
|
336
400
|
readonly pendingIntentKind?: IntentKind;
|
|
337
401
|
readonly pendingIntentReason?: string;
|
|
338
402
|
readonly lastAssessmentAt?: string;
|
|
403
|
+
readonly baselineStartedAt?: string;
|
|
339
404
|
readonly lastReassessmentTaskCount?: number;
|
|
340
405
|
readonly lastReassessmentAt?: string;
|
|
341
406
|
readonly lastRegressionCheckTaskCount?: number;
|
|
@@ -344,20 +409,37 @@ export interface OpenMeritProjectState {
|
|
|
344
409
|
readonly swapAppliedAt?: string;
|
|
345
410
|
readonly lastVerificationAt?: string;
|
|
346
411
|
readonly latestMetricValues?: Readonly<Partial<Record<MetricId, number>>>;
|
|
412
|
+
/** Latest reported aggregate application-run window per metric; overlapping windows are never summed. */
|
|
413
|
+
readonly baselineMetricWindows?: readonly MetricRecord[];
|
|
414
|
+
/** Spend from controlled challenger trials; ordinary product work is excluded. */
|
|
415
|
+
readonly evaluationSpend?: number;
|
|
347
416
|
};
|
|
348
417
|
readonly updatedAt: string;
|
|
349
418
|
}
|
|
350
|
-
export type AuditEventType = "project_initialized" | "intent_requested" | "intent_progressed" | "intent_completed" | "requirements_confirmation_required" | "swap_confirmation_required" | "frontier_verified" | "frontier_rejected" | "cycle_advanced" | "setup_nudged" | "task_observed" | "model_catalog_changed" | "automation_signal_recorded" | "automation_signal_duplicate" | "automation_check_due" | "observability_readiness_checked";
|
|
419
|
+
export type AuditEventType = "project_initialized" | "intent_requested" | "intent_progressed" | "intent_completed" | "requirements_confirmation_required" | "swap_confirmation_required" | "frontier_verified" | "frontier_rejected" | "cycle_advanced" | "setup_nudged" | "task_observed" | "model_catalog_changed" | "automation_signal_recorded" | "automation_signal_duplicate" | "automation_check_due" | "baseline_sufficiency_checked" | "observability_readiness_checked";
|
|
351
420
|
interface AutomationSignalBase {
|
|
352
421
|
readonly protocolVersion: typeof PROTOCOL_VERSION;
|
|
353
422
|
readonly id: string;
|
|
354
423
|
readonly occurredAt: string;
|
|
424
|
+
readonly targetId: string;
|
|
355
425
|
readonly evidence?: readonly EvidenceReference[];
|
|
356
426
|
}
|
|
357
427
|
export type AutomationSignal = (AutomationSignalBase & {
|
|
358
428
|
readonly type: "product_task_completed";
|
|
429
|
+
/** The model used by the application target, never the coding harness model. */
|
|
359
430
|
readonly modelId: string;
|
|
360
|
-
|
|
431
|
+
/** Provider telemetry captured from the application LLM call. */
|
|
432
|
+
readonly telemetry?: {
|
|
433
|
+
readonly startedAt: string;
|
|
434
|
+
readonly completedAt: string;
|
|
435
|
+
readonly durationMs: number;
|
|
436
|
+
readonly inputTokens: number;
|
|
437
|
+
readonly outputTokens: number;
|
|
438
|
+
readonly cacheReadTokens: number;
|
|
439
|
+
readonly cacheWriteTokens: number;
|
|
440
|
+
readonly cost: number;
|
|
441
|
+
readonly currency: "USD";
|
|
442
|
+
};
|
|
361
443
|
}) | (AutomationSignalBase & {
|
|
362
444
|
readonly type: "metric_window_available";
|
|
363
445
|
readonly metrics: readonly MetricRecord[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const PROTOCOL_VERSION = "0.1";
|
|
2
|
-
export { CandidateAssessmentSchema, CandidateDescriptorSchema, completionToolSchemaFor, EvidenceReferenceSchema, FrontierRecommendationSchema, FrontierSnapshotSchema, INTENT_OUTPUT_SCHEMAS, intentOutputSchemaFor, MetricObjectiveSchema, MetricRecordSchema, ObservabilityCoverageSchema, OPENMERIT_RESULT_SCHEMA_VERSION, OPENMERIT_SCHEMA_DIALECT, SupervisedGraduationPolicySchema, TaskProfileSchema, validateIntentOutputSchema, } from "./schemas.js";
|
|
2
|
+
export { ApplicationLlmTargetSchema, CandidateAssessmentSchema, CandidateDescriptorSchema, completionToolSchemaFor, EvidenceReferenceSchema, FrontierRecommendationSchema, FrontierSnapshotSchema, INTENT_OUTPUT_SCHEMAS, intentOutputSchemaFor, MetricObjectiveSchema, MetricRecordSchema, ObservabilityCoverageSchema, OPENMERIT_RESULT_SCHEMA_VERSION, OPENMERIT_SCHEMA_DIALECT, SupervisedGraduationPolicySchema, TaskProfileSchema, validateIntentOutputSchema, } from "./schemas.js";
|
|
3
3
|
export const METRIC_CATALOG = [
|
|
4
4
|
{ id: "task_quality", label: "Task quality", direction: "maximize", defaultUnit: "score", requiresRepeatedRuns: false },
|
|
5
5
|
{ id: "task_success", label: "Task success rate", direction: "maximize", defaultUnit: "ratio", requiresRepeatedRuns: true },
|