@skill-harness/core 0.11.0 → 0.13.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/README.md +2 -1
- package/dist/adapters/types.d.ts +19 -0
- package/dist/adjudication.d.ts +9 -1
- package/dist/adjudication.js +41 -33
- package/dist/adoption.d.ts +128 -0
- package/dist/adoption.js +102 -0
- package/dist/arms.d.ts +1 -1
- package/dist/capture-trace-types.d.ts +2 -0
- package/dist/command-cost.d.ts +9 -0
- package/dist/command-cost.js +23 -0
- package/dist/comparison.d.ts +1 -0
- package/dist/comparison.js +9 -3
- package/dist/execution-trace.js +9 -1
- package/dist/factory-calibration.d.ts +63 -0
- package/dist/factory-calibration.js +115 -0
- package/dist/grade.d.ts +2 -0
- package/dist/grade.js +2 -1
- package/dist/index.d.ts +21 -0
- package/dist/index.js +21 -0
- package/dist/intervention-results.d.ts +6 -0
- package/dist/intervention-results.js +52 -0
- package/dist/intervention.d.ts +123 -0
- package/dist/intervention.js +218 -0
- package/dist/investigation.d.ts +94 -0
- package/dist/investigation.js +148 -0
- package/dist/journal.d.ts +1 -1
- package/dist/judge-agreement.d.ts +19 -0
- package/dist/judge-agreement.js +31 -0
- package/dist/judge-policy.js +5 -3
- package/dist/lift.js +1 -1
- package/dist/lint.js +1 -1
- package/dist/prompt-normalization.d.ts +6 -0
- package/dist/prompt-normalization.js +14 -0
- package/dist/qualification-capture.d.ts +44 -0
- package/dist/qualification-capture.js +163 -0
- package/dist/qualification-config.d.ts +233 -0
- package/dist/qualification-config.js +694 -0
- package/dist/qualification-lock.d.ts +15 -0
- package/dist/qualification-lock.js +87 -0
- package/dist/qualification-oauth-directory.d.ts +79 -0
- package/dist/qualification-oauth-directory.js +444 -0
- package/dist/qualification-panel-store.d.ts +14 -0
- package/dist/qualification-panel-store.js +188 -0
- package/dist/qualification-panels.d.ts +99 -0
- package/dist/qualification-panels.js +91 -0
- package/dist/qualification-process.d.ts +13 -0
- package/dist/qualification-process.js +190 -0
- package/dist/qualification-runner.d.ts +203 -0
- package/dist/qualification-runner.js +2037 -0
- package/dist/qualification-store.d.ts +187 -0
- package/dist/qualification-store.js +833 -0
- package/dist/qualification-validation.d.ts +12 -0
- package/dist/qualification-validation.js +8 -0
- package/dist/regate.js +42 -10
- package/dist/regrade.d.ts +3 -1
- package/dist/regrade.js +37 -5
- package/dist/reps.d.ts +4 -2
- package/dist/reps.js +13 -4
- package/dist/rescore.js +2 -1
- package/dist/results.d.ts +53 -7
- package/dist/results.js +210 -7
- package/dist/run.js +66 -17
- package/dist/score.d.ts +4 -3
- package/dist/score.js +13 -4
- package/dist/screen.d.ts +31 -0
- package/dist/screen.js +105 -0
- package/dist/seeded.d.ts +2 -1
- package/dist/seeded.js +1 -0
- package/dist/sources.d.ts +7 -1
- package/dist/sources.js +13 -5
- package/dist/spec.d.ts +1 -1
- package/dist/spec.js +1 -1
- package/dist/stability.js +1 -1
- package/dist/trajectory-gates.d.ts +14 -14
- package/dist/trajectory-gates.js +18 -34
- package/dist/trusted-host-supervision.d.ts +25 -0
- package/dist/trusted-host-supervision.js +94 -0
- package/dist/vote-panel.d.ts +33 -0
- package/dist/vote-panel.js +41 -0
- package/dist/work-capture-schema.d.ts +38 -0
- package/dist/work-capture-schema.js +33 -0
- package/dist/work-capture.d.ts +43 -0
- package/dist/work-capture.js +81 -0
- package/dist/work-signals.d.ts +55 -0
- package/dist/work-signals.js +71 -0
- package/dist/workspace.js +4 -1
- package/package.json +3 -3
- package/schemas/qualification-cell-result-v1.schema.json +32 -0
- package/schemas/qualification-config-v1.schema.json +244 -0
- package/schemas/qualification-invocation-request-v1.schema.json +59 -0
- package/schemas/qualification-judge-panel-result-v1.schema.json +42 -0
- package/schemas/results-v2.schema.json +19 -21
- package/schemas/results-v3.schema.json +654 -0
- package/schemas/specification-v1.schema.json +1 -1
- package/schemas/trajectory-event-v1.schema.json +20 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { closeSync, constants, fstatSync, fsyncSync, openSync, readFileSync, writeSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { StringDecoder } from "node:string_decoder";
|
|
5
|
+
import { redactText } from "./capture.js";
|
|
6
|
+
import { qualificationSha256 } from "./qualification-config.js";
|
|
7
|
+
export function redactQualificationOutput(text, secretValues = []) {
|
|
8
|
+
let output = text;
|
|
9
|
+
for (const secret of [...new Set(secretValues)].sort((left, right) => right.length - left.length)) {
|
|
10
|
+
if (secret.length >= 8)
|
|
11
|
+
output = output.split(secret).join("[REDACTED credential]");
|
|
12
|
+
}
|
|
13
|
+
output = output
|
|
14
|
+
.replace(/\b([A-Z][A-Z0-9_]*(?:API_KEY|ACCESS_KEY|SECRET_KEY|AUTH_TOKEN|BEARER_TOKEN|SESSION_TOKEN))\s*[:=]\s*[^\s,;"']+/gi, "$1=[REDACTED credential]")
|
|
15
|
+
.replace(/\bBearer\s+[A-Za-z0-9._~+\/-]{8,}/gi, "Bearer [REDACTED credential]")
|
|
16
|
+
.replace(/\b(?:sk|sess|key|token)-[A-Za-z0-9._-]{8,}/gi, "[REDACTED credential]")
|
|
17
|
+
.replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, "[REDACTED credential]");
|
|
18
|
+
return redactText(output);
|
|
19
|
+
}
|
|
20
|
+
export function openQualificationBoundedCapture(path, limit, redact) {
|
|
21
|
+
const fd = openSync(path, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY, 0o600);
|
|
22
|
+
const decoder = new StringDecoder("utf8");
|
|
23
|
+
let pending = "";
|
|
24
|
+
let acceptedRawBytes = 0;
|
|
25
|
+
let closed = false;
|
|
26
|
+
const persist = (text) => {
|
|
27
|
+
if (!text)
|
|
28
|
+
return;
|
|
29
|
+
const sanitized = Buffer.from(redact(text), "utf8");
|
|
30
|
+
const remaining = Math.max(0, limit - state.captured_bytes);
|
|
31
|
+
const part = sanitized.subarray(0, remaining);
|
|
32
|
+
if (part.length > 0) {
|
|
33
|
+
writeSync(fd, part);
|
|
34
|
+
state.captured_bytes += part.length;
|
|
35
|
+
fsyncSync(fd);
|
|
36
|
+
}
|
|
37
|
+
if (sanitized.length > remaining)
|
|
38
|
+
state.truncated = true;
|
|
39
|
+
};
|
|
40
|
+
const flushLines = () => {
|
|
41
|
+
let newline = pending.indexOf("\n");
|
|
42
|
+
while (newline >= 0) {
|
|
43
|
+
persist(pending.slice(0, newline + 1));
|
|
44
|
+
pending = pending.slice(newline + 1);
|
|
45
|
+
newline = pending.indexOf("\n");
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const state = {
|
|
49
|
+
path, total_bytes: 0, captured_bytes: 0, truncated: false,
|
|
50
|
+
write(chunk) {
|
|
51
|
+
state.total_bytes += chunk.length;
|
|
52
|
+
const remainingRaw = Math.max(0, limit - acceptedRawBytes);
|
|
53
|
+
const accepted = chunk.subarray(0, remainingRaw);
|
|
54
|
+
acceptedRawBytes += accepted.length;
|
|
55
|
+
if (accepted.length > 0) {
|
|
56
|
+
pending += decoder.write(accepted);
|
|
57
|
+
flushLines();
|
|
58
|
+
}
|
|
59
|
+
if (chunk.length > remainingRaw)
|
|
60
|
+
state.truncated = true;
|
|
61
|
+
},
|
|
62
|
+
close() {
|
|
63
|
+
if (closed)
|
|
64
|
+
return;
|
|
65
|
+
pending += decoder.end();
|
|
66
|
+
// If the raw limit split a line, discard that incomplete tail rather than
|
|
67
|
+
// persisting a credential prefix that cannot be matched as a whole value.
|
|
68
|
+
if (!state.truncated)
|
|
69
|
+
persist(pending);
|
|
70
|
+
pending = "";
|
|
71
|
+
fsyncSync(fd);
|
|
72
|
+
closeSync(fd);
|
|
73
|
+
closed = true;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
return state;
|
|
77
|
+
}
|
|
78
|
+
export function qualificationOutputReceipt(spoolRoot, path, capture) {
|
|
79
|
+
const bytes = readFileSync(path);
|
|
80
|
+
return {
|
|
81
|
+
path: path.slice(spoolRoot.length + 1),
|
|
82
|
+
total_bytes: capture.total_bytes,
|
|
83
|
+
captured_bytes: bytes.length,
|
|
84
|
+
truncated: capture.truncated,
|
|
85
|
+
sha256: qualificationSha256(bytes),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export function verifyQualificationOutputReceipt(spoolRoot, receipt) {
|
|
89
|
+
const path = join(spoolRoot, receipt.path);
|
|
90
|
+
let fd;
|
|
91
|
+
try {
|
|
92
|
+
fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
93
|
+
const stat = fstatSync(fd);
|
|
94
|
+
if (!stat.isFile())
|
|
95
|
+
throw new Error(`qualification output ${receipt.path} must be a regular non-symlink file`);
|
|
96
|
+
const bytes = readFileSync(fd);
|
|
97
|
+
if (bytes.length !== receipt.captured_bytes || qualificationSha256(bytes) !== receipt.sha256) {
|
|
98
|
+
throw new Error(`qualification output ${receipt.path} digest/size mismatch`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
if (fd !== undefined)
|
|
103
|
+
closeSync(fd);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export function attestQualificationPiJsonl(text, requested) {
|
|
107
|
+
const records = [];
|
|
108
|
+
try {
|
|
109
|
+
for (const line of text.split("\n")) {
|
|
110
|
+
if (!line.trim())
|
|
111
|
+
continue;
|
|
112
|
+
const value = JSON.parse(line);
|
|
113
|
+
if (!plainObject(value))
|
|
114
|
+
throw new Error("event is not an object");
|
|
115
|
+
records.push(value);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return { ok: false, actual: null, fallback: false, refused: false, error: "artifact is not valid JSONL" };
|
|
120
|
+
}
|
|
121
|
+
const fallback = records.some((record) => record.type === "provider_fallback" || record.type === "model_fallback" || Object.hasOwn(record, "fallback_provider") || Object.hasOwn(record, "fallback_model"));
|
|
122
|
+
const messages = records
|
|
123
|
+
.filter((record) => record.type === "message_end" && plainObject(record.message) && record.message.role === "assistant")
|
|
124
|
+
.map((record) => record.message);
|
|
125
|
+
if (messages.length === 0)
|
|
126
|
+
return { ok: false, actual: null, fallback, refused: false, error: "artifact has no authoritative assistant provider/model identity" };
|
|
127
|
+
const identities = messages.map((message) => ({ provider: stringValue(message.provider), model: stringValue(message.model) }));
|
|
128
|
+
if (identities.some((identity) => !identity.provider || !identity.model))
|
|
129
|
+
return { ok: false, actual: null, fallback, refused: false, error: "artifact assistant identity is missing provider or model" };
|
|
130
|
+
const actual = { provider: identities.at(-1).provider, model: identities.at(-1).model };
|
|
131
|
+
if (fallback)
|
|
132
|
+
return { ok: false, actual, fallback: true, refused: false, error: "artifact reports provider/model fallback" };
|
|
133
|
+
if (identities.some((identity) => identity.provider !== requested.provider))
|
|
134
|
+
return { ok: false, actual, fallback: false, refused: false, error: `provider substitution: requested ${requested.provider}, observed ${actual.provider}` };
|
|
135
|
+
if (identities.some((identity) => identity.model !== requested.model))
|
|
136
|
+
return { ok: false, actual, fallback: false, refused: false, error: `model substitution: requested ${requested.model}, observed ${actual.model}` };
|
|
137
|
+
const terminal = messages.at(-1);
|
|
138
|
+
const errorMessage = stringValue(terminal.errorMessage) ?? "";
|
|
139
|
+
const refused = terminal.stopReason === "error" && /(?:refus|not supported|not available|subscription|usage limit|unauthor)/i.test(errorMessage);
|
|
140
|
+
if (terminal.stopReason === "error" && !refused)
|
|
141
|
+
return { ok: false, actual, fallback: false, refused: false, error: errorMessage || "assistant ended with an error" };
|
|
142
|
+
return { ok: true, actual, fallback: false, refused, error: refused ? errorMessage : null };
|
|
143
|
+
}
|
|
144
|
+
export async function spawnQualificationCapture(command, argv, options) {
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
const child = spawn(command, argv, { cwd: options.cwd, env: options.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
147
|
+
let stdout = Buffer.alloc(0), stderr = Buffer.alloc(0), timedOut = false;
|
|
148
|
+
const append = (current, chunk) => Buffer.concat([current, chunk]).subarray(0, options.output_limit_bytes);
|
|
149
|
+
child.stdout.on("data", (chunk) => { stdout = append(stdout, chunk); });
|
|
150
|
+
child.stderr.on("data", (chunk) => { stderr = append(stderr, chunk); });
|
|
151
|
+
const timer = setTimeout(() => { timedOut = true; child.kill("SIGKILL"); }, options.timeout_ms);
|
|
152
|
+
child.once("error", (error) => { clearTimeout(timer); reject(error); });
|
|
153
|
+
child.once("close", (code) => { clearTimeout(timer); resolve({ stdout: stdout.toString("utf8"), stderr: stderr.toString("utf8"), code, timed_out: timedOut }); });
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function plainObject(value) {
|
|
157
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
158
|
+
return false;
|
|
159
|
+
const prototype = Object.getPrototypeOf(value);
|
|
160
|
+
return prototype === Object.prototype || prototype === null;
|
|
161
|
+
}
|
|
162
|
+
function stringValue(value) { return typeof value === "string" ? value : undefined; }
|
|
163
|
+
//# sourceMappingURL=qualification-capture.js.map
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { QUALIFICATION_JUDGE_PANEL_POLICY } from "./qualification-panels.js";
|
|
2
|
+
export declare const QUALIFICATION_CONFIG_VERSION: "qualification-config-v1";
|
|
3
|
+
export declare const QUALIFICATION_RUNNER_VERSION: "qualification-runner-v1";
|
|
4
|
+
export declare const QUALIFICATION_REQUEST_VERSION: "qualification-invocation-request-v1";
|
|
5
|
+
export declare const QUALIFICATION_BOARD_VERSION: "qualification-board-v1";
|
|
6
|
+
export declare const QUALIFICATION_TERMINAL_RECEIPT_VERSION_V3: "qualification-terminal-receipt-v3";
|
|
7
|
+
/** Historical configurations omit this field and retain the original closed policy. */
|
|
8
|
+
export declare const QUALIFICATION_OAUTH_DIRECTORY_POLICY_V1: "qualification-oauth-directory-policy-v1";
|
|
9
|
+
/** New qualification configurations select this policy explicitly. */
|
|
10
|
+
export declare const QUALIFICATION_OAUTH_DIRECTORY_POLICY_V2: "qualification-oauth-directory-policy-v2";
|
|
11
|
+
export type QualificationOAuthDirectoryPolicy = typeof QUALIFICATION_OAUTH_DIRECTORY_POLICY_V1 | typeof QUALIFICATION_OAUTH_DIRECTORY_POLICY_V2;
|
|
12
|
+
export declare const PRINCIPAL_QUALIFICATION_PRODUCT_PIN: {
|
|
13
|
+
readonly repository: "https://github.com/mojomanyana/principal-pi-skills";
|
|
14
|
+
readonly commit: "a6596950d64a3a525f95329d5dbd3e38948be408";
|
|
15
|
+
readonly tree: "960359d69deb6f216724b86e13eef67e2f6a6aa1";
|
|
16
|
+
readonly package_sha256: "3677f76fb31dcaf6a28c9e8b9cf9d6358f998b78bd370f0a0f250d05e136fcc8";
|
|
17
|
+
readonly package_bytes: 110168;
|
|
18
|
+
};
|
|
19
|
+
/** Immutable pi-daddy ledger-v3 producer merge head. */
|
|
20
|
+
export declare const PI_DADDY_QUALIFICATION_PRODUCER_PIN: {
|
|
21
|
+
readonly repository: "https://github.com/mojomanyana/pi-daddy";
|
|
22
|
+
readonly commit: "4a9524394ca995fd74ed9bbb836dc4e73cda3b8c";
|
|
23
|
+
readonly tree: "7c006bff213142634f0f911ba9bd6add363ecaae";
|
|
24
|
+
readonly version: "0.21.1";
|
|
25
|
+
readonly ledger_version: 3;
|
|
26
|
+
readonly ledger_schema_sha256: "64e3d875e74bc32fa43fb96892605548259cd16f6ed6678646d73cc56280c511";
|
|
27
|
+
};
|
|
28
|
+
export declare const QUALIFICATION_ACCOUNTING_POLICY: {
|
|
29
|
+
readonly wave_a: {
|
|
30
|
+
readonly subject: 54;
|
|
31
|
+
readonly judge: 54;
|
|
32
|
+
};
|
|
33
|
+
readonly complete_program: {
|
|
34
|
+
readonly subject: 642;
|
|
35
|
+
readonly judge: 642;
|
|
36
|
+
};
|
|
37
|
+
readonly ceilings: {
|
|
38
|
+
readonly subject: 700;
|
|
39
|
+
readonly judge: 700;
|
|
40
|
+
};
|
|
41
|
+
readonly initial: {
|
|
42
|
+
readonly subject: 0;
|
|
43
|
+
readonly judge: 0;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/** Prospective call ceilings for the universal two-plus-conditional-third panel. */
|
|
47
|
+
export declare const QUALIFICATION_PANEL_ACCOUNTING_POLICY: {
|
|
48
|
+
readonly wave_a: {
|
|
49
|
+
readonly subject: 54;
|
|
50
|
+
readonly judge: 162;
|
|
51
|
+
};
|
|
52
|
+
readonly complete_program: {
|
|
53
|
+
readonly subject: 642;
|
|
54
|
+
readonly judge: 1926;
|
|
55
|
+
};
|
|
56
|
+
readonly ceilings: {
|
|
57
|
+
readonly subject: 700;
|
|
58
|
+
readonly judge: 2100;
|
|
59
|
+
};
|
|
60
|
+
readonly initial: {
|
|
61
|
+
readonly subject: 0;
|
|
62
|
+
readonly judge: 0;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export type QualificationAccountingPolicy = typeof QUALIFICATION_ACCOUNTING_POLICY | typeof QUALIFICATION_PANEL_ACCOUNTING_POLICY;
|
|
66
|
+
export type QualificationRole = "holdout-author" | "holdout-reviewer" | "subject" | "judge" | "calibration" | "canary";
|
|
67
|
+
export type QualificationArmKind = "subject" | "judge";
|
|
68
|
+
export type QualificationConfigMode = "production" | "test";
|
|
69
|
+
export type QualificationConflictPolicy = "refuse" | "remove-and-record";
|
|
70
|
+
export interface QualificationExecutablePin {
|
|
71
|
+
path: string;
|
|
72
|
+
sha256: string;
|
|
73
|
+
}
|
|
74
|
+
export interface QualificationRepositoryPin {
|
|
75
|
+
repository: string;
|
|
76
|
+
commit: string;
|
|
77
|
+
tree: string;
|
|
78
|
+
}
|
|
79
|
+
export interface QualificationProductPin extends QualificationRepositoryPin {
|
|
80
|
+
checkout_path: string;
|
|
81
|
+
package_path: string;
|
|
82
|
+
package_sha256: string;
|
|
83
|
+
package_bytes: number;
|
|
84
|
+
}
|
|
85
|
+
export interface QualificationEnginePin extends QualificationRepositoryPin {
|
|
86
|
+
checkout_path: string;
|
|
87
|
+
package_paths: {
|
|
88
|
+
core: string;
|
|
89
|
+
adapters: string;
|
|
90
|
+
cli: string;
|
|
91
|
+
meta: string;
|
|
92
|
+
};
|
|
93
|
+
package_sha256: {
|
|
94
|
+
core: string;
|
|
95
|
+
adapters: string;
|
|
96
|
+
cli: string;
|
|
97
|
+
meta: string;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export interface QualificationProducerPin extends QualificationRepositoryPin {
|
|
101
|
+
checkout_path: string;
|
|
102
|
+
version: string;
|
|
103
|
+
ledger_version: 3;
|
|
104
|
+
ledger_schema_sha256: string;
|
|
105
|
+
}
|
|
106
|
+
export interface QualificationResourcePin {
|
|
107
|
+
kind: "extension" | "skill" | "system-prompt";
|
|
108
|
+
path: string;
|
|
109
|
+
sha256: string;
|
|
110
|
+
}
|
|
111
|
+
export interface QualificationArmV1 {
|
|
112
|
+
id: string;
|
|
113
|
+
kind: QualificationArmKind;
|
|
114
|
+
provider: string;
|
|
115
|
+
model: string;
|
|
116
|
+
authentication: "chatgpt-oauth" | "test-oauth";
|
|
117
|
+
executable: QualificationExecutablePin;
|
|
118
|
+
resources: QualificationResourcePin[];
|
|
119
|
+
arguments: string[];
|
|
120
|
+
allowed_environment_names: string[];
|
|
121
|
+
timeout_ms: number;
|
|
122
|
+
output_limit_bytes: number;
|
|
123
|
+
artifact: {
|
|
124
|
+
type: "pi-jsonl";
|
|
125
|
+
relative_path_template: "artifacts/{invocation_id}.jsonl";
|
|
126
|
+
};
|
|
127
|
+
fallback: false;
|
|
128
|
+
metered_override: false;
|
|
129
|
+
}
|
|
130
|
+
export interface QualificationBoardV1 {
|
|
131
|
+
schema_version: typeof QUALIFICATION_BOARD_VERSION;
|
|
132
|
+
read_only: true;
|
|
133
|
+
cells: {
|
|
134
|
+
id: string;
|
|
135
|
+
scenario_id: string;
|
|
136
|
+
measurement_identity_sha256: string;
|
|
137
|
+
scenario_version: string;
|
|
138
|
+
stimulus_sha256: string;
|
|
139
|
+
rubric_sha256: string;
|
|
140
|
+
subject_input_sha256: string;
|
|
141
|
+
subject_arm: string;
|
|
142
|
+
judge_arms: [string, string, string];
|
|
143
|
+
panels: {
|
|
144
|
+
id: string;
|
|
145
|
+
repetition: number;
|
|
146
|
+
}[];
|
|
147
|
+
critical: boolean;
|
|
148
|
+
pass_threshold: number;
|
|
149
|
+
}[];
|
|
150
|
+
}
|
|
151
|
+
export interface QualificationConfigV1 {
|
|
152
|
+
schema_version: typeof QUALIFICATION_CONFIG_VERSION;
|
|
153
|
+
/** Omission is the historical v1 policy and is preserved in canonical digests. */
|
|
154
|
+
oauth_directory_policy?: typeof QUALIFICATION_OAUTH_DIRECTORY_POLICY_V2;
|
|
155
|
+
/** Omission preserves historical v1/v2 terminal-receipt selection. */
|
|
156
|
+
terminal_receipt_version?: typeof QUALIFICATION_TERMINAL_RECEIPT_VERSION_V3;
|
|
157
|
+
/** Omission preserves the historical single-draw judge methodology. */
|
|
158
|
+
judge_panel?: typeof QUALIFICATION_JUDGE_PANEL_POLICY;
|
|
159
|
+
/** Externally approved board authority; required with judge_panel. */
|
|
160
|
+
board?: QualificationBoardV1;
|
|
161
|
+
mode: QualificationConfigMode;
|
|
162
|
+
product: QualificationProductPin;
|
|
163
|
+
engine: QualificationEnginePin;
|
|
164
|
+
producer: QualificationProducerPin;
|
|
165
|
+
runner: {
|
|
166
|
+
version: typeof QUALIFICATION_RUNNER_VERSION;
|
|
167
|
+
executable: QualificationExecutablePin;
|
|
168
|
+
conflicting_parent_environment: QualificationConflictPolicy;
|
|
169
|
+
};
|
|
170
|
+
accounting: QualificationAccountingPolicy;
|
|
171
|
+
arms: QualificationArmV1[];
|
|
172
|
+
}
|
|
173
|
+
export interface QualificationInvocationRequestV1 {
|
|
174
|
+
schema_version: typeof QUALIFICATION_REQUEST_VERSION;
|
|
175
|
+
measurement_identity_sha256: string;
|
|
176
|
+
invocation_id: string;
|
|
177
|
+
continuation_authority_sha256: string;
|
|
178
|
+
continuation_authority_expires_at: string;
|
|
179
|
+
scenario: {
|
|
180
|
+
id: string;
|
|
181
|
+
version: string;
|
|
182
|
+
stimulus_sha256: string;
|
|
183
|
+
rubric_sha256: string;
|
|
184
|
+
input_path: string;
|
|
185
|
+
input_sha256: string;
|
|
186
|
+
working_directory: string;
|
|
187
|
+
};
|
|
188
|
+
role: QualificationRole;
|
|
189
|
+
counts_as_measurement: boolean;
|
|
190
|
+
arms: {
|
|
191
|
+
subject: string;
|
|
192
|
+
judge: string;
|
|
193
|
+
};
|
|
194
|
+
selected_arm: string;
|
|
195
|
+
repetition: number;
|
|
196
|
+
/** Present only for judge calls under the prospective panel policy. */
|
|
197
|
+
panel?: {
|
|
198
|
+
id: string;
|
|
199
|
+
member_ordinal: 1 | 2 | 3;
|
|
200
|
+
subject_invocation_id: string;
|
|
201
|
+
subject_artifact_sha256: string;
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Names that can alter provider credentials/routing or inject code into the child.
|
|
206
|
+
* Qualification children start from an allow-list regardless; this predicate also
|
|
207
|
+
* makes a dirty parent shell observable by NAME without ever retaining its value.
|
|
208
|
+
*/
|
|
209
|
+
export declare function isQualificationConflictingEnvironmentName(name: string): boolean;
|
|
210
|
+
export declare function sanitizeQualificationEnvironment(parent: NodeJS.ProcessEnv, allowedNames: readonly string[], conflictPolicy: QualificationConflictPolicy): {
|
|
211
|
+
env: NodeJS.ProcessEnv;
|
|
212
|
+
removed_names: string[];
|
|
213
|
+
};
|
|
214
|
+
export declare function qualificationCanonicalJson(value: unknown): string;
|
|
215
|
+
export declare function qualificationSha256(value: string | Buffer): string;
|
|
216
|
+
export declare function qualificationConfigDigest(config: QualificationConfigV1): string;
|
|
217
|
+
export declare function qualificationOAuthDirectoryPolicy(config: QualificationConfigV1): QualificationOAuthDirectoryPolicy;
|
|
218
|
+
export declare function verifyQualificationPins(config: QualificationConfigV1): void;
|
|
219
|
+
export declare function verifyQualificationResource(pin: QualificationResourcePin): {
|
|
220
|
+
realpath: string;
|
|
221
|
+
bytes: number;
|
|
222
|
+
sha256: string;
|
|
223
|
+
};
|
|
224
|
+
export declare function verifyQualificationExecutable(pin: QualificationExecutablePin): {
|
|
225
|
+
realpath: string;
|
|
226
|
+
bytes: number;
|
|
227
|
+
sha256: string;
|
|
228
|
+
device: number;
|
|
229
|
+
inode: number;
|
|
230
|
+
mtime_ms: number;
|
|
231
|
+
};
|
|
232
|
+
export declare function parseQualificationConfig(value: unknown): QualificationConfigV1;
|
|
233
|
+
export declare function parseQualificationRequest(value: unknown, config: QualificationConfigV1): QualificationInvocationRequestV1;
|