modelrig 0.7.0 → 0.8.1
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 +118 -0
- package/README.md +86 -0
- package/dist/bakeoff/disagreement.d.ts +93 -0
- package/dist/bakeoff/disagreement.d.ts.map +1 -0
- package/dist/bakeoff/disagreement.js +140 -0
- package/dist/bakeoff/engine.d.ts.map +1 -1
- package/dist/bakeoff/engine.js +58 -2
- package/dist/bakeoff/pairwise.d.ts +102 -0
- package/dist/bakeoff/pairwise.d.ts.map +1 -0
- package/dist/bakeoff/pairwise.js +214 -0
- package/dist/bakeoff/replay.d.ts +6 -0
- package/dist/bakeoff/replay.d.ts.map +1 -1
- package/dist/bakeoff/replay.js +6 -2
- package/dist/bakeoff/report.d.ts +7 -0
- package/dist/bakeoff/report.d.ts.map +1 -1
- package/dist/bakeoff/report.js +46 -0
- package/dist/bakeoff/types.d.ts +24 -0
- package/dist/bakeoff/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -9
- package/dist/mask/apply.d.ts +80 -0
- package/dist/mask/apply.d.ts.map +1 -0
- package/dist/mask/apply.js +228 -0
- package/dist/mask/detect.d.ts +38 -0
- package/dist/mask/detect.d.ts.map +1 -0
- package/dist/mask/detect.js +167 -0
- package/dist/mask/index.d.ts +21 -0
- package/dist/mask/index.d.ts.map +1 -0
- package/dist/mask/index.js +54 -0
- package/dist/mask/mask-policy-cli.d.ts +11 -0
- package/dist/mask/mask-policy-cli.d.ts.map +1 -0
- package/dist/mask/mask-policy-cli.js +33 -0
- package/dist/mask/policy.d.ts +38 -0
- package/dist/mask/policy.d.ts.map +1 -0
- package/dist/mask/policy.js +187 -0
- package/dist/mask/proof.d.ts +54 -0
- package/dist/mask/proof.d.ts.map +1 -0
- package/dist/mask/proof.js +120 -0
- package/dist/mask/receipt.d.ts +30 -0
- package/dist/mask/receipt.d.ts.map +1 -0
- package/dist/mask/receipt.js +49 -0
- package/dist/mask/seam.d.ts +53 -0
- package/dist/mask/seam.d.ts.map +1 -0
- package/dist/mask/seam.js +120 -0
- package/dist/mask/types.d.ts +81 -0
- package/dist/mask/types.d.ts.map +1 -0
- package/dist/mask/types.js +10 -0
- package/dist/mask/vault.d.ts +50 -0
- package/dist/mask/vault.d.ts.map +1 -0
- package/dist/mask/vault.js +81 -0
- package/dist/receipts/types.d.ts +65 -0
- package/dist/receipts/types.d.ts.map +1 -0
- package/dist/receipts/types.js +134 -0
- package/dist/routes/loader-warnings.d.ts +8 -0
- package/dist/routes/loader-warnings.d.ts.map +1 -1
- package/dist/routes/loader-warnings.js +23 -0
- package/dist/routes/loader.d.ts +1 -1
- package/dist/routes/loader.d.ts.map +1 -1
- package/dist/routes/loader.js +24 -25
- package/dist/routes/mask-loader.d.ts +18 -0
- package/dist/routes/mask-loader.d.ts.map +1 -0
- package/dist/routes/mask-loader.js +39 -0
- package/dist/routes/objective-loader.d.ts.map +1 -1
- package/dist/routes/objective-loader.js +51 -17
- package/dist/routes/screen-loader.d.ts +23 -0
- package/dist/routes/screen-loader.d.ts.map +1 -0
- package/dist/routes/screen-loader.js +79 -0
- package/dist/routes/template.d.ts +10 -0
- package/dist/routes/template.d.ts.map +1 -1
- package/dist/routes/template.js +10 -3
- package/dist/run/accept.d.ts +4 -0
- package/dist/run/accept.d.ts.map +1 -1
- package/dist/run/accept.js +2 -0
- package/dist/run/dispatch.d.ts +35 -0
- package/dist/run/dispatch.d.ts.map +1 -1
- package/dist/run/dispatch.js +33 -0
- package/dist/run/grounding.d.ts +47 -2
- package/dist/run/grounding.d.ts.map +1 -1
- package/dist/run/grounding.js +113 -6
- package/dist/run/raw.d.ts.map +1 -1
- package/dist/run/raw.js +6 -1
- package/dist/run/record-attempt.d.ts.map +1 -1
- package/dist/run/record-attempt.js +12 -1
- package/dist/run/run.d.ts.map +1 -1
- package/dist/run/run.js +19 -16
- package/dist/screen/provenance.d.ts +59 -0
- package/dist/screen/provenance.d.ts.map +1 -0
- package/dist/screen/provenance.js +104 -0
- package/dist/screen/types.d.ts +71 -0
- package/dist/screen/types.d.ts.map +1 -0
- package/dist/screen/types.js +9 -0
- package/dist/status-cli.d.ts +11 -0
- package/dist/status-cli.d.ts.map +1 -0
- package/dist/status-cli.js +21 -0
- package/dist/status-runs.d.ts +38 -0
- package/dist/status-runs.d.ts.map +1 -0
- package/dist/status-runs.js +80 -0
- package/dist/status.d.ts +7 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +11 -2
- package/dist/telemetry/ingest-protocol.d.ts +8 -0
- package/dist/telemetry/ingest-protocol.d.ts.map +1 -1
- package/dist/telemetry/store-migrations.d.ts.map +1 -1
- package/dist/telemetry/store-migrations.js +11 -0
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/store.js +12 -3
- package/dist/types/provider.d.ts +11 -0
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/provider.js +9 -0
- package/dist/types/route.d.ts +55 -0
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/telemetry.d.ts +7 -0
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/validate-cli.d.ts.map +1 -1
- package/dist/validate-cli.js +13 -0
- package/dist/verify/types.d.ts +6 -0
- package/dist/verify/types.d.ts.map +1 -1
- package/docs/agent-skill/SKILL.md +131 -0
- package/docs/how-it-fits.md +34 -0
- package/docs/instrumentation.md +221 -0
- package/docs/llms.txt +276 -0
- package/docs/migration-playbook.md +512 -0
- package/docs/quickstart.md +339 -0
- package/package.json +18 -2
- package/receipts.d.ts +12 -0
package/dist/routes/loader.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* resolves schema/prompt paths relative to the bundle file, freezes.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.RouteConfigError = exports.unreferencedTrialCandidatesWarning = exports.arrayRootSchemaWarning = void 0;
|
|
8
|
+
exports.RouteConfigError = exports.untrustedShapedVariableWarning = exports.unreferencedTrialCandidatesWarning = exports.arrayRootSchemaWarning = void 0;
|
|
9
9
|
exports.loadRoutesWithExtra = loadRoutesWithExtra;
|
|
10
10
|
exports.mergeLoadedRoutes = mergeLoadedRoutes;
|
|
11
11
|
exports.validateRoutesDir = validateRoutesDir;
|
|
@@ -15,16 +15,18 @@ const node_path_1 = require("node:path");
|
|
|
15
15
|
const yaml_1 = require("yaml");
|
|
16
16
|
const failures_1 = require("../types/failures");
|
|
17
17
|
const fingerprint_1 = require("../registry/fingerprint");
|
|
18
|
-
const template_1 = require("./template");
|
|
19
18
|
const cache_lint_1 = require("./cache-lint");
|
|
20
19
|
const sampling_config_1 = require("./sampling-config");
|
|
21
20
|
const loader_warnings_1 = require("./loader-warnings");
|
|
21
|
+
const screen_loader_1 = require("./screen-loader");
|
|
22
|
+
const mask_loader_1 = require("./mask-loader");
|
|
22
23
|
const objective_loader_1 = require("./objective-loader");
|
|
23
24
|
// Re-exported so existing importers of "./loader" keep resolving these advisories
|
|
24
25
|
// (they live in ./loader-warnings to hold loader.ts under the 700-LOC cap).
|
|
25
26
|
var loader_warnings_2 = require("./loader-warnings");
|
|
26
27
|
Object.defineProperty(exports, "arrayRootSchemaWarning", { enumerable: true, get: function () { return loader_warnings_2.arrayRootSchemaWarning; } });
|
|
27
28
|
Object.defineProperty(exports, "unreferencedTrialCandidatesWarning", { enumerable: true, get: function () { return loader_warnings_2.unreferencedTrialCandidatesWarning; } });
|
|
29
|
+
Object.defineProperty(exports, "untrustedShapedVariableWarning", { enumerable: true, get: function () { return loader_warnings_2.untrustedShapedVariableWarning; } });
|
|
28
30
|
/**
|
|
29
31
|
* Structured config error thrown for any invalid bundle (never a raw Error).
|
|
30
32
|
* Load-time problems are deliberately NOT RigFailures — the failure taxonomy
|
|
@@ -389,19 +391,26 @@ function loadBundleFile(filePath) {
|
|
|
389
391
|
}
|
|
390
392
|
}
|
|
391
393
|
let groundingQuery;
|
|
394
|
+
let groundingAssembly;
|
|
392
395
|
if (doc.grounding !== undefined) {
|
|
393
396
|
if (!isRecord(doc.grounding) || typeof doc.grounding.query !== "string" || doc.grounding.query === "") {
|
|
394
397
|
problems.push("grounding must be an object {query: <template string>}");
|
|
395
398
|
}
|
|
396
399
|
else {
|
|
397
400
|
groundingQuery = doc.grounding.query;
|
|
401
|
+
groundingAssembly = (0, screen_loader_1.parseGroundingAssembly)(doc.grounding, problems); // S1 (SC-0 B3)
|
|
398
402
|
}
|
|
399
403
|
}
|
|
400
404
|
// RB-1 (near-optimal spec §3): objective knob, reference arm + judge, value
|
|
401
405
|
// checks — all additive; candidate-set invariant enforced in parseRb1Fields.
|
|
402
406
|
const rb1 = (0, objective_loader_1.parseRb1Fields)(doc, route, candidates, problems);
|
|
407
|
+
// CS-1 Proven Masking (spec §3): resolve the `mask:` block + its local
|
|
408
|
+
// dictionary here so an unreadable dictionary or unknown type is a LOAD error.
|
|
409
|
+
// Absent / `mode: off` ⇒ undefined ⇒ byte-identical (the golden test).
|
|
410
|
+
const mask = (0, mask_loader_1.parseMaskBlock)(doc.mask, bundleDir, problems);
|
|
403
411
|
let systemTemplate = "";
|
|
404
412
|
let variables = [];
|
|
413
|
+
let variableTrust;
|
|
405
414
|
if (!isRecord(doc.prompt) || typeof doc.prompt.system !== "string") {
|
|
406
415
|
problems.push("prompt.system must be a relative path");
|
|
407
416
|
}
|
|
@@ -413,30 +422,12 @@ function loadBundleFile(filePath) {
|
|
|
413
422
|
else {
|
|
414
423
|
systemTemplate = (0, node_fs_1.readFileSync)(promptPath, "utf8");
|
|
415
424
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
else {
|
|
421
|
-
variables = rawVars;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
if (systemTemplate !== "") {
|
|
425
|
-
const declared = new Set(variables);
|
|
426
|
-
for (const ref of (0, template_1.scanTemplateVariables)(systemTemplate)) {
|
|
427
|
-
if (!declared.has(ref)) {
|
|
428
|
-
problems.push(`template references undeclared variable "${ref}" (declare it in prompt.variables)`);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
if (groundingQuery !== undefined) {
|
|
433
|
-
const declared = new Set(variables);
|
|
434
|
-
for (const ref of (0, template_1.scanTemplateVariables)(groundingQuery)) {
|
|
435
|
-
if (!declared.has(ref)) {
|
|
436
|
-
problems.push(`grounding.query references undeclared variable "${ref}"`);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
425
|
+
// Screening S2 (SC-0 B3): parse names + optional per-variable x-trust.
|
|
426
|
+
const parsed = (0, screen_loader_1.parseVariables)(doc.prompt.variables ?? [], problems);
|
|
427
|
+
variables = parsed.names;
|
|
428
|
+
variableTrust = parsed.trust;
|
|
439
429
|
}
|
|
430
|
+
(0, screen_loader_1.pushUndeclaredVariableProblems)(systemTemplate, groundingQuery, variables, problems);
|
|
440
431
|
if (problems.length > 0) {
|
|
441
432
|
throw new RouteConfigError("invalid route bundle", { file: filePath, problems });
|
|
442
433
|
}
|
|
@@ -466,6 +457,11 @@ function loadBundleFile(filePath) {
|
|
|
466
457
|
const trialWarning = (0, loader_warnings_1.unreferencedTrialCandidatesWarning)(route, candidates, variants);
|
|
467
458
|
if (trialWarning !== null)
|
|
468
459
|
console.warn(`modelrig: ${trialWarning}`);
|
|
460
|
+
// Screening S2 (SC-0 B3, spec §2.4): advisory when an untrusted-shaped variable
|
|
461
|
+
// renders in the system slot without an `x-trust: untrusted` annotation.
|
|
462
|
+
const xTrustWarning = (0, loader_warnings_1.untrustedShapedVariableWarning)(route, variables, variableTrust);
|
|
463
|
+
if (xTrustWarning !== null)
|
|
464
|
+
console.warn(`modelrig: ${xTrustWarning}`);
|
|
469
465
|
return Object.freeze({
|
|
470
466
|
route: route,
|
|
471
467
|
version: version,
|
|
@@ -481,6 +477,9 @@ function loadBundleFile(filePath) {
|
|
|
481
477
|
capture: capture === true,
|
|
482
478
|
cache,
|
|
483
479
|
...(groundingQuery !== undefined ? { groundingQuery } : {}),
|
|
480
|
+
...(groundingAssembly !== undefined ? { groundingAssembly } : {}),
|
|
481
|
+
...(variableTrust !== undefined ? { variableTrust } : {}),
|
|
482
|
+
...(mask !== undefined ? { mask } : {}),
|
|
484
483
|
// Network-effect instrumentation (spec WS6): computed once at load,
|
|
485
484
|
// stamped on every telemetry row for this route.
|
|
486
485
|
fingerprintCell: (0, fingerprint_1.fingerprintSchema)(outputSchema)?.cellKey ?? null,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CS-1 mask-block parsing (Proven Masking, spec §3) — extracted from loader.ts to
|
|
3
|
+
* keep it under the 700-LOC cap (same discipline as screen-loader.ts /
|
|
4
|
+
* objective-loader.ts). Validates the `mask:` block shape, parses it, and
|
|
5
|
+
* resolves its dictionary relative to the bundle dir. An unreadable dictionary or
|
|
6
|
+
* an unknown type is a LOAD problem (pushed into the shared `problems[]`), never a
|
|
7
|
+
* runtime surprise.
|
|
8
|
+
*/
|
|
9
|
+
import type { ResolvedMaskPolicy } from "../mask/types";
|
|
10
|
+
/**
|
|
11
|
+
* Parse + resolve the optional `mask:` block. Returns the resolved policy, or
|
|
12
|
+
* `undefined` when the block is absent OR `mode: off` (both ⇒ byte-identical, no
|
|
13
|
+
* masking). Pushes teaching-style problems for a malformed block or an
|
|
14
|
+
* unreadable/invalid dictionary. `bundleDir` is where a relative dictionary path
|
|
15
|
+
* resolves from (the routes dir, same as schema/prompt paths).
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseMaskBlock(raw: unknown, bundleDir: string, problems: string[]): ResolvedMaskPolicy | undefined;
|
|
18
|
+
//# sourceMappingURL=mask-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask-loader.d.ts","sourceRoot":"","sources":["../../src/routes/mask-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAAE,GACjB,kBAAkB,GAAG,SAAS,CAehC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CS-1 mask-block parsing (Proven Masking, spec §3) — extracted from loader.ts to
|
|
4
|
+
* keep it under the 700-LOC cap (same discipline as screen-loader.ts /
|
|
5
|
+
* objective-loader.ts). Validates the `mask:` block shape, parses it, and
|
|
6
|
+
* resolves its dictionary relative to the bundle dir. An unreadable dictionary or
|
|
7
|
+
* an unknown type is a LOAD problem (pushed into the shared `problems[]`), never a
|
|
8
|
+
* runtime surprise.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.parseMaskBlock = parseMaskBlock;
|
|
12
|
+
const policy_1 = require("../mask/policy");
|
|
13
|
+
/**
|
|
14
|
+
* Parse + resolve the optional `mask:` block. Returns the resolved policy, or
|
|
15
|
+
* `undefined` when the block is absent OR `mode: off` (both ⇒ byte-identical, no
|
|
16
|
+
* masking). Pushes teaching-style problems for a malformed block or an
|
|
17
|
+
* unreadable/invalid dictionary. `bundleDir` is where a relative dictionary path
|
|
18
|
+
* resolves from (the routes dir, same as schema/prompt paths).
|
|
19
|
+
*/
|
|
20
|
+
function parseMaskBlock(raw, bundleDir, problems) {
|
|
21
|
+
if (raw === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
const shapeProblems = (0, policy_1.validateMaskPolicyShape)(raw);
|
|
24
|
+
if (shapeProblems.length > 0) {
|
|
25
|
+
for (const p of shapeProblems)
|
|
26
|
+
problems.push(`mask: ${p}`);
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const policy = (0, policy_1.parseMaskPolicy)(raw);
|
|
30
|
+
if (policy.mode === "off")
|
|
31
|
+
return undefined; // off ⇒ no masking, byte-identical
|
|
32
|
+
try {
|
|
33
|
+
return (0, policy_1.resolveMaskPolicy)(policy, bundleDir);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
problems.push(err instanceof Error ? err.message : String(err));
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"objective-loader.d.ts","sourceRoot":"","sources":["../../src/routes/objective-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EAGb,cAAc,EACd,UAAU,EACX,MAAM,gBAAgB,CAAC;AAExB;;2EAE2E;AAC3E,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,SAAS,CAAC,EAAE,cAAc,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,CAe9F;AAoCD;mEACmE;AACnE,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"objective-loader.d.ts","sourceRoot":"","sources":["../../src/routes/objective-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EAGb,cAAc,EACd,UAAU,EACX,MAAM,gBAAgB,CAAC;AAExB;;2EAE2E;AAC3E,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,SAAS,CAAC,EAAE,cAAc,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,CAe9F;AAoCD;mEACmE;AACnE,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,SAAS,CAqD3F;AAqCD;;2EAE2E;AAC3E,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,QAAQ,EAAE,MAAM,EAAE,GACjB,aAAa,GAAG,SAAS,CAwE3B;AAiCD;uCACuC;AACvC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,UAAU,EAAE,GAAG,SAAS,CAqCpG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAUvG"}
|
|
@@ -103,11 +103,25 @@ function parseObjective(raw, problems) {
|
|
|
103
103
|
if (mode === "balanced" && lambda === undefined) {
|
|
104
104
|
problems.push("objective.mode: balanced requires objective.lambda");
|
|
105
105
|
}
|
|
106
|
+
// N5: the pairwise-aware gate knob — additive & optional, default off.
|
|
107
|
+
let pairwiseAware;
|
|
108
|
+
if (raw.pairwise_aware !== undefined) {
|
|
109
|
+
if (typeof raw.pairwise_aware !== "boolean") {
|
|
110
|
+
problems.push("objective.pairwise_aware must be a boolean");
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
pairwiseAware = raw.pairwise_aware;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (pairwiseAware === true && mode === "cost-first") {
|
|
117
|
+
problems.push("objective.pairwise_aware applies to quality-first (cost-first keeps the legacy gate)");
|
|
118
|
+
}
|
|
106
119
|
return Object.freeze({
|
|
107
120
|
mode: mode,
|
|
108
121
|
...(maxRegret !== undefined ? { maxRegret } : {}),
|
|
109
122
|
...(priceCeiling !== undefined ? { priceCeiling } : {}),
|
|
110
123
|
...(lambda !== undefined ? { lambda } : {}),
|
|
124
|
+
...(pairwiseAware !== undefined ? { pairwiseAware } : {}),
|
|
111
125
|
});
|
|
112
126
|
}
|
|
113
127
|
const PROVIDERS = new Set([
|
|
@@ -194,25 +208,18 @@ function parseBakeoffConfig(raw, candidates, problems) {
|
|
|
194
208
|
referenceEnvelopeUsd = raw.reference_envelope_usd;
|
|
195
209
|
}
|
|
196
210
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
211
|
+
const judge = parseJudgeSpec(raw.judge, "bakeoff.judge", declared, problems);
|
|
212
|
+
// N5: pairwise-vs-reference judge (same #223 F3 candidate-set rule as the
|
|
213
|
+
// value-accuracy judge). `bakeoff.pairwise.judge: { model, max_samples }`.
|
|
214
|
+
let pairwise;
|
|
215
|
+
if (raw.pairwise !== undefined && raw.pairwise !== null) {
|
|
216
|
+
if (!isRecord(raw.pairwise)) {
|
|
217
|
+
problems.push("bakeoff.pairwise must be an object { judge? }");
|
|
201
218
|
}
|
|
202
219
|
else {
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
problems.push("bakeoff.judge.max_samples must be a positive integer");
|
|
207
|
-
}
|
|
208
|
-
if (model !== null && !declared(model)) {
|
|
209
|
-
// #223 F3: the judge model must be a declared candidate.
|
|
210
|
-
problems.push(`bakeoff.judge.model (${model.provider}/${model.model}) is not a declared candidate ` +
|
|
211
|
-
"(a judge model must be one of the route's declared candidates, #223 F3)");
|
|
212
|
-
}
|
|
213
|
-
else if (model !== null && typeof maxSamples === "number" && Number.isInteger(maxSamples) && maxSamples >= 1) {
|
|
214
|
-
judge = { model, maxSamples };
|
|
215
|
-
}
|
|
220
|
+
const pwJudge = parseJudgeSpec(raw.pairwise.judge, "bakeoff.pairwise.judge", declared, problems);
|
|
221
|
+
if (pwJudge !== undefined)
|
|
222
|
+
pairwise = { judge: pwJudge };
|
|
216
223
|
}
|
|
217
224
|
}
|
|
218
225
|
const out = {
|
|
@@ -220,9 +227,36 @@ function parseBakeoffConfig(raw, candidates, problems) {
|
|
|
220
227
|
...(referenceAllowExternal ? { referenceAllowExternal: true } : {}),
|
|
221
228
|
...(referenceEnvelopeUsd !== undefined ? { referenceEnvelopeUsd } : {}),
|
|
222
229
|
...(judge !== undefined ? { judge } : {}),
|
|
230
|
+
...(pairwise !== undefined ? { pairwise } : {}),
|
|
223
231
|
};
|
|
224
232
|
return Object.freeze(out);
|
|
225
233
|
}
|
|
234
|
+
/** Parse a `{ model, max_samples }` judge spec (shared by `bakeoff.judge` and
|
|
235
|
+
* `bakeoff.pairwise.judge`). Enforces #223 F3: the judge model must be a declared
|
|
236
|
+
* candidate. Returns the parsed spec, or undefined when absent/invalid (problems
|
|
237
|
+
* pushed). */
|
|
238
|
+
function parseJudgeSpec(raw, field, declared, problems) {
|
|
239
|
+
if (raw === undefined || raw === null)
|
|
240
|
+
return undefined;
|
|
241
|
+
if (!isRecord(raw)) {
|
|
242
|
+
problems.push(`${field} must be an object { model, max_samples }`);
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
const model = parseModelRef(raw.model, `${field}.model`, problems);
|
|
246
|
+
const maxSamples = raw.max_samples;
|
|
247
|
+
const maxOk = typeof maxSamples === "number" && Number.isInteger(maxSamples) && maxSamples >= 1;
|
|
248
|
+
if (!maxOk)
|
|
249
|
+
problems.push(`${field}.max_samples must be a positive integer`);
|
|
250
|
+
if (model !== null && !declared(model)) {
|
|
251
|
+
// #223 F3: the judge model must be a declared candidate.
|
|
252
|
+
problems.push(`${field}.model (${model.provider}/${model.model}) is not a declared candidate ` +
|
|
253
|
+
"(a judge model must be one of the route's declared candidates, #223 F3)");
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
if (model !== null && maxOk)
|
|
257
|
+
return { model, maxSamples: maxSamples };
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
226
260
|
/** Parse `value_checks:` — a list of {path, expect}. `path` is a JSON pointer;
|
|
227
261
|
* `expect` is a literal or {regex}. */
|
|
228
262
|
function parseValueChecks(raw, problems) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screening route-bundle parsing (SC-0 B3) — extracted from loader.ts to keep it
|
|
3
|
+
* under the 700-LOC cap (same discipline as loader-warnings.ts / objective-loader.ts).
|
|
4
|
+
* Pure functions that push into the shared `problems[]`; unit-tested directly.
|
|
5
|
+
* Spec: docs/ModelRig/screening/spec.md §2.4 (S1 assembly knob, S2 x-trust).
|
|
6
|
+
*/
|
|
7
|
+
/** Push a problem for every `{{var}}` referenced in the system template or the
|
|
8
|
+
* grounding query that was not declared in `prompt.variables`. Colocated with
|
|
9
|
+
* the variable parser it validates. */
|
|
10
|
+
export declare function pushUndeclaredVariableProblems(systemTemplate: string, groundingQuery: string | undefined, variables: readonly string[], problems: string[]): void;
|
|
11
|
+
/** Parse `prompt.variables` — each entry is a bare name (semi, stays in the
|
|
12
|
+
* system slot — the default) or `{name, "x-trust": "untrusted"}` (spotlighted out
|
|
13
|
+
* of the system slot, S2). Returns the declared names and, when any variable is
|
|
14
|
+
* annotated, the trust map. Backward-compatible with a plain list of strings. */
|
|
15
|
+
export declare function parseVariables(rawVars: unknown, problems: string[]): {
|
|
16
|
+
readonly names: string[];
|
|
17
|
+
readonly trust?: Record<string, "untrusted">;
|
|
18
|
+
};
|
|
19
|
+
/** Parse the optional `grounding.assembly` knob (S1). `legacy` (default, absent)
|
|
20
|
+
* = byte-identical system-prompt injection; `spotlight` = untrusted user-slot
|
|
21
|
+
* block via the provenance assembler. The flip is bake-off-gated (spec §2.4). */
|
|
22
|
+
export declare function parseGroundingAssembly(grounding: Record<string, unknown>, problems: string[]): "legacy" | "spotlight" | undefined;
|
|
23
|
+
//# sourceMappingURL=screen-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen-loader.d.ts","sourceRoot":"","sources":["../../src/routes/screen-loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;uCAEuC;AACvC,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,EAAE,MAAM,EAAE,GACjB,IAAI,CAcN;AAED;;;iFAGiF;AACjF,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;CAAE,CAwB5E;AAED;;iFAEiF;AACjF,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,QAAQ,EAAE,MAAM,EAAE,GACjB,QAAQ,GAAG,WAAW,GAAG,SAAS,CAQpC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Screening route-bundle parsing (SC-0 B3) — extracted from loader.ts to keep it
|
|
4
|
+
* under the 700-LOC cap (same discipline as loader-warnings.ts / objective-loader.ts).
|
|
5
|
+
* Pure functions that push into the shared `problems[]`; unit-tested directly.
|
|
6
|
+
* Spec: docs/ModelRig/screening/spec.md §2.4 (S1 assembly knob, S2 x-trust).
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.pushUndeclaredVariableProblems = pushUndeclaredVariableProblems;
|
|
10
|
+
exports.parseVariables = parseVariables;
|
|
11
|
+
exports.parseGroundingAssembly = parseGroundingAssembly;
|
|
12
|
+
const template_1 = require("./template");
|
|
13
|
+
function isRecord(v) {
|
|
14
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
15
|
+
}
|
|
16
|
+
/** Push a problem for every `{{var}}` referenced in the system template or the
|
|
17
|
+
* grounding query that was not declared in `prompt.variables`. Colocated with
|
|
18
|
+
* the variable parser it validates. */
|
|
19
|
+
function pushUndeclaredVariableProblems(systemTemplate, groundingQuery, variables, problems) {
|
|
20
|
+
const declared = new Set(variables);
|
|
21
|
+
if (systemTemplate !== "") {
|
|
22
|
+
for (const ref of (0, template_1.scanTemplateVariables)(systemTemplate)) {
|
|
23
|
+
if (!declared.has(ref)) {
|
|
24
|
+
problems.push(`template references undeclared variable "${ref}" (declare it in prompt.variables)`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (groundingQuery !== undefined) {
|
|
29
|
+
for (const ref of (0, template_1.scanTemplateVariables)(groundingQuery)) {
|
|
30
|
+
if (!declared.has(ref))
|
|
31
|
+
problems.push(`grounding.query references undeclared variable "${ref}"`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Parse `prompt.variables` — each entry is a bare name (semi, stays in the
|
|
36
|
+
* system slot — the default) or `{name, "x-trust": "untrusted"}` (spotlighted out
|
|
37
|
+
* of the system slot, S2). Returns the declared names and, when any variable is
|
|
38
|
+
* annotated, the trust map. Backward-compatible with a plain list of strings. */
|
|
39
|
+
function parseVariables(rawVars, problems) {
|
|
40
|
+
if (!Array.isArray(rawVars)) {
|
|
41
|
+
problems.push("prompt.variables must be a list of strings or {name, x-trust} objects");
|
|
42
|
+
return { names: [] };
|
|
43
|
+
}
|
|
44
|
+
const names = [];
|
|
45
|
+
const trust = {};
|
|
46
|
+
for (const v of rawVars) {
|
|
47
|
+
if (typeof v === "string") {
|
|
48
|
+
names.push(v);
|
|
49
|
+
}
|
|
50
|
+
else if (isRecord(v) && typeof v.name === "string") {
|
|
51
|
+
names.push(v.name);
|
|
52
|
+
if (v["x-trust"] !== undefined) {
|
|
53
|
+
if (v["x-trust"] !== "untrusted") {
|
|
54
|
+
problems.push(`prompt.variables "${v.name}": x-trust must be "untrusted" when set`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
trust[v.name] = "untrusted";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
problems.push('prompt.variables entries must be a string or {name, "x-trust"?: "untrusted"}');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return Object.keys(trust).length > 0 ? { names, trust } : { names };
|
|
66
|
+
}
|
|
67
|
+
/** Parse the optional `grounding.assembly` knob (S1). `legacy` (default, absent)
|
|
68
|
+
* = byte-identical system-prompt injection; `spotlight` = untrusted user-slot
|
|
69
|
+
* block via the provenance assembler. The flip is bake-off-gated (spec §2.4). */
|
|
70
|
+
function parseGroundingAssembly(grounding, problems) {
|
|
71
|
+
const asm = grounding.assembly;
|
|
72
|
+
if (asm === undefined)
|
|
73
|
+
return undefined;
|
|
74
|
+
if (asm !== "legacy" && asm !== "spotlight") {
|
|
75
|
+
problems.push('grounding.assembly must be "legacy" or "spotlight"');
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return asm;
|
|
79
|
+
}
|
|
@@ -10,6 +10,16 @@ import type { CapabilityFlag } from "../types/provider";
|
|
|
10
10
|
export interface RenderContext {
|
|
11
11
|
readonly variables: Record<string, unknown>;
|
|
12
12
|
readonly capabilities: ReadonlySet<CapabilityFlag>;
|
|
13
|
+
/** Screening S2 (SC-0 B3): variables annotated `x-trust: untrusted` are
|
|
14
|
+
* removed from the (trusted) system slot — their `{{var}}` renders empty —
|
|
15
|
+
* and delivered instead as a spotlighted untrusted user-slot block (see
|
|
16
|
+
* run/grounding.ts `untrustedUserBlock`). The untrusted-input policy sentence
|
|
17
|
+
* for the system slot is NOT emitted here: the provenance assembler owns it as
|
|
18
|
+
* a single source (run/grounding.ts `untrustedSystemAppend`, screening F2), so
|
|
19
|
+
* it fires exactly once whenever any untrusted segment is delivered — including
|
|
20
|
+
* an x-trust variable that is not referenced in this template. Absent ⇒ every
|
|
21
|
+
* variable renders in place (default). */
|
|
22
|
+
readonly variableTrust?: Readonly<Record<string, "untrusted">>;
|
|
13
23
|
}
|
|
14
24
|
export declare function renderTemplate(template: string, ctx: RenderContext): string;
|
|
15
25
|
/** Distinct {{var}} names referenced anywhere in the template (loader
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/routes/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/routes/template.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IACnD;;;;;;;;8CAQ0C;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;CAChE;AAkGD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CAM3E;AAED;+DAC+D;AAC/D,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAIzE"}
|
package/dist/routes/template.js
CHANGED
|
@@ -69,12 +69,19 @@ function resolveConditionals(template, capabilities) {
|
|
|
69
69
|
}
|
|
70
70
|
return out + template.slice(cursor);
|
|
71
71
|
}
|
|
72
|
-
/** Pass 2: substitute {{var}} from ctx.variables; missing variables throw.
|
|
73
|
-
|
|
72
|
+
/** Pass 2: substitute {{var}} from ctx.variables; missing variables throw. A
|
|
73
|
+
* variable annotated `x-trust: untrusted` renders EMPTY here — the
|
|
74
|
+
* security-critical system-slot removal — because it is spotlighted into the
|
|
75
|
+
* user slot instead. The paired policy sentence for the system slot is emitted
|
|
76
|
+
* by the provenance assembler, not here (screening F2, single owner). */
|
|
77
|
+
function substituteVariables(template, variables, variableTrust) {
|
|
74
78
|
return template.replace(VAR_TAG, (_match, name) => {
|
|
75
79
|
if (!(name in variables)) {
|
|
76
80
|
throw new Error(`template error: missing variable "${name}"`);
|
|
77
81
|
}
|
|
82
|
+
if (variableTrust?.[name] === "untrusted") {
|
|
83
|
+
return "";
|
|
84
|
+
}
|
|
78
85
|
const value = variables[name];
|
|
79
86
|
if (typeof value === "string")
|
|
80
87
|
return value;
|
|
@@ -82,7 +89,7 @@ function substituteVariables(template, variables) {
|
|
|
82
89
|
});
|
|
83
90
|
}
|
|
84
91
|
function renderTemplate(template, ctx) {
|
|
85
|
-
return substituteVariables(resolveConditionals(template, ctx.capabilities), ctx.variables);
|
|
92
|
+
return substituteVariables(resolveConditionals(template, ctx.capabilities), ctx.variables, ctx.variableTrust);
|
|
86
93
|
}
|
|
87
94
|
/** Distinct {{var}} names referenced anywhere in the template (loader
|
|
88
95
|
* validation: every reference must be a declared variable). */
|
package/dist/run/accept.d.ts
CHANGED
|
@@ -34,8 +34,12 @@ export interface SuccessMetaInput {
|
|
|
34
34
|
readonly callId: string;
|
|
35
35
|
/** Grounding-inject citations, when the search rung served this run. */
|
|
36
36
|
readonly citations?: RunMeta["citations"];
|
|
37
|
+
/** Grounding hygiene counters (SC-0 B3 S5) — dropped-citation count. */
|
|
38
|
+
readonly grounding?: RunMeta["grounding"];
|
|
37
39
|
/** Q1 quality verdict, when a gate ran on this run. */
|
|
38
40
|
readonly quality?: RunMeta["quality"];
|
|
41
|
+
/** CS-1 mask receipt (spec §6) — counts-only, when the route masks. */
|
|
42
|
+
readonly mask?: RunMeta["mask"];
|
|
39
43
|
}
|
|
40
44
|
/** The validated `RunMeta` for the accept path — `repairedBy` is null here (the
|
|
41
45
|
* repair path builds its own meta), `validated` is always true. */
|
package/dist/run/accept.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accept.d.ts","sourceRoot":"","sources":["../../src/run/accept.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE;;;iDAGiD;AACjD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,YAAY,EACvB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,OAAO,EACvB,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,UAAU,EAAE,iBAAiB,EAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,gBAAgB,CAiBlB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAChE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1C,uDAAuD;IACvD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"accept.d.ts","sourceRoot":"","sources":["../../src/run/accept.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE;;;iDAGiD;AACjD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,YAAY,EACvB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,OAAO,EACvB,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,UAAU,EAAE,iBAAiB,EAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,gBAAgB,CAiBlB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAChE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1C,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1C,uDAAuD;IACvD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACtC,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;mEACmE;AACnE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAyBjE"}
|
package/dist/run/accept.js
CHANGED
|
@@ -60,6 +60,8 @@ function buildSuccessMeta(input) {
|
|
|
60
60
|
repairedBy: null,
|
|
61
61
|
callId: input.callId,
|
|
62
62
|
...(input.citations !== undefined ? { citations: input.citations } : {}),
|
|
63
|
+
...(input.grounding !== undefined ? { grounding: input.grounding } : {}),
|
|
63
64
|
...(input.quality !== undefined ? { quality: input.quality } : {}),
|
|
65
|
+
...(input.mask !== undefined ? { mask: input.mask } : {}),
|
|
64
66
|
};
|
|
65
67
|
}
|
package/dist/run/dispatch.d.ts
CHANGED
|
@@ -14,6 +14,9 @@ import type { RouteBundle, RunMeta, RunOptions, RunResult, RunTags } from "../ty
|
|
|
14
14
|
import type { TelemetryRung, TelemetryStore } from "../types/telemetry";
|
|
15
15
|
import type { AttemptMetaSource } from "../telemetry/attempt-meta";
|
|
16
16
|
import type { LadderKeyMinter } from "./ladder-key";
|
|
17
|
+
import type { MaskReceipt, ResolvedMaskPolicy } from "../mask/types";
|
|
18
|
+
import type { RunVault } from "../mask/vault";
|
|
19
|
+
import { type MaskSeam } from "../mask/seam";
|
|
17
20
|
/** One telemetry attempt row's inputs — shared with run.ts's recordAttempt so
|
|
18
21
|
* the tool-call helper here can record through the same closure. */
|
|
19
22
|
export interface AttemptTelemetry {
|
|
@@ -49,6 +52,10 @@ export interface AttemptTelemetry {
|
|
|
49
52
|
* `quality` / `quality_score` here). Never carries `rung` — the recorder
|
|
50
53
|
* stamps that last so a caller cannot override it. */
|
|
51
54
|
readonly extraTags?: Record<string, string>;
|
|
55
|
+
/** CS-1 Proven Masking receipt (spec §6) — the counts-only mask summary for
|
|
56
|
+
* this attempt, written to `inferences.mask` by record-attempt.ts. Present
|
|
57
|
+
* only on a masked route; NEVER a matched value. Additive & optional. */
|
|
58
|
+
readonly mask?: MaskReceipt;
|
|
52
59
|
}
|
|
53
60
|
/** Assemble the recorder's `metaInputs` from a completed dispatch (WI-1) — the
|
|
54
61
|
* adapter's native meta plus the rendered request (system+user+schema, hashed)
|
|
@@ -105,6 +112,34 @@ export declare function buildRepairAdapterRequest(route: RouteBundle, candidate:
|
|
|
105
112
|
* buffered `call()`.
|
|
106
113
|
*/
|
|
107
114
|
export declare function dispatchCandidate(adapter: ProviderAdapter, req: AdapterRequest, onDelta?: StreamDeltaSink): Promise<AdapterResult>;
|
|
115
|
+
/** The active mask context for one run: the route's resolved policy + the
|
|
116
|
+
* run-scoped vault (shared across attempts so a value keeps one token). */
|
|
117
|
+
export interface MaskContext {
|
|
118
|
+
readonly policy: ResolvedMaskPolicy;
|
|
119
|
+
readonly vault: RunVault;
|
|
120
|
+
}
|
|
121
|
+
/** The outcome of a build+mask+dispatch (CS-1 seam, spec §1.2). Carries the
|
|
122
|
+
* (possibly masked) request, the adapter result, measured latency, and the
|
|
123
|
+
* per-attempt {@link MaskSeam} the run loop uses to rehydrate the response and
|
|
124
|
+
* build the receipt. `maskRefusal` is set when masking FAILED CLOSED
|
|
125
|
+
* pre-dispatch (`block` found a match, or a detector threw in mask/block) — no
|
|
126
|
+
* request was sent, and the run loop fails the run with `invariant_violation`. */
|
|
127
|
+
export interface DispatchOutcome {
|
|
128
|
+
readonly request: AdapterRequest;
|
|
129
|
+
readonly result: AdapterResult;
|
|
130
|
+
readonly latencyMs: number;
|
|
131
|
+
readonly seam: MaskSeam | null;
|
|
132
|
+
readonly maskRefusal?: "blocked" | "error";
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Build the primary AdapterRequest, mask its outgoing user slot when the route
|
|
136
|
+
* has an active policy (spec §1.2 — "rewrites the AdapterRequest before dispatch
|
|
137
|
+
* and rehydrates the AdapterResult after"), dispatch, and time it. With no mask
|
|
138
|
+
* context this is byte-identical to `buildAdapterRequest` + `dispatchCandidate`
|
|
139
|
+
* (the golden test). The trusted system slot is never masked (B3 keeps untrusted
|
|
140
|
+
* content in the user path).
|
|
141
|
+
*/
|
|
142
|
+
export declare function buildDispatchMaybeMasked(adapter: ProviderAdapter, parts: PrimaryRequestParts, onDelta: StreamDeltaSink | undefined, mask: MaskContext | null): Promise<DispatchOutcome>;
|
|
108
143
|
export interface ToolCallResultParts {
|
|
109
144
|
readonly route: RouteBundle;
|
|
110
145
|
readonly candidate: CandidateRef;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/run/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,eAAe,EACf,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAInE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/run/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,eAAe,EACf,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAInE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7D;oEACoE;AACpE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;6DACyD;IACzD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;0BACsB;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;;gEAE4D;IAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC;IAC9B;;;uFAGmF;IACnF,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IACxC;;0DAEsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C;;6EAEyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;CAC7B;AAED;;;+DAG+D;AAC/D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CAC5C,GAAG,iBAAiB,CAWpB;AAED;gEACgE;AAChE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC;AAElE;;4EAE4E;AAC5E,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,cAAc,EACzB,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,gBAAgB,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,GACtB,IAAI,CAoCN;AAED;;8EAE8E;AAC9E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED;;0CAE0C;AAC1C,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B;;oEAEgE;IAChE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED;uDACuD;AACvD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc,CAgC9E;AAED;4CAC4C;AAC5C,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GACtB,cAAc,CAmBhB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,eAAe,EACxB,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,aAAa,CAAC,CAuBxB;AAED;2EAC2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED;;;;;kFAKkF;AAClF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAC5C;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,IAAI,EAAE,WAAW,GAAG,IAAI,GACvB,OAAO,CAAC,eAAe,CAAC,CAsB1B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrD,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;kDAC8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CACzC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,mBAAmB,GAAG,SAAS,CAiD/F"}
|
package/dist/run/dispatch.js
CHANGED
|
@@ -16,11 +16,13 @@ exports.jsonModeCoaching = jsonModeCoaching;
|
|
|
16
16
|
exports.buildAdapterRequest = buildAdapterRequest;
|
|
17
17
|
exports.buildRepairAdapterRequest = buildRepairAdapterRequest;
|
|
18
18
|
exports.dispatchCandidate = dispatchCandidate;
|
|
19
|
+
exports.buildDispatchMaybeMasked = buildDispatchMaybeMasked;
|
|
19
20
|
exports.emitToolCallResult = emitToolCallResult;
|
|
20
21
|
const node_crypto_1 = require("node:crypto");
|
|
21
22
|
const attempt_meta_1 = require("../telemetry/attempt-meta");
|
|
22
23
|
const cache_stamp_1 = require("./cache-stamp");
|
|
23
24
|
const cache_handle_1 = require("./cache-handle");
|
|
25
|
+
const seam_1 = require("../mask/seam");
|
|
24
26
|
/** Assemble the recorder's `metaInputs` from a completed dispatch (WI-1) — the
|
|
25
27
|
* adapter's native meta plus the rendered request (system+user+schema, hashed)
|
|
26
28
|
* and the output text (hashed). One helper so the routed lane's several record
|
|
@@ -179,6 +181,37 @@ async function dispatchCandidate(adapter, req, onDelta) {
|
|
|
179
181
|
},
|
|
180
182
|
});
|
|
181
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Build the primary AdapterRequest, mask its outgoing user slot when the route
|
|
186
|
+
* has an active policy (spec §1.2 — "rewrites the AdapterRequest before dispatch
|
|
187
|
+
* and rehydrates the AdapterResult after"), dispatch, and time it. With no mask
|
|
188
|
+
* context this is byte-identical to `buildAdapterRequest` + `dispatchCandidate`
|
|
189
|
+
* (the golden test). The trusted system slot is never masked (B3 keeps untrusted
|
|
190
|
+
* content in the user path).
|
|
191
|
+
*/
|
|
192
|
+
async function buildDispatchMaybeMasked(adapter, parts, onDelta, mask) {
|
|
193
|
+
const built = buildAdapterRequest(parts);
|
|
194
|
+
if (mask === null) {
|
|
195
|
+
const started = Date.now();
|
|
196
|
+
const result = await dispatchCandidate(adapter, built, onDelta);
|
|
197
|
+
return { request: built, result, latencyMs: Date.now() - started, seam: null };
|
|
198
|
+
}
|
|
199
|
+
const seam = (0, seam_1.createMaskSeam)(mask.policy, mask.vault);
|
|
200
|
+
const outcome = seam.maskRequest(built);
|
|
201
|
+
if (outcome.kind !== "ok") {
|
|
202
|
+
// Fail closed: no request is sent. The run loop refuses pre-dispatch.
|
|
203
|
+
return {
|
|
204
|
+
request: built,
|
|
205
|
+
result: { ok: false, failure: { class: "invariant_violation", message: `masking failed closed (${outcome.kind})`, provider: parts.candidate.provider, model: parts.candidate.model } },
|
|
206
|
+
latencyMs: 0,
|
|
207
|
+
seam,
|
|
208
|
+
maskRefusal: outcome.kind,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const started = Date.now();
|
|
212
|
+
const result = await dispatchCandidate(adapter, outcome.request, onDelta);
|
|
213
|
+
return { request: outcome.request, result, latencyMs: Date.now() - started, seam };
|
|
214
|
+
}
|
|
182
215
|
/**
|
|
183
216
|
* Record a tool-call turn and build its RunResult (spec §4.4). A tool call is
|
|
184
217
|
* NOT a schema-validated JSON turn: it records a normal (non-failure) telemetry
|