agent-inspect 6.29.5 → 6.30.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 +22 -0
- package/README.md +1 -1
- package/docs/CLI.md +27 -5
- package/docs/TRACE-CONTRACTS.md +10 -7
- package/package.json +1 -1
- package/packages/cli/dist/{chunk-XWQEHKGB.mjs → chunk-BDRJENLM.mjs} +2334 -102
- package/packages/cli/dist/chunk-BDRJENLM.mjs.map +1 -0
- package/packages/cli/dist/index.cjs +3122 -168
- package/packages/cli/dist/index.cjs.map +1 -1
- package/packages/cli/dist/index.mjs +793 -61
- package/packages/cli/dist/index.mjs.map +1 -1
- package/packages/cli/dist/{src-XNC4EUN3.mjs → src-ZUGAUXY6.mjs} +3 -3
- package/packages/cli/dist/{src-XNC4EUN3.mjs.map → src-ZUGAUXY6.mjs.map} +1 -1
- package/packages/core/dist/advanced.cjs +19 -1
- package/packages/core/dist/advanced.cjs.map +1 -1
- package/packages/core/dist/advanced.d.cts +2 -2
- package/packages/core/dist/advanced.d.ts +2 -2
- package/packages/core/dist/advanced.mjs +2 -2
- package/packages/core/dist/checks.cjs +33 -1
- package/packages/core/dist/checks.cjs.map +1 -1
- package/packages/core/dist/checks.d.cts +2 -2
- package/packages/core/dist/checks.d.ts +2 -2
- package/packages/core/dist/checks.mjs +1 -1
- package/packages/core/dist/{chunk-TU47EKKS.mjs → chunk-OOX25GTH.mjs} +35 -3
- package/packages/core/dist/chunk-OOX25GTH.mjs.map +1 -0
- package/packages/core/dist/{index-DvSbXNot.d.ts → index-7hG_qggp.d.ts} +5 -0
- package/packages/core/dist/{index-DKv7esIo.d.cts → index-CQJUNPPe.d.cts} +5 -0
- package/packages/cli/dist/chunk-XWQEHKGB.mjs.map +0 -1
- package/packages/core/dist/chunk-TU47EKKS.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { ATTRIBUTION_CONFIDENCES, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, truncateStringForProfile, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, renderErrorLine, isAgentInspectTrace, filterMetasBySessionScope, aggregateSessionCheckResults, createBaselineRegressionRule, summarizeSemanticParity, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, formatStepLabel, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, getIndent, TreeBuilder, zeroKinds, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, projectLogicalEvents, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, isAttributionConfidence, diffRuns, manualTraceEventsToComparableRun } from './chunk-
|
|
2
|
+
import { ATTRIBUTION_CONFIDENCES, createSafetyRawContentRule, createSafetyRedactionRule, createSafetySecretPatternRule, createSafetyOversizedAttributeRule, resolveTraceDir, parseDuration, buildSessionIndex, resolveBundleRunIds, getTraceFilePath, openTrace, sha256Hex, collectTraceSchemaVersions, aggregateBundleSafeStatus, bundleFailsOnSafety, bundleRunAssetRelativePath, buildPlaceholderArtifact, EVIDENCE_HTML_FILENAME, EVIDENCE_MANIFEST_FILENAME, buildBundleMetadata, buildBundleSummaryMarkdown, buildEvidenceHtmlShell, buildEvidenceProvenanceViewHtml, EVIDENCE_FORMAT_VERSION, inferEvidenceFileRole, buildEvidenceSafetyViewHtml, buildEvidenceDiffViewHtml, buildEvidenceCircuitViewHtml, buildEvidenceOutcomesViewHtml, buildEvidenceContractsViewHtml, buildEvidenceToolsLlmViewHtml, buildEvidenceCausalFailureViewHtml, buildEvidenceTimelineViewHtml, buildEvidenceTreeViewHtml, buildEvidenceManifest, serializeEvidenceManifest, buildZipArchive, assertBundlePathContained, enrichSessionRunRecord, normalizeBundleOutputPath, sanitizeBundleRunId, defaultBundleOutputPath, runTraceChecks, assertEvidenceRelativePath, TraceDirectory, loadTraceMetadataList, loadSessionRunRecords, TraceReadError, resolveRedactionProfile, applyProfileMetadataCaps, Redactor, flattenTree, escapeHtml, safeString, compactAttributes, stableJson, escapeMarkdown, truncateStringForProfile, extractMetadata, filterTraces, truncateName, buildRunSummary, formatDuration, formatTimestamp, renderErrorLine, isAgentInspectTrace, defineTraceContract, filterMetasBySessionScope, evaluateTraceContract, aggregateSessionCheckResults, createBaselineRegressionRule, summarizeSemanticParity, buildEvidenceCiPackage, verifyEvidenceDirectory, diffTraceEvents, renderRunDiff, buildRunTimeline, renderTimeline, buildTraceStats, renderTraceStats, parseDurationFilter, searchTraces, formatStepLabel, buildActivitySummary, renderActivitySummaryHuman, buildRunWhatSummary, renderRunWhat, buildLocalExplanation, resolveSuiteTemplate, defaultSuiteConfigTemplate, loadSuiteConfig, validateSuiteConfig, runSuite, renderSuiteReport, analyzeCohort, renderCohortReport, gateHasThresholds, runGate, renderGateReport, persistedInspectEventsToTraceEvents, renderStepLine, getIndent, TreeBuilder, zeroKinds, validateEvent, traceEventToPersistedInspectEvent, isPersistedInspectEvent, createRunStatusRule, createStructureOrphanRule, createStructureCycleRule, createRunDurationRule, createMaxStepDurationRule, createRequireCompletedRule, createStallDetectionRule, createObservedOutcomeRule, createRunDepthRule, createToolUsageRule, createLlmUsageRule, createStructureRelationshipRule, createStructureParallelWidthRule, projectLogicalEvents, summarizeObservedOutcomes, extractOutcomesFromTraceEvents, renderObservedOutcomesMarkdown, renderObservedOutcomesHtml, DEFAULT_SUITE_ARTIFACTS_DIR, parseCohortMetricList, COHORT_METRIC_IDS, parseGateList, nanoid, isAttributionConfidence, diffRuns, manualTraceEventsToComparableRun } from './chunk-BDRJENLM.mjs';
|
|
3
3
|
import { realpathSync, constants as constants$1, existsSync, readFileSync } from 'fs';
|
|
4
4
|
import path19 from 'path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
@@ -13,7 +13,7 @@ import { createServer } from 'http';
|
|
|
13
13
|
import { createRequire } from 'module';
|
|
14
14
|
|
|
15
15
|
// package.json
|
|
16
|
-
var version = "6.
|
|
16
|
+
var version = "6.30.0";
|
|
17
17
|
|
|
18
18
|
// packages/cli/src/trace-dir-scale.ts
|
|
19
19
|
var TRACE_COUNT_WARN = 1e3;
|
|
@@ -3397,7 +3397,7 @@ async function newestTraceMtimeMs(traceDir) {
|
|
|
3397
3397
|
}
|
|
3398
3398
|
async function loadSessionRuns(traceDir) {
|
|
3399
3399
|
try {
|
|
3400
|
-
const mod = await import('./src-
|
|
3400
|
+
const mod = await import('./src-ZUGAUXY6.mjs');
|
|
3401
3401
|
const dbPath = mod.resolveIndexDbPath(traceDir);
|
|
3402
3402
|
const status = mod.indexStatus(dbPath);
|
|
3403
3403
|
if (!status.healthy) {
|
|
@@ -5855,7 +5855,8 @@ async function writeLocalEvidence(input3) {
|
|
|
5855
5855
|
redactionProfile: profile,
|
|
5856
5856
|
assessmentStatus,
|
|
5857
5857
|
checkResultsJson: input3.checkResultsJson,
|
|
5858
|
-
...input3.summaryText !== void 0 ? { summaryText: input3.summaryText } : {}
|
|
5858
|
+
...input3.summaryText !== void 0 ? { summaryText: input3.summaryText } : {},
|
|
5859
|
+
...input3.contractPackage !== void 0 ? { contractPackage: input3.contractPackage } : {}
|
|
5859
5860
|
});
|
|
5860
5861
|
const files = [
|
|
5861
5862
|
["evidence.html", evidencePackage["evidence.html"]],
|
|
@@ -5863,6 +5864,10 @@ async function writeLocalEvidence(input3) {
|
|
|
5863
5864
|
["check-results.json", evidencePackage["check-results.json"]],
|
|
5864
5865
|
["trace.jsonl", evidencePackage["trace.jsonl"]]
|
|
5865
5866
|
];
|
|
5867
|
+
const resolvedContract = evidencePackage["contract.resolved.json"];
|
|
5868
|
+
if (resolvedContract !== void 0) {
|
|
5869
|
+
files.push(["contract.resolved.json", resolvedContract]);
|
|
5870
|
+
}
|
|
5866
5871
|
const expected = createEvidenceCiArtifacts({
|
|
5867
5872
|
redactionProfile: profile
|
|
5868
5873
|
}).map((a) => a.path);
|
|
@@ -6824,6 +6829,131 @@ function asStringArray(value) {
|
|
|
6824
6829
|
return value;
|
|
6825
6830
|
}
|
|
6826
6831
|
var CHECKS_KEYS = /* @__PURE__ */ new Set(["select", "run", "tool", "llm", "structure", "safety"]);
|
|
6832
|
+
var ROOT_CONFIG_KEYS = /* @__PURE__ */ new Set(["checks", "contract"]);
|
|
6833
|
+
var CONTRACT_KEYS = /* @__PURE__ */ new Set([
|
|
6834
|
+
"run",
|
|
6835
|
+
"tools",
|
|
6836
|
+
"llm",
|
|
6837
|
+
"observations",
|
|
6838
|
+
"scope",
|
|
6839
|
+
"alternatives",
|
|
6840
|
+
"controls",
|
|
6841
|
+
"retry"
|
|
6842
|
+
]);
|
|
6843
|
+
var CONTRACT_BODY_KEYS = /* @__PURE__ */ new Set([
|
|
6844
|
+
"run",
|
|
6845
|
+
"tools",
|
|
6846
|
+
"llm",
|
|
6847
|
+
"observations",
|
|
6848
|
+
"controls",
|
|
6849
|
+
"retry"
|
|
6850
|
+
]);
|
|
6851
|
+
var CONTRACT_SCOPE_KEYS = /* @__PURE__ */ new Set([
|
|
6852
|
+
"runId",
|
|
6853
|
+
"subAgentId",
|
|
6854
|
+
"groupId",
|
|
6855
|
+
"workflowStep",
|
|
6856
|
+
"rootEventId"
|
|
6857
|
+
]);
|
|
6858
|
+
var CONTRACT_RUN_KEYS = /* @__PURE__ */ new Set(["requireCompleted", "allowedStatuses", "maxDurationMs"]);
|
|
6859
|
+
var CONTRACT_TOOLS_KEYS = /* @__PURE__ */ new Set([
|
|
6860
|
+
"required",
|
|
6861
|
+
"requiredTools",
|
|
6862
|
+
"forbidden",
|
|
6863
|
+
"forbiddenTools",
|
|
6864
|
+
"allowed",
|
|
6865
|
+
"maxCalls",
|
|
6866
|
+
"requiredOrder",
|
|
6867
|
+
"requiredOrderMode",
|
|
6868
|
+
"arguments",
|
|
6869
|
+
"orderRules",
|
|
6870
|
+
"defaultOccurrenceMode"
|
|
6871
|
+
]);
|
|
6872
|
+
var CONTRACT_LLM_KEYS = /* @__PURE__ */ new Set(["maxCalls", "maxTotalTokens", "allowedModels"]);
|
|
6873
|
+
var CONTRACT_OBSERVATION_KEYS = /* @__PURE__ */ new Set(["required", "failOn", "requireProvenance"]);
|
|
6874
|
+
var CONTRACT_PROVENANCE_KEYS = /* @__PURE__ */ new Set(["method", "evidence", "sameRunEventReference"]);
|
|
6875
|
+
var CONTRACT_CONTROLS_KEYS = /* @__PURE__ */ new Set([
|
|
6876
|
+
"declaredTools",
|
|
6877
|
+
"enforcedTools",
|
|
6878
|
+
"declaredToolsAttribute",
|
|
6879
|
+
"enforcedToolsAttribute",
|
|
6880
|
+
"requireDeclaredMatchesEnforced",
|
|
6881
|
+
"requireObservedWithinEnforced",
|
|
6882
|
+
"requireObservedWithinDeclared",
|
|
6883
|
+
"requiredStages"
|
|
6884
|
+
]);
|
|
6885
|
+
var CONTRACT_CONTROL_STAGES = /* @__PURE__ */ new Set([
|
|
6886
|
+
"declared",
|
|
6887
|
+
"presented",
|
|
6888
|
+
"validated",
|
|
6889
|
+
"enforced",
|
|
6890
|
+
"observed",
|
|
6891
|
+
"accepted"
|
|
6892
|
+
]);
|
|
6893
|
+
var CONTRACT_CONTROL_STAGE_KEYS = /* @__PURE__ */ new Set(["stage", "observation"]);
|
|
6894
|
+
var CONTRACT_RETRY_KEYS = /* @__PURE__ */ new Set([
|
|
6895
|
+
"maxAttempts",
|
|
6896
|
+
"requireTerminalResult",
|
|
6897
|
+
"fallbackOnlyAfterFailure",
|
|
6898
|
+
"nonIdempotentTools",
|
|
6899
|
+
"requireIdempotencyEvidenceForRetry",
|
|
6900
|
+
"requireRecoveredFailureVisible",
|
|
6901
|
+
"operations"
|
|
6902
|
+
]);
|
|
6903
|
+
var CONTRACT_OPERATION_KEYS = /* @__PURE__ */ new Set([
|
|
6904
|
+
"tool",
|
|
6905
|
+
"maxAttempts",
|
|
6906
|
+
"retryableErrors",
|
|
6907
|
+
"requireFailureBeforeRetry",
|
|
6908
|
+
"requireSameArguments",
|
|
6909
|
+
"requireTerminalSuccess",
|
|
6910
|
+
"requireRecoveredFailureVisible",
|
|
6911
|
+
"successfulResultDependency",
|
|
6912
|
+
"sideEffectClass"
|
|
6913
|
+
]);
|
|
6914
|
+
var CONTRACT_RETRYABLE_ERRORS_KEYS = /* @__PURE__ */ new Set(["codes"]);
|
|
6915
|
+
var CONTRACT_RESULT_DEP_KEYS = /* @__PURE__ */ new Set(["consumerKind", "requireExplicitReference"]);
|
|
6916
|
+
var CONTRACT_ALT_KEYS = /* @__PURE__ */ new Set(["anyOf"]);
|
|
6917
|
+
var CONTRACT_ALT_BRANCH_KEYS = /* @__PURE__ */ new Set(["id", "description", "contract"]);
|
|
6918
|
+
var CONTRACT_ORDER_RULE_KEYS = /* @__PURE__ */ new Set([
|
|
6919
|
+
"before",
|
|
6920
|
+
"after",
|
|
6921
|
+
"occurrenceMode",
|
|
6922
|
+
"requireEndpoints"
|
|
6923
|
+
]);
|
|
6924
|
+
var CONTRACT_ARGUMENT_KEYS = /* @__PURE__ */ new Set([
|
|
6925
|
+
"tool",
|
|
6926
|
+
"path",
|
|
6927
|
+
"operator",
|
|
6928
|
+
"occurrence",
|
|
6929
|
+
"expected",
|
|
6930
|
+
"oneOf",
|
|
6931
|
+
"type"
|
|
6932
|
+
]);
|
|
6933
|
+
var CONTRACT_ARGUMENT_OPERATORS = /* @__PURE__ */ new Set(["exists", "type", "equals", "oneOf"]);
|
|
6934
|
+
var CONTRACT_ARGUMENT_OCCURRENCES = /* @__PURE__ */ new Set(["first", "last", "any", "all"]);
|
|
6935
|
+
var CONTRACT_ARGUMENT_TYPES = /* @__PURE__ */ new Set([
|
|
6936
|
+
"string",
|
|
6937
|
+
"number",
|
|
6938
|
+
"boolean",
|
|
6939
|
+
"object",
|
|
6940
|
+
"array",
|
|
6941
|
+
"null"
|
|
6942
|
+
]);
|
|
6943
|
+
var CONTRACT_ORDER_MODES = /* @__PURE__ */ new Set([
|
|
6944
|
+
"first-occurrence",
|
|
6945
|
+
"happens-before",
|
|
6946
|
+
"all-occurrences"
|
|
6947
|
+
]);
|
|
6948
|
+
var CONTRACT_FAIL_ON = /* @__PURE__ */ new Set(["failed", "unknown", "skipped"]);
|
|
6949
|
+
var CONTRACT_SIDE_EFFECT_CLASSES = /* @__PURE__ */ new Set(["read", "write"]);
|
|
6950
|
+
var CONTRACT_MAX_STRING_LIST = 64;
|
|
6951
|
+
var CONTRACT_MAX_ARGUMENTS = 32;
|
|
6952
|
+
var CONTRACT_MAX_ORDER_RULES = 32;
|
|
6953
|
+
var CONTRACT_MAX_ANY_OF = 16;
|
|
6954
|
+
var CONTRACT_MAX_OPERATIONS = 32;
|
|
6955
|
+
var CONTRACT_MAX_REQUIRED_STAGES = 16;
|
|
6956
|
+
var CONTRACT_MAX_ONE_OF = 32;
|
|
6827
6957
|
var RUN_KEYS = /* @__PURE__ */ new Set(["expected", "allowIncomplete", "maxDurationMs", "maxDepth"]);
|
|
6828
6958
|
var TOOL_KEYS = /* @__PURE__ */ new Set(["required", "forbidden", "allowed", "minCount", "maxCount"]);
|
|
6829
6959
|
var LLM_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -6930,6 +7060,49 @@ function requireBoolean(value, pathPrefix) {
|
|
|
6930
7060
|
}
|
|
6931
7061
|
return value;
|
|
6932
7062
|
}
|
|
7063
|
+
function requireNonEmptyString(value, pathPrefix) {
|
|
7064
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
7065
|
+
throw new CheckConfigError(
|
|
7066
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7067
|
+
`${pathPrefix} must be a non-empty string.`
|
|
7068
|
+
);
|
|
7069
|
+
}
|
|
7070
|
+
return value;
|
|
7071
|
+
}
|
|
7072
|
+
function requireBoundedArray(value, pathPrefix, max) {
|
|
7073
|
+
if (!Array.isArray(value)) {
|
|
7074
|
+
throw new CheckConfigError(
|
|
7075
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7076
|
+
`${pathPrefix} must be an array.`
|
|
7077
|
+
);
|
|
7078
|
+
}
|
|
7079
|
+
if (value.length > max) {
|
|
7080
|
+
throw new CheckConfigError(
|
|
7081
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7082
|
+
`${pathPrefix} exceeds bound of ${max} items.`
|
|
7083
|
+
);
|
|
7084
|
+
}
|
|
7085
|
+
return value;
|
|
7086
|
+
}
|
|
7087
|
+
function requireBoundedStringArray(value, pathPrefix, max = CONTRACT_MAX_STRING_LIST) {
|
|
7088
|
+
const items = requireBoundedArray(value, pathPrefix, max);
|
|
7089
|
+
if (items.some((item) => typeof item !== "string" || item.trim() === "")) {
|
|
7090
|
+
throw new CheckConfigError(
|
|
7091
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7092
|
+
`${pathPrefix} must be an array of non-empty strings.`
|
|
7093
|
+
);
|
|
7094
|
+
}
|
|
7095
|
+
return items;
|
|
7096
|
+
}
|
|
7097
|
+
function requireOrderMode(value, pathPrefix) {
|
|
7098
|
+
if (typeof value !== "string" || !CONTRACT_ORDER_MODES.has(value)) {
|
|
7099
|
+
throw new CheckConfigError(
|
|
7100
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7101
|
+
`${pathPrefix} must be one of: "first-occurrence", "happens-before", "all-occurrences".`
|
|
7102
|
+
);
|
|
7103
|
+
}
|
|
7104
|
+
return value;
|
|
7105
|
+
}
|
|
6933
7106
|
function parseRunSection(value) {
|
|
6934
7107
|
const record = requireObject(value, "checks.run");
|
|
6935
7108
|
rejectUnknownKeys(record, RUN_KEYS, "checks.run");
|
|
@@ -7062,6 +7235,7 @@ function sectionHasEffect(section) {
|
|
|
7062
7235
|
return Object.keys(section).length > 0;
|
|
7063
7236
|
}
|
|
7064
7237
|
function checkConfigHasEffect(config) {
|
|
7238
|
+
if (contractConfigHasEffect(config.contract)) return true;
|
|
7065
7239
|
const checks2 = config.checks;
|
|
7066
7240
|
if (checks2 === void 0) return false;
|
|
7067
7241
|
if ((checks2.select?.length ?? 0) > 0) return true;
|
|
@@ -7072,43 +7246,587 @@ function checkConfigHasEffect(config) {
|
|
|
7072
7246
|
if (sectionHasEffect(checks2.safety)) return true;
|
|
7073
7247
|
return false;
|
|
7074
7248
|
}
|
|
7249
|
+
function contractConfigHasEffect(contract) {
|
|
7250
|
+
if (contract === void 0) return false;
|
|
7251
|
+
if (sectionHasEffect(contract.run)) return true;
|
|
7252
|
+
if (sectionHasEffect(contract.tools)) return true;
|
|
7253
|
+
if (sectionHasEffect(contract.llm)) return true;
|
|
7254
|
+
if (sectionHasEffect(contract.observations)) {
|
|
7255
|
+
return true;
|
|
7256
|
+
}
|
|
7257
|
+
if (sectionHasEffect(contract.controls)) return true;
|
|
7258
|
+
if (sectionHasEffect(contract.retry)) return true;
|
|
7259
|
+
if ((contract.alternatives?.anyOf?.length ?? 0) > 0) return true;
|
|
7260
|
+
return false;
|
|
7261
|
+
}
|
|
7262
|
+
function parseContractRunSection(value, pathPrefix = "contract.run") {
|
|
7263
|
+
const record = requireObject(value, pathPrefix);
|
|
7264
|
+
rejectUnknownKeys(record, CONTRACT_RUN_KEYS, pathPrefix);
|
|
7265
|
+
const out = {};
|
|
7266
|
+
if (record.requireCompleted !== void 0) {
|
|
7267
|
+
out.requireCompleted = requireBoolean(
|
|
7268
|
+
record.requireCompleted,
|
|
7269
|
+
`${pathPrefix}.requireCompleted`
|
|
7270
|
+
);
|
|
7271
|
+
}
|
|
7272
|
+
if (record.allowedStatuses !== void 0) {
|
|
7273
|
+
out.allowedStatuses = requireBoundedStringArray(
|
|
7274
|
+
record.allowedStatuses,
|
|
7275
|
+
`${pathPrefix}.allowedStatuses`
|
|
7276
|
+
);
|
|
7277
|
+
}
|
|
7278
|
+
if (record.maxDurationMs !== void 0) {
|
|
7279
|
+
out.maxDurationMs = requireNonNegativeNumber(
|
|
7280
|
+
record.maxDurationMs,
|
|
7281
|
+
`${pathPrefix}.maxDurationMs`
|
|
7282
|
+
);
|
|
7283
|
+
}
|
|
7284
|
+
return out;
|
|
7285
|
+
}
|
|
7286
|
+
function parseToolArgumentCheck(value, pathPrefix) {
|
|
7287
|
+
const record = requireObject(value, pathPrefix);
|
|
7288
|
+
rejectUnknownKeys(record, CONTRACT_ARGUMENT_KEYS, pathPrefix);
|
|
7289
|
+
const tool = requireNonEmptyString(record.tool, `${pathPrefix}.tool`);
|
|
7290
|
+
if (typeof record.path !== "string") {
|
|
7291
|
+
throw new CheckConfigError(
|
|
7292
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7293
|
+
`${pathPrefix}.path must be a string JSON Pointer ("" or start with "/").`
|
|
7294
|
+
);
|
|
7295
|
+
}
|
|
7296
|
+
const pathValue = record.path;
|
|
7297
|
+
if (typeof record.operator !== "string" || !CONTRACT_ARGUMENT_OPERATORS.has(record.operator)) {
|
|
7298
|
+
throw new CheckConfigError(
|
|
7299
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7300
|
+
`${pathPrefix}.operator must be one of: "exists", "type", "equals", "oneOf".`
|
|
7301
|
+
);
|
|
7302
|
+
}
|
|
7303
|
+
const operator = record.operator;
|
|
7304
|
+
const out = { tool, path: pathValue, operator };
|
|
7305
|
+
if (record.occurrence !== void 0) {
|
|
7306
|
+
if (typeof record.occurrence !== "string" || !CONTRACT_ARGUMENT_OCCURRENCES.has(record.occurrence)) {
|
|
7307
|
+
throw new CheckConfigError(
|
|
7308
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7309
|
+
`${pathPrefix}.occurrence must be one of: "first", "last", "any", "all".`
|
|
7310
|
+
);
|
|
7311
|
+
}
|
|
7312
|
+
out.occurrence = record.occurrence;
|
|
7313
|
+
}
|
|
7314
|
+
if (record.expected !== void 0) {
|
|
7315
|
+
out.expected = record.expected;
|
|
7316
|
+
}
|
|
7317
|
+
if (record.oneOf !== void 0) {
|
|
7318
|
+
out.oneOf = requireBoundedArray(record.oneOf, `${pathPrefix}.oneOf`, CONTRACT_MAX_ONE_OF);
|
|
7319
|
+
}
|
|
7320
|
+
if (record.type !== void 0) {
|
|
7321
|
+
if (typeof record.type !== "string" || !CONTRACT_ARGUMENT_TYPES.has(record.type)) {
|
|
7322
|
+
throw new CheckConfigError(
|
|
7323
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7324
|
+
`${pathPrefix}.type must be one of: "string", "number", "boolean", "object", "array", "null".`
|
|
7325
|
+
);
|
|
7326
|
+
}
|
|
7327
|
+
out.type = record.type;
|
|
7328
|
+
}
|
|
7329
|
+
return out;
|
|
7330
|
+
}
|
|
7331
|
+
function parseOrderRule(value, pathPrefix) {
|
|
7332
|
+
const record = requireObject(value, pathPrefix);
|
|
7333
|
+
rejectUnknownKeys(record, CONTRACT_ORDER_RULE_KEYS, pathPrefix);
|
|
7334
|
+
const out = {
|
|
7335
|
+
before: requireNonEmptyString(record.before, `${pathPrefix}.before`),
|
|
7336
|
+
after: requireNonEmptyString(record.after, `${pathPrefix}.after`)
|
|
7337
|
+
};
|
|
7338
|
+
if (record.occurrenceMode !== void 0) {
|
|
7339
|
+
out.occurrenceMode = requireOrderMode(record.occurrenceMode, `${pathPrefix}.occurrenceMode`);
|
|
7340
|
+
}
|
|
7341
|
+
if (record.requireEndpoints !== void 0) {
|
|
7342
|
+
out.requireEndpoints = requireBoolean(
|
|
7343
|
+
record.requireEndpoints,
|
|
7344
|
+
`${pathPrefix}.requireEndpoints`
|
|
7345
|
+
);
|
|
7346
|
+
}
|
|
7347
|
+
return out;
|
|
7348
|
+
}
|
|
7349
|
+
function parseContractToolsSection(value, pathPrefix = "contract.tools") {
|
|
7350
|
+
const record = requireObject(value, pathPrefix);
|
|
7351
|
+
rejectUnknownKeys(record, CONTRACT_TOOLS_KEYS, pathPrefix);
|
|
7352
|
+
const out = {};
|
|
7353
|
+
if (record.required !== void 0) {
|
|
7354
|
+
out.required = requireBoundedStringArray(record.required, `${pathPrefix}.required`);
|
|
7355
|
+
}
|
|
7356
|
+
if (record.requiredTools !== void 0) {
|
|
7357
|
+
out.requiredTools = requireBoundedStringArray(
|
|
7358
|
+
record.requiredTools,
|
|
7359
|
+
`${pathPrefix}.requiredTools`
|
|
7360
|
+
);
|
|
7361
|
+
}
|
|
7362
|
+
if (record.forbidden !== void 0) {
|
|
7363
|
+
out.forbidden = requireBoundedStringArray(record.forbidden, `${pathPrefix}.forbidden`);
|
|
7364
|
+
}
|
|
7365
|
+
if (record.forbiddenTools !== void 0) {
|
|
7366
|
+
out.forbiddenTools = requireBoundedStringArray(
|
|
7367
|
+
record.forbiddenTools,
|
|
7368
|
+
`${pathPrefix}.forbiddenTools`
|
|
7369
|
+
);
|
|
7370
|
+
}
|
|
7371
|
+
if (record.allowed !== void 0) {
|
|
7372
|
+
out.allowed = requireBoundedStringArray(record.allowed, `${pathPrefix}.allowed`);
|
|
7373
|
+
}
|
|
7374
|
+
if (record.maxCalls !== void 0) {
|
|
7375
|
+
out.maxCalls = requireNonNegativeNumber(record.maxCalls, `${pathPrefix}.maxCalls`);
|
|
7376
|
+
}
|
|
7377
|
+
if (record.requiredOrder !== void 0) {
|
|
7378
|
+
out.requiredOrder = requireBoundedStringArray(
|
|
7379
|
+
record.requiredOrder,
|
|
7380
|
+
`${pathPrefix}.requiredOrder`
|
|
7381
|
+
);
|
|
7382
|
+
}
|
|
7383
|
+
if (record.requiredOrderMode !== void 0) {
|
|
7384
|
+
out.requiredOrderMode = requireOrderMode(
|
|
7385
|
+
record.requiredOrderMode,
|
|
7386
|
+
`${pathPrefix}.requiredOrderMode`
|
|
7387
|
+
);
|
|
7388
|
+
}
|
|
7389
|
+
if (record.defaultOccurrenceMode !== void 0) {
|
|
7390
|
+
out.defaultOccurrenceMode = requireOrderMode(
|
|
7391
|
+
record.defaultOccurrenceMode,
|
|
7392
|
+
`${pathPrefix}.defaultOccurrenceMode`
|
|
7393
|
+
);
|
|
7394
|
+
}
|
|
7395
|
+
if (record.arguments !== void 0) {
|
|
7396
|
+
const items = requireBoundedArray(
|
|
7397
|
+
record.arguments,
|
|
7398
|
+
`${pathPrefix}.arguments`,
|
|
7399
|
+
CONTRACT_MAX_ARGUMENTS
|
|
7400
|
+
);
|
|
7401
|
+
out.arguments = items.map(
|
|
7402
|
+
(item, index) => parseToolArgumentCheck(item, `${pathPrefix}.arguments[${index}]`)
|
|
7403
|
+
);
|
|
7404
|
+
}
|
|
7405
|
+
if (record.orderRules !== void 0) {
|
|
7406
|
+
const items = requireBoundedArray(
|
|
7407
|
+
record.orderRules,
|
|
7408
|
+
`${pathPrefix}.orderRules`,
|
|
7409
|
+
CONTRACT_MAX_ORDER_RULES
|
|
7410
|
+
);
|
|
7411
|
+
out.orderRules = items.map(
|
|
7412
|
+
(item, index) => parseOrderRule(item, `${pathPrefix}.orderRules[${index}]`)
|
|
7413
|
+
);
|
|
7414
|
+
}
|
|
7415
|
+
return out;
|
|
7416
|
+
}
|
|
7417
|
+
function parseContractLlmSection(value, pathPrefix = "contract.llm") {
|
|
7418
|
+
const record = requireObject(value, pathPrefix);
|
|
7419
|
+
rejectUnknownKeys(record, CONTRACT_LLM_KEYS, pathPrefix);
|
|
7420
|
+
const out = {};
|
|
7421
|
+
if (record.maxCalls !== void 0) {
|
|
7422
|
+
out.maxCalls = requireNonNegativeNumber(record.maxCalls, `${pathPrefix}.maxCalls`);
|
|
7423
|
+
}
|
|
7424
|
+
if (record.maxTotalTokens !== void 0) {
|
|
7425
|
+
out.maxTotalTokens = requireNonNegativeNumber(
|
|
7426
|
+
record.maxTotalTokens,
|
|
7427
|
+
`${pathPrefix}.maxTotalTokens`
|
|
7428
|
+
);
|
|
7429
|
+
}
|
|
7430
|
+
if (record.allowedModels !== void 0) {
|
|
7431
|
+
out.allowedModels = requireBoundedStringArray(
|
|
7432
|
+
record.allowedModels,
|
|
7433
|
+
`${pathPrefix}.allowedModels`
|
|
7434
|
+
);
|
|
7435
|
+
}
|
|
7436
|
+
return out;
|
|
7437
|
+
}
|
|
7438
|
+
function parseRequireProvenance(value, pathPrefix) {
|
|
7439
|
+
const record = requireObject(value, pathPrefix);
|
|
7440
|
+
rejectUnknownKeys(record, CONTRACT_PROVENANCE_KEYS, pathPrefix);
|
|
7441
|
+
const out = {};
|
|
7442
|
+
if (record.method !== void 0) {
|
|
7443
|
+
out.method = requireBoolean(record.method, `${pathPrefix}.method`);
|
|
7444
|
+
}
|
|
7445
|
+
if (record.evidence !== void 0) {
|
|
7446
|
+
out.evidence = requireBoolean(record.evidence, `${pathPrefix}.evidence`);
|
|
7447
|
+
}
|
|
7448
|
+
if (record.sameRunEventReference !== void 0) {
|
|
7449
|
+
out.sameRunEventReference = requireBoolean(
|
|
7450
|
+
record.sameRunEventReference,
|
|
7451
|
+
`${pathPrefix}.sameRunEventReference`
|
|
7452
|
+
);
|
|
7453
|
+
}
|
|
7454
|
+
return out;
|
|
7455
|
+
}
|
|
7456
|
+
function parseContractObservationsSection(value, pathPrefix = "contract.observations") {
|
|
7457
|
+
const record = requireObject(value, pathPrefix);
|
|
7458
|
+
rejectUnknownKeys(record, CONTRACT_OBSERVATION_KEYS, pathPrefix);
|
|
7459
|
+
const out = {};
|
|
7460
|
+
if (record.required !== void 0) {
|
|
7461
|
+
out.required = requireBoundedStringArray(record.required, `${pathPrefix}.required`);
|
|
7462
|
+
}
|
|
7463
|
+
if (record.failOn !== void 0) {
|
|
7464
|
+
const items = requireBoundedArray(record.failOn, `${pathPrefix}.failOn`, CONTRACT_MAX_STRING_LIST);
|
|
7465
|
+
for (const item of items) {
|
|
7466
|
+
if (typeof item !== "string" || !CONTRACT_FAIL_ON.has(item)) {
|
|
7467
|
+
throw new CheckConfigError(
|
|
7468
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7469
|
+
`${pathPrefix}.failOn values must be "failed", "unknown", or "skipped".`
|
|
7470
|
+
);
|
|
7471
|
+
}
|
|
7472
|
+
}
|
|
7473
|
+
out.failOn = items;
|
|
7474
|
+
}
|
|
7475
|
+
if (record.requireProvenance !== void 0) {
|
|
7476
|
+
out.requireProvenance = parseRequireProvenance(
|
|
7477
|
+
record.requireProvenance,
|
|
7478
|
+
`${pathPrefix}.requireProvenance`
|
|
7479
|
+
);
|
|
7480
|
+
}
|
|
7481
|
+
return out;
|
|
7482
|
+
}
|
|
7483
|
+
function parseControlRequiredStage(value, pathPrefix) {
|
|
7484
|
+
const record = requireObject(value, pathPrefix);
|
|
7485
|
+
rejectUnknownKeys(record, CONTRACT_CONTROL_STAGE_KEYS, pathPrefix);
|
|
7486
|
+
if (typeof record.stage !== "string" || !CONTRACT_CONTROL_STAGES.has(record.stage)) {
|
|
7487
|
+
throw new CheckConfigError(
|
|
7488
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7489
|
+
`${pathPrefix}.stage must be one of: declared, presented, validated, enforced, observed, accepted.`
|
|
7490
|
+
);
|
|
7491
|
+
}
|
|
7492
|
+
const out = {
|
|
7493
|
+
stage: record.stage
|
|
7494
|
+
};
|
|
7495
|
+
if (record.observation !== void 0) {
|
|
7496
|
+
out.observation = requireNonEmptyString(record.observation, `${pathPrefix}.observation`);
|
|
7497
|
+
}
|
|
7498
|
+
return out;
|
|
7499
|
+
}
|
|
7500
|
+
function parseContractControlsSection(value, pathPrefix = "contract.controls") {
|
|
7501
|
+
const record = requireObject(value, pathPrefix);
|
|
7502
|
+
rejectUnknownKeys(record, CONTRACT_CONTROLS_KEYS, pathPrefix);
|
|
7503
|
+
const out = {};
|
|
7504
|
+
if (record.declaredTools !== void 0) {
|
|
7505
|
+
out.declaredTools = requireBoundedStringArray(
|
|
7506
|
+
record.declaredTools,
|
|
7507
|
+
`${pathPrefix}.declaredTools`
|
|
7508
|
+
);
|
|
7509
|
+
}
|
|
7510
|
+
if (record.enforcedTools !== void 0) {
|
|
7511
|
+
out.enforcedTools = requireBoundedStringArray(
|
|
7512
|
+
record.enforcedTools,
|
|
7513
|
+
`${pathPrefix}.enforcedTools`
|
|
7514
|
+
);
|
|
7515
|
+
}
|
|
7516
|
+
if (record.declaredToolsAttribute !== void 0) {
|
|
7517
|
+
out.declaredToolsAttribute = requireNonEmptyString(
|
|
7518
|
+
record.declaredToolsAttribute,
|
|
7519
|
+
`${pathPrefix}.declaredToolsAttribute`
|
|
7520
|
+
);
|
|
7521
|
+
}
|
|
7522
|
+
if (record.enforcedToolsAttribute !== void 0) {
|
|
7523
|
+
out.enforcedToolsAttribute = requireNonEmptyString(
|
|
7524
|
+
record.enforcedToolsAttribute,
|
|
7525
|
+
`${pathPrefix}.enforcedToolsAttribute`
|
|
7526
|
+
);
|
|
7527
|
+
}
|
|
7528
|
+
if (record.requireDeclaredMatchesEnforced !== void 0) {
|
|
7529
|
+
out.requireDeclaredMatchesEnforced = requireBoolean(
|
|
7530
|
+
record.requireDeclaredMatchesEnforced,
|
|
7531
|
+
`${pathPrefix}.requireDeclaredMatchesEnforced`
|
|
7532
|
+
);
|
|
7533
|
+
}
|
|
7534
|
+
if (record.requireObservedWithinEnforced !== void 0) {
|
|
7535
|
+
out.requireObservedWithinEnforced = requireBoolean(
|
|
7536
|
+
record.requireObservedWithinEnforced,
|
|
7537
|
+
`${pathPrefix}.requireObservedWithinEnforced`
|
|
7538
|
+
);
|
|
7539
|
+
}
|
|
7540
|
+
if (record.requireObservedWithinDeclared !== void 0) {
|
|
7541
|
+
out.requireObservedWithinDeclared = requireBoolean(
|
|
7542
|
+
record.requireObservedWithinDeclared,
|
|
7543
|
+
`${pathPrefix}.requireObservedWithinDeclared`
|
|
7544
|
+
);
|
|
7545
|
+
}
|
|
7546
|
+
if (record.requiredStages !== void 0) {
|
|
7547
|
+
const items = requireBoundedArray(
|
|
7548
|
+
record.requiredStages,
|
|
7549
|
+
`${pathPrefix}.requiredStages`,
|
|
7550
|
+
CONTRACT_MAX_REQUIRED_STAGES
|
|
7551
|
+
);
|
|
7552
|
+
out.requiredStages = items.map(
|
|
7553
|
+
(item, index) => parseControlRequiredStage(item, `${pathPrefix}.requiredStages[${index}]`)
|
|
7554
|
+
);
|
|
7555
|
+
}
|
|
7556
|
+
return out;
|
|
7557
|
+
}
|
|
7558
|
+
function parseRecoveryOperation(value, pathPrefix) {
|
|
7559
|
+
const record = requireObject(value, pathPrefix);
|
|
7560
|
+
rejectUnknownKeys(record, CONTRACT_OPERATION_KEYS, pathPrefix);
|
|
7561
|
+
const out = {
|
|
7562
|
+
tool: requireNonEmptyString(record.tool, `${pathPrefix}.tool`)
|
|
7563
|
+
};
|
|
7564
|
+
if (record.maxAttempts !== void 0) {
|
|
7565
|
+
out.maxAttempts = requireNonNegativeNumber(record.maxAttempts, `${pathPrefix}.maxAttempts`);
|
|
7566
|
+
}
|
|
7567
|
+
if (record.retryableErrors !== void 0) {
|
|
7568
|
+
const errors = requireObject(record.retryableErrors, `${pathPrefix}.retryableErrors`);
|
|
7569
|
+
rejectUnknownKeys(errors, CONTRACT_RETRYABLE_ERRORS_KEYS, `${pathPrefix}.retryableErrors`);
|
|
7570
|
+
const retryableErrors = {};
|
|
7571
|
+
if (errors.codes !== void 0) {
|
|
7572
|
+
retryableErrors.codes = requireBoundedStringArray(
|
|
7573
|
+
errors.codes,
|
|
7574
|
+
`${pathPrefix}.retryableErrors.codes`
|
|
7575
|
+
);
|
|
7576
|
+
}
|
|
7577
|
+
out.retryableErrors = retryableErrors;
|
|
7578
|
+
}
|
|
7579
|
+
if (record.requireFailureBeforeRetry !== void 0) {
|
|
7580
|
+
out.requireFailureBeforeRetry = requireBoolean(
|
|
7581
|
+
record.requireFailureBeforeRetry,
|
|
7582
|
+
`${pathPrefix}.requireFailureBeforeRetry`
|
|
7583
|
+
);
|
|
7584
|
+
}
|
|
7585
|
+
if (record.requireSameArguments !== void 0) {
|
|
7586
|
+
if (record.requireSameArguments === true || record.requireSameArguments === false) {
|
|
7587
|
+
out.requireSameArguments = record.requireSameArguments;
|
|
7588
|
+
} else if (record.requireSameArguments === "structured-or-digest") {
|
|
7589
|
+
out.requireSameArguments = "structured-or-digest";
|
|
7590
|
+
} else {
|
|
7591
|
+
throw new CheckConfigError(
|
|
7592
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7593
|
+
`${pathPrefix}.requireSameArguments must be a boolean or "structured-or-digest".`
|
|
7594
|
+
);
|
|
7595
|
+
}
|
|
7596
|
+
}
|
|
7597
|
+
if (record.requireTerminalSuccess !== void 0) {
|
|
7598
|
+
out.requireTerminalSuccess = requireBoolean(
|
|
7599
|
+
record.requireTerminalSuccess,
|
|
7600
|
+
`${pathPrefix}.requireTerminalSuccess`
|
|
7601
|
+
);
|
|
7602
|
+
}
|
|
7603
|
+
if (record.requireRecoveredFailureVisible !== void 0) {
|
|
7604
|
+
out.requireRecoveredFailureVisible = requireBoolean(
|
|
7605
|
+
record.requireRecoveredFailureVisible,
|
|
7606
|
+
`${pathPrefix}.requireRecoveredFailureVisible`
|
|
7607
|
+
);
|
|
7608
|
+
}
|
|
7609
|
+
if (record.successfulResultDependency !== void 0) {
|
|
7610
|
+
const dep = requireObject(
|
|
7611
|
+
record.successfulResultDependency,
|
|
7612
|
+
`${pathPrefix}.successfulResultDependency`
|
|
7613
|
+
);
|
|
7614
|
+
rejectUnknownKeys(dep, CONTRACT_RESULT_DEP_KEYS, `${pathPrefix}.successfulResultDependency`);
|
|
7615
|
+
if (dep.consumerKind !== "LLM") {
|
|
7616
|
+
throw new CheckConfigError(
|
|
7617
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7618
|
+
`${pathPrefix}.successfulResultDependency.consumerKind must be "LLM".`
|
|
7619
|
+
);
|
|
7620
|
+
}
|
|
7621
|
+
const dependency = { consumerKind: "LLM" };
|
|
7622
|
+
if (dep.requireExplicitReference !== void 0) {
|
|
7623
|
+
dependency.requireExplicitReference = requireBoolean(
|
|
7624
|
+
dep.requireExplicitReference,
|
|
7625
|
+
`${pathPrefix}.successfulResultDependency.requireExplicitReference`
|
|
7626
|
+
);
|
|
7627
|
+
}
|
|
7628
|
+
out.successfulResultDependency = dependency;
|
|
7629
|
+
}
|
|
7630
|
+
if (record.sideEffectClass !== void 0) {
|
|
7631
|
+
if (typeof record.sideEffectClass !== "string" || !CONTRACT_SIDE_EFFECT_CLASSES.has(record.sideEffectClass)) {
|
|
7632
|
+
throw new CheckConfigError(
|
|
7633
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7634
|
+
`${pathPrefix}.sideEffectClass must be "read" or "write".`
|
|
7635
|
+
);
|
|
7636
|
+
}
|
|
7637
|
+
out.sideEffectClass = record.sideEffectClass;
|
|
7638
|
+
}
|
|
7639
|
+
return out;
|
|
7640
|
+
}
|
|
7641
|
+
function parseContractRetrySection(value, pathPrefix = "contract.retry") {
|
|
7642
|
+
const record = requireObject(value, pathPrefix);
|
|
7643
|
+
rejectUnknownKeys(record, CONTRACT_RETRY_KEYS, pathPrefix);
|
|
7644
|
+
const out = {};
|
|
7645
|
+
if (record.maxAttempts !== void 0) {
|
|
7646
|
+
out.maxAttempts = requireNonNegativeNumber(record.maxAttempts, `${pathPrefix}.maxAttempts`);
|
|
7647
|
+
}
|
|
7648
|
+
if (record.requireTerminalResult !== void 0) {
|
|
7649
|
+
out.requireTerminalResult = requireBoolean(
|
|
7650
|
+
record.requireTerminalResult,
|
|
7651
|
+
`${pathPrefix}.requireTerminalResult`
|
|
7652
|
+
);
|
|
7653
|
+
}
|
|
7654
|
+
if (record.fallbackOnlyAfterFailure !== void 0) {
|
|
7655
|
+
out.fallbackOnlyAfterFailure = requireBoolean(
|
|
7656
|
+
record.fallbackOnlyAfterFailure,
|
|
7657
|
+
`${pathPrefix}.fallbackOnlyAfterFailure`
|
|
7658
|
+
);
|
|
7659
|
+
}
|
|
7660
|
+
if (record.nonIdempotentTools !== void 0) {
|
|
7661
|
+
out.nonIdempotentTools = requireBoundedStringArray(
|
|
7662
|
+
record.nonIdempotentTools,
|
|
7663
|
+
`${pathPrefix}.nonIdempotentTools`
|
|
7664
|
+
);
|
|
7665
|
+
}
|
|
7666
|
+
if (record.requireIdempotencyEvidenceForRetry !== void 0) {
|
|
7667
|
+
out.requireIdempotencyEvidenceForRetry = requireBoolean(
|
|
7668
|
+
record.requireIdempotencyEvidenceForRetry,
|
|
7669
|
+
`${pathPrefix}.requireIdempotencyEvidenceForRetry`
|
|
7670
|
+
);
|
|
7671
|
+
}
|
|
7672
|
+
if (record.requireRecoveredFailureVisible !== void 0) {
|
|
7673
|
+
out.requireRecoveredFailureVisible = requireBoolean(
|
|
7674
|
+
record.requireRecoveredFailureVisible,
|
|
7675
|
+
`${pathPrefix}.requireRecoveredFailureVisible`
|
|
7676
|
+
);
|
|
7677
|
+
}
|
|
7678
|
+
if (record.operations !== void 0) {
|
|
7679
|
+
const items = requireBoundedArray(
|
|
7680
|
+
record.operations,
|
|
7681
|
+
`${pathPrefix}.operations`,
|
|
7682
|
+
CONTRACT_MAX_OPERATIONS
|
|
7683
|
+
);
|
|
7684
|
+
out.operations = items.map(
|
|
7685
|
+
(item, index) => parseRecoveryOperation(item, `${pathPrefix}.operations[${index}]`)
|
|
7686
|
+
);
|
|
7687
|
+
}
|
|
7688
|
+
return out;
|
|
7689
|
+
}
|
|
7690
|
+
function parseContractScopeSection(value) {
|
|
7691
|
+
const record = requireObject(value, "contract.scope");
|
|
7692
|
+
rejectUnknownKeys(record, CONTRACT_SCOPE_KEYS, "contract.scope");
|
|
7693
|
+
const out = {};
|
|
7694
|
+
if (record.runId !== void 0) {
|
|
7695
|
+
out.runId = requireNonEmptyString(record.runId, "contract.scope.runId");
|
|
7696
|
+
}
|
|
7697
|
+
if (record.subAgentId !== void 0) {
|
|
7698
|
+
out.subAgentId = requireNonEmptyString(record.subAgentId, "contract.scope.subAgentId");
|
|
7699
|
+
}
|
|
7700
|
+
if (record.groupId !== void 0) {
|
|
7701
|
+
out.groupId = requireNonEmptyString(record.groupId, "contract.scope.groupId");
|
|
7702
|
+
}
|
|
7703
|
+
if (record.workflowStep !== void 0) {
|
|
7704
|
+
out.workflowStep = requireNonEmptyString(
|
|
7705
|
+
record.workflowStep,
|
|
7706
|
+
"contract.scope.workflowStep"
|
|
7707
|
+
);
|
|
7708
|
+
}
|
|
7709
|
+
if (record.rootEventId !== void 0) {
|
|
7710
|
+
out.rootEventId = requireNonEmptyString(record.rootEventId, "contract.scope.rootEventId");
|
|
7711
|
+
}
|
|
7712
|
+
return out;
|
|
7713
|
+
}
|
|
7714
|
+
function parseContractBodySection(value, pathPrefix) {
|
|
7715
|
+
const record = requireObject(value, pathPrefix);
|
|
7716
|
+
rejectUnknownKeys(record, CONTRACT_BODY_KEYS, pathPrefix);
|
|
7717
|
+
const out = {};
|
|
7718
|
+
if (record.run !== void 0) out.run = parseContractRunSection(record.run, `${pathPrefix}.run`);
|
|
7719
|
+
if (record.tools !== void 0) {
|
|
7720
|
+
out.tools = parseContractToolsSection(record.tools, `${pathPrefix}.tools`);
|
|
7721
|
+
}
|
|
7722
|
+
if (record.llm !== void 0) out.llm = parseContractLlmSection(record.llm, `${pathPrefix}.llm`);
|
|
7723
|
+
if (record.observations !== void 0) {
|
|
7724
|
+
out.observations = parseContractObservationsSection(
|
|
7725
|
+
record.observations,
|
|
7726
|
+
`${pathPrefix}.observations`
|
|
7727
|
+
);
|
|
7728
|
+
}
|
|
7729
|
+
if (record.controls !== void 0) {
|
|
7730
|
+
out.controls = parseContractControlsSection(record.controls, `${pathPrefix}.controls`);
|
|
7731
|
+
}
|
|
7732
|
+
if (record.retry !== void 0) {
|
|
7733
|
+
out.retry = parseContractRetrySection(record.retry, `${pathPrefix}.retry`);
|
|
7734
|
+
}
|
|
7735
|
+
return out;
|
|
7736
|
+
}
|
|
7737
|
+
function parseContractAlternativesSection(value) {
|
|
7738
|
+
const record = requireObject(value, "contract.alternatives");
|
|
7739
|
+
rejectUnknownKeys(record, CONTRACT_ALT_KEYS, "contract.alternatives");
|
|
7740
|
+
if (record.anyOf === void 0) {
|
|
7741
|
+
throw new CheckConfigError(
|
|
7742
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7743
|
+
"contract.alternatives.anyOf is required."
|
|
7744
|
+
);
|
|
7745
|
+
}
|
|
7746
|
+
const items = requireBoundedArray(
|
|
7747
|
+
record.anyOf,
|
|
7748
|
+
"contract.alternatives.anyOf",
|
|
7749
|
+
CONTRACT_MAX_ANY_OF
|
|
7750
|
+
);
|
|
7751
|
+
const anyOf = items.map((item, index) => {
|
|
7752
|
+
const pathPrefix = `contract.alternatives.anyOf[${index}]`;
|
|
7753
|
+
const branch = requireObject(item, pathPrefix);
|
|
7754
|
+
rejectUnknownKeys(branch, CONTRACT_ALT_BRANCH_KEYS, pathPrefix);
|
|
7755
|
+
const id = requireNonEmptyString(branch.id, `${pathPrefix}.id`);
|
|
7756
|
+
if (branch.contract === void 0) {
|
|
7757
|
+
throw new CheckConfigError(
|
|
7758
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7759
|
+
`${pathPrefix}.contract is required.`
|
|
7760
|
+
);
|
|
7761
|
+
}
|
|
7762
|
+
const out = {
|
|
7763
|
+
id,
|
|
7764
|
+
contract: parseContractBodySection(branch.contract, `${pathPrefix}.contract`)
|
|
7765
|
+
};
|
|
7766
|
+
if (branch.description !== void 0) {
|
|
7767
|
+
out.description = requireNonEmptyString(branch.description, `${pathPrefix}.description`);
|
|
7768
|
+
}
|
|
7769
|
+
return out;
|
|
7770
|
+
});
|
|
7771
|
+
return { anyOf };
|
|
7772
|
+
}
|
|
7773
|
+
function parseContractSection(value) {
|
|
7774
|
+
const record = requireObject(value, "contract");
|
|
7775
|
+
rejectUnknownKeys(record, CONTRACT_KEYS, "contract");
|
|
7776
|
+
const bodyOnly = {};
|
|
7777
|
+
for (const key of Object.keys(record)) {
|
|
7778
|
+
if (CONTRACT_BODY_KEYS.has(key)) bodyOnly[key] = record[key];
|
|
7779
|
+
}
|
|
7780
|
+
const out = { ...parseContractBodySection(bodyOnly, "contract") };
|
|
7781
|
+
if (record.scope !== void 0) out.scope = parseContractScopeSection(record.scope);
|
|
7782
|
+
if (record.alternatives !== void 0) {
|
|
7783
|
+
out.alternatives = parseContractAlternativesSection(record.alternatives);
|
|
7784
|
+
}
|
|
7785
|
+
return out;
|
|
7786
|
+
}
|
|
7075
7787
|
function parseCheckConfig(value) {
|
|
7076
7788
|
if (value === void 0 || value === null) return {};
|
|
7077
7789
|
if (typeof value !== "object" || Array.isArray(value)) {
|
|
7078
7790
|
throw new CheckConfigError("AI_CHECK_CONFIG_INVALID_VALUE", "Config must export an object.");
|
|
7079
7791
|
}
|
|
7080
7792
|
const root = value;
|
|
7081
|
-
if ("contract" in root) {
|
|
7082
|
-
throw new CheckConfigError(
|
|
7083
|
-
"AI_CHECK_CONFIG_UNKNOWN_KEY",
|
|
7084
|
-
'Top-level "contract" is not supported by `agent-inspect check --config`. Use the TraceContract TypeScript API (`defineTraceContract` / `evaluateTraceContract` from `agent-inspect/checks`), or express tool/run/llm rules under `checks`.'
|
|
7085
|
-
);
|
|
7086
|
-
}
|
|
7087
7793
|
const rootKeys = Object.keys(root);
|
|
7088
7794
|
for (const key of rootKeys) {
|
|
7089
|
-
if (key
|
|
7090
|
-
const suggestion = closestKey(key, [
|
|
7795
|
+
if (ROOT_CONFIG_KEYS.has(key)) continue;
|
|
7796
|
+
const suggestion = closestKey(key, [...ROOT_CONFIG_KEYS]);
|
|
7091
7797
|
const hint = suggestion ? ` Did you mean "${suggestion}"?` : "";
|
|
7092
7798
|
throw new CheckConfigError(
|
|
7093
7799
|
"AI_CHECK_CONFIG_UNKNOWN_KEY",
|
|
7094
|
-
`Unknown top-level check config key "${key}". Allowed: checks.${hint}`
|
|
7800
|
+
`Unknown top-level check config key "${key}". Allowed: checks, contract.${hint}`
|
|
7095
7801
|
);
|
|
7096
7802
|
}
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7803
|
+
const out = {};
|
|
7804
|
+
if ("checks" in root) {
|
|
7805
|
+
const checksRecord = requireObject(root.checks, "checks");
|
|
7806
|
+
rejectUnknownKeys(checksRecord, CHECKS_KEYS, "checks");
|
|
7807
|
+
const checks2 = {};
|
|
7808
|
+
if (checksRecord.select !== void 0) {
|
|
7809
|
+
checks2.select = requireStringArray(checksRecord.select, "checks.select");
|
|
7810
|
+
}
|
|
7811
|
+
if (checksRecord.run !== void 0) checks2.run = parseRunSection(checksRecord.run);
|
|
7812
|
+
if (checksRecord.tool !== void 0) checks2.tool = parseToolSection(checksRecord.tool);
|
|
7813
|
+
if (checksRecord.llm !== void 0) checks2.llm = parseLlmSection(checksRecord.llm);
|
|
7814
|
+
if (checksRecord.structure !== void 0) {
|
|
7815
|
+
checks2.structure = parseStructureSection(checksRecord.structure);
|
|
7816
|
+
}
|
|
7817
|
+
if (checksRecord.safety !== void 0) checks2.safety = parseSafetySection(checksRecord.safety);
|
|
7818
|
+
out.checks = checks2;
|
|
7103
7819
|
}
|
|
7104
|
-
if (
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
if (
|
|
7108
|
-
|
|
7820
|
+
if ("contract" in root) {
|
|
7821
|
+
out.contract = parseContractSection(root.contract);
|
|
7822
|
+
}
|
|
7823
|
+
if (out.contract !== void 0 && contractConfigHasEffect(out.contract) && checkConfigHasEffect({ checks: out.checks })) {
|
|
7824
|
+
throw new CheckConfigError(
|
|
7825
|
+
"AI_CHECK_CONFIG_INVALID_VALUE",
|
|
7826
|
+
'Config cannot combine top-level "checks" and "contract". Use one vocabulary per config file.'
|
|
7827
|
+
);
|
|
7109
7828
|
}
|
|
7110
|
-
|
|
7111
|
-
return { checks: checks2 };
|
|
7829
|
+
return out;
|
|
7112
7830
|
}
|
|
7113
7831
|
async function loadConfig(configPath) {
|
|
7114
7832
|
if (configPath === void 0) return {};
|
|
@@ -7436,6 +8154,7 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7436
8154
|
let evidenceRead;
|
|
7437
8155
|
let evidenceRunIds = [];
|
|
7438
8156
|
let evidenceSourceContents;
|
|
8157
|
+
let evidenceContract;
|
|
7439
8158
|
const sessionId = options.session?.trim();
|
|
7440
8159
|
const groupId = options.group?.trim();
|
|
7441
8160
|
const useSessionScope = Boolean(sessionId || groupId);
|
|
@@ -7444,7 +8163,7 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7444
8163
|
if (options.config !== void 0 && !checkConfigHasEffect(config)) {
|
|
7445
8164
|
result = errorResult(
|
|
7446
8165
|
"AI_CHECK_CONFIG_NO_EFFECTIVE_RULES",
|
|
7447
|
-
"Explicit --config has no effective check rules. Configure checks.select, checks.run, checks.tool, checks.llm, checks.structure,
|
|
8166
|
+
"Explicit --config has no effective check rules. Configure checks.select, checks.run, checks.tool, checks.llm, checks.structure, checks.safety, or contract."
|
|
7448
8167
|
);
|
|
7449
8168
|
if (options.json) printJson2(result);
|
|
7450
8169
|
else printHuman2(result, options);
|
|
@@ -7452,7 +8171,11 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7452
8171
|
return;
|
|
7453
8172
|
}
|
|
7454
8173
|
let effectiveOptions = options;
|
|
7455
|
-
const
|
|
8174
|
+
const useContract = config.contract !== void 0 && contractConfigHasEffect(config.contract);
|
|
8175
|
+
if (useContract) {
|
|
8176
|
+
evidenceContract = defineTraceContract(config.contract);
|
|
8177
|
+
}
|
|
8178
|
+
const resolved = useContract ? void 0 : resolvePreset(options.preset, {
|
|
7456
8179
|
hasToolRules: hasToolRulesConfigured(config, options)
|
|
7457
8180
|
});
|
|
7458
8181
|
if (resolved !== void 0) {
|
|
@@ -7460,7 +8183,7 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7460
8183
|
config = applied.config;
|
|
7461
8184
|
effectiveOptions = applied.options;
|
|
7462
8185
|
}
|
|
7463
|
-
const built = buildRules(config, effectiveOptions, resolved?.select ?? []);
|
|
8186
|
+
const built = useContract ? { rules: [], select: [], diagnostics: [] } : buildRules(config, effectiveOptions, resolved?.select ?? []);
|
|
7464
8187
|
if (built.diagnostics.some((item) => item.severity === "error")) {
|
|
7465
8188
|
result = errorResult("AI_CHECK_INVALID_CONFIG", "Invalid check configuration.");
|
|
7466
8189
|
result.diagnostics = [...built.diagnostics];
|
|
@@ -7482,6 +8205,7 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7482
8205
|
});
|
|
7483
8206
|
const perRun = [];
|
|
7484
8207
|
const sourceContents = /* @__PURE__ */ new Map();
|
|
8208
|
+
const definedContract = evidenceContract;
|
|
7485
8209
|
for (const meta of scoped.metas) {
|
|
7486
8210
|
const read = await openTrace(
|
|
7487
8211
|
{ type: "file", path: meta.filePath },
|
|
@@ -7498,23 +8222,20 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7498
8222
|
`
|
|
7499
8223
|
);
|
|
7500
8224
|
}
|
|
8225
|
+
const base = definedContract ? evaluateTraceContract({ read }, definedContract, { runId: meta.runId }) : runTraceChecks(
|
|
8226
|
+
{ read },
|
|
8227
|
+
{
|
|
8228
|
+
rules: built.rules,
|
|
8229
|
+
select: built.select,
|
|
8230
|
+
runId: meta.runId
|
|
8231
|
+
}
|
|
8232
|
+
);
|
|
7501
8233
|
perRun.push(
|
|
7502
|
-
mergeSafetyExtensions(
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
select: built.select,
|
|
7508
|
-
runId: meta.runId
|
|
7509
|
-
}
|
|
7510
|
-
),
|
|
7511
|
-
read,
|
|
7512
|
-
{
|
|
7513
|
-
...options.guardrails ? { guardrails: options.guardrails } : {},
|
|
7514
|
-
...options.circuit ? { circuits: options.circuit } : {},
|
|
7515
|
-
runId: meta.runId
|
|
7516
|
-
}
|
|
7517
|
-
)
|
|
8234
|
+
mergeSafetyExtensions(base, read, {
|
|
8235
|
+
...options.guardrails ? { guardrails: options.guardrails } : {},
|
|
8236
|
+
...options.circuit ? { circuits: options.circuit } : {},
|
|
8237
|
+
runId: meta.runId
|
|
8238
|
+
})
|
|
7518
8239
|
);
|
|
7519
8240
|
}
|
|
7520
8241
|
evidenceRunIds = scoped.runIds;
|
|
@@ -7553,22 +8274,25 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7553
8274
|
])
|
|
7554
8275
|
);
|
|
7555
8276
|
}
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
),
|
|
7565
|
-
read,
|
|
8277
|
+
const base = useContract && evidenceContract !== void 0 ? evaluateTraceContract(
|
|
8278
|
+
{ read },
|
|
8279
|
+
evidenceContract,
|
|
8280
|
+
{
|
|
8281
|
+
...options.run !== void 0 ? { runId: options.run } : {}
|
|
8282
|
+
}
|
|
8283
|
+
) : runTraceChecks(
|
|
8284
|
+
{ read },
|
|
7566
8285
|
{
|
|
7567
|
-
|
|
7568
|
-
|
|
8286
|
+
rules: built.rules,
|
|
8287
|
+
select: built.select,
|
|
7569
8288
|
...options.run !== void 0 ? { runId: options.run } : {}
|
|
7570
8289
|
}
|
|
7571
8290
|
);
|
|
8291
|
+
result = mergeSafetyExtensions(base, read, {
|
|
8292
|
+
...options.guardrails ? { guardrails: options.guardrails } : {},
|
|
8293
|
+
...options.circuit ? { circuits: options.circuit } : {},
|
|
8294
|
+
...options.run !== void 0 ? { runId: options.run } : {}
|
|
8295
|
+
});
|
|
7572
8296
|
}
|
|
7573
8297
|
} catch (error) {
|
|
7574
8298
|
if (phase === "config") {
|
|
@@ -7612,7 +8336,15 @@ async function checkCommand(target, options = {}, stdin = process.stdin) {
|
|
|
7612
8336
|
checkResultsJson: checkResultToEvidenceJson(result, runIds),
|
|
7613
8337
|
summaryText: `Check status: ${result.status}`,
|
|
7614
8338
|
redactionProfile,
|
|
7615
|
-
format: evidenceFormat
|
|
8339
|
+
format: evidenceFormat,
|
|
8340
|
+
...evidenceContract !== void 0 ? {
|
|
8341
|
+
contractPackage: {
|
|
8342
|
+
engineVersion: "",
|
|
8343
|
+
source: "file",
|
|
8344
|
+
contract: evidenceContract,
|
|
8345
|
+
...options.config !== void 0 ? { path: options.config } : {}
|
|
8346
|
+
}
|
|
8347
|
+
} : {}
|
|
7616
8348
|
});
|
|
7617
8349
|
if (!options.json) {
|
|
7618
8350
|
console.log(`Evidence: ${written}`);
|
|
@@ -12173,7 +12905,7 @@ function isModuleNotFound4(e) {
|
|
|
12173
12905
|
}
|
|
12174
12906
|
async function loadIndexSqlite() {
|
|
12175
12907
|
try {
|
|
12176
|
-
return await import('./src-
|
|
12908
|
+
return await import('./src-ZUGAUXY6.mjs');
|
|
12177
12909
|
} catch (e) {
|
|
12178
12910
|
if (isModuleNotFound4(e)) {
|
|
12179
12911
|
console.error(
|
|
@@ -13123,7 +13855,7 @@ function createCliProgram() {
|
|
|
13123
13855
|
"add run.maxStepDuration (e.g. 30s, 5m)"
|
|
13124
13856
|
).option("--require-completed", "add run.requireCompleted").option("--detect-stalls", "add run.stall for running or incomplete events").option(
|
|
13125
13857
|
"--fail-on-observation <status>",
|
|
13126
|
-
"
|
|
13858
|
+
"outcome gate: require \u22651 OUTCOME and fail when status matches (passed,failed,unknown,skipped; comma-separated). Does not invent outcomes from tool/LLM/run success; use --preset trajectory for structural checks"
|
|
13127
13859
|
).option("--session <id>", "check all runs in a workflow session (requires --dir)").option("--group <id>", "check all runs sharing a groupId (requires --dir)").option(
|
|
13128
13860
|
"--correlate-group",
|
|
13129
13861
|
"when using --session, also match synthetic group: session keys"
|
|
@@ -13136,7 +13868,7 @@ function createCliProgram() {
|
|
|
13136
13868
|
"run optional circuit rules (repeatable): same-tool-repetition, max-retries, ...",
|
|
13137
13869
|
(value, previous = []) => [...previous, value]
|
|
13138
13870
|
).addOption(
|
|
13139
|
-
new Option("--preset <name>", "additive check preset").choices(["trajectory", "safety", "comprehensive", "behavioral-session"])
|
|
13871
|
+
new Option("--preset <name>", "additive check preset (trajectory=structure only; safety=share checks; not interchangeable)").choices(["trajectory", "safety", "comprehensive", "behavioral-session"])
|
|
13140
13872
|
).addOption(
|
|
13141
13873
|
new Option(
|
|
13142
13874
|
"--evidence-on <mode>",
|