test(mcp): record the advertised-schema summary per tool (#11192)

summary.json held every advertised pattern's site list and every tool's
schema digests in one file. Each new path-taking tool appended to the
shared path pattern's list, so concurrent tool PRs conflicted on it, and
updating it required a local build.

Each tool's digests and patterns now live in
scripts/verify/advertised-schemas/tools/<tool>.json. The check still prints
aggregated review lines such as "N tool schemas gained pattern /.../", and
on failure also prints the expected contents of each missing or stale file
so a PR can commit them from CI output without building. --update-summary
writes those files and deletes summaries of removed tools. The existing
summary was split into per-tool files from its recorded data.

Fixes #11189
This commit is contained in:
morluto authored and GitHub committed 2026-11-15 22:11:06 +08:00
1 parent 1995ab7fce
commit b4cc1c998b
262 files changed
+2424 -1350

No files matched your search

+12 -10
View File
@@ -333,16 +333,18 @@ run the check, because it needs a current build. `--package-root=DIR` lists
an installed package instead of the checkout's build; the release guide uses
it to [check the qualified archive](releasing.md#check-the-packed-catalog-with-client-engines).
The same run compares the listings with
`scripts/verify/advertised-schemas/summary.json`, which records each advertised
pattern with the tool schemas that carry it and a digest of every tool's
schema per input or output profile. A difference fails the check and prints
lines such as `119 tool schemas gained pattern /…/`, so a change that reaches
many tools at once is visible in review. Regenerate it with
`npm run verify:advertised-schemas -- --update-summary` and commit it with the
schema change. Absolute local paths advertise the host's pattern, so the
summary records the POSIX advertisement and Windows hosts skip the
comparison.
The same run compares the listings with the per-tool summaries in
`scripts/verify/advertised-schemas/tools/`: each file records one tool's
schema digest per input or output profile and the patterns its schemas
advertise. A difference fails the check and prints aggregated lines such as
`119 tool schemas gained pattern /…/`, so a change that reaches many tools at
once is visible in review, followed by the expected contents of every missing
or stale file. Commit those contents with the schema change, or regenerate
them with `npm run verify:advertised-schemas -- --update-summary`, which also
deletes the files of removed tools. A PR that adds a tool adds only its own
file, so PRs adding different tools do not conflict. Absolute local paths
advertise the host's pattern, so the summaries record the POSIX advertisement
and Windows hosts skip the comparison.
The same run builds a validator for every distinct advertised input and output
schema with the Rust `jsonschema` crate's defaults, which check the declared
@@ -0,0 +1,35 @@
export interface ToolSummary {
/** A 16-hex digest of each advertised schema, keyed `<kind> <profile>`. */
readonly schemas: Readonly<Record<string, string>>;
/** Patterns each schema kind advertises, sorted; empty kinds are omitted. */
readonly patterns: Readonly<
Partial<Record<"input" | "output", readonly string[]>>
>;
}
export type CatalogSummary = Readonly<Record<string, ToolSummary>>;
export interface AdvertisedCatalog {
readonly profile: { readonly input: string; readonly output: string };
readonly tools: readonly {
readonly name: string;
readonly inputSchema?: unknown;
readonly outputSchema?: unknown;
}[];
}
export declare const summarizeAdvertisedCatalogs: (
catalogs: readonly AdvertisedCatalog[],
advertisedSchemaPatterns: (
schema: unknown,
) => readonly { readonly pattern: string }[],
) => CatalogSummary;
export declare const toolSummaryFile: (name: string) => string;
export declare const serializeToolSummary: (summary: ToolSummary) => string;
export declare const describeSummaryChanges: (
recorded: CatalogSummary,
current: CatalogSummary,
) => string[];
+81 -63
View File
@@ -1,11 +1,13 @@
import { createHash } from "node:crypto";
// A reviewable summary of what the packaged server advertises. A change that
// touches many tools' schemas at once, such as a pattern added to a shared
// path schema (#10830), shows up in review as one line per pattern instead of
// being buried in generated contracts.
// A reviewable summary of what the packaged server advertises, recorded as one
// file per tool. A change that touches many tools' schemas at once, such as a
// pattern added to a shared path schema (#10830), still shows up in review as
// one aggregated line per pattern, while a PR that adds a tool adds only its
// own file and does not conflict with other tool PRs (#11189).
const SHOWN_NAMES = 8;
const KINDS = ["input", "output"];
const sorted = (record) =>
Object.fromEntries(
@@ -15,71 +17,88 @@ const sorted = (record) =>
);
/**
* Summarize listings from every profile: each advertised pattern with the
* tool schemas that advertise it, and a digest of each tool's schema per
* input or output profile.
* Summarize listings from every profile, per tool: a digest of each schema
* per input or output profile, and the patterns each schema kind advertises.
*/
export const summarizeAdvertisedCatalogs = (
catalogs,
advertisedSchemaPatterns,
) => {
const patterns = new Map();
const tools = new Map();
const schemas = catalogs.flatMap(({ profile, tools: listed }) =>
listed.flatMap((tool) =>
[
["input", profile.input],
["output", profile.output],
].flatMap(([kind, selected]) => {
const schema = tool[`${kind}Schema`];
return schema === undefined
? []
: [{ name: tool.name, kind, group: `${kind} ${selected}`, schema }];
}),
),
);
for (const { name, kind, group, schema } of schemas) {
for (const { pattern } of advertisedSchemaPatterns(schema)) {
if (!patterns.has(pattern)) patterns.set(pattern, new Set());
patterns.get(pattern).add(`${name} ${kind}`);
}
if (!tools.has(name)) tools.set(name, {});
tools.get(name)[group] = createHash("sha256")
.update(JSON.stringify(schema))
.digest("hex")
.slice(0, 16);
}
return {
patterns: sorted(
Object.fromEntries(
[...patterns].map(([pattern, sites]) => [pattern, [...sites].sort()]),
),
),
tools: sorted(
Object.fromEntries(
[...tools].map(([name, digests]) => [name, sorted(digests)]),
),
),
const entry = (name) => {
if (!tools.has(name))
tools.set(name, {
schemas: {},
patterns: Object.fromEntries(KINDS.map((kind) => [kind, new Set()])),
});
return tools.get(name);
};
for (const { profile, tools: listed } of catalogs)
for (const tool of listed)
for (const kind of KINDS) {
const schema = tool[`${kind}Schema`];
if (schema === undefined) continue;
const record = entry(tool.name);
record.schemas[`${kind} ${profile[kind]}`] = createHash("sha256")
.update(JSON.stringify(schema))
.digest("hex")
.slice(0, 16);
for (const { pattern } of advertisedSchemaPatterns(schema))
record.patterns[kind].add(pattern);
}
return Object.fromEntries(
[...tools]
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
.map(([name, { schemas, patterns }]) => [
name,
{
schemas: sorted(schemas),
patterns: Object.fromEntries(
KINDS.flatMap((kind) =>
patterns[kind].size === 0
? []
: [[kind, [...patterns[kind]].sort()]],
),
),
},
]),
);
};
/** The committed file name for one tool's summary. */
export const toolSummaryFile = (name) => `${name}.json`;
/** One tool's summary as committed: sorted, two-space JSON with a newline. */
export const serializeToolSummary = (summary) =>
`${JSON.stringify(summary, null, 2)}\n`;
const names = (values) =>
values.length > SHOWN_NAMES
? `${values.slice(0, SHOWN_NAMES).join(", ")} and ${String(values.length - SHOWN_NAMES)} more`
: values.join(", ");
/** Review lines for every difference between two summaries. */
/** Each `<tool> <kind>` site that advertises each pattern, across tools. */
const patternSites = (tools) => {
const sites = new Map();
for (const [name, { patterns }] of Object.entries(tools))
for (const [kind, listed] of Object.entries(patterns ?? {}))
for (const pattern of listed) {
if (!sites.has(pattern)) sites.set(pattern, new Set());
sites.get(pattern).add(`${name} ${kind}`);
}
return sites;
};
/** Review lines for every difference between two per-tool summaries. */
export const describeSummaryChanges = (recorded, current) => {
const lines = [];
const recordedPatterns = recorded?.patterns ?? {};
for (const pattern of new Set([
...Object.keys(recordedPatterns),
...Object.keys(current.patterns),
])) {
const before = new Set(recordedPatterns[pattern] ?? []);
const after = new Set(current.patterns[pattern] ?? []);
const gained = [...after].filter((site) => !before.has(site));
const lost = [...before].filter((site) => !after.has(site));
const before = patternSites(recorded);
const after = patternSites(current);
for (const pattern of new Set([...before.keys(), ...after.keys()])) {
const was = before.get(pattern) ?? new Set();
const is = after.get(pattern) ?? new Set();
const gained = [...is].filter((site) => !was.has(site)).sort();
const lost = [...was].filter((site) => !is.has(site)).sort();
if (gained.length > 0)
lines.push(
`${String(gained.length)} tool schemas gained pattern /${pattern}/: ${names(gained)}`,
@@ -89,23 +108,22 @@ export const describeSummaryChanges = (recorded, current) => {
`${String(lost.length)} tool schemas lost pattern /${pattern}/: ${names(lost)}`,
);
}
const recordedTools = recorded?.tools ?? {};
const changed = new Map();
for (const tool of new Set([
...Object.keys(recordedTools),
...Object.keys(current.tools),
]))
for (const group of new Set([
...Object.keys(recordedTools[tool] ?? {}),
...Object.keys(current.tools[tool] ?? {}),
]))
if (recordedTools[tool]?.[group] !== current.tools[tool]?.[group]) {
...Object.keys(recorded),
...Object.keys(current),
])) {
const was = recorded[tool]?.schemas ?? {};
const is = current[tool]?.schemas ?? {};
for (const group of new Set([...Object.keys(was), ...Object.keys(is)]))
if (was[group] !== is[group]) {
if (!changed.has(group)) changed.set(group, []);
changed.get(group).push(tool);
}
}
for (const [group, changedTools] of changed)
lines.push(
`${String(changedTools.length)} tools changed their ${group} schema: ${names(changedTools)}`,
`${String(changedTools.length)} tools changed their ${group} schema: ${names(changedTools.sort())}`,
);
return lines;
};
+58 -23
View File
@@ -1,4 +1,4 @@
import { readFile, writeFile } from "node:fs/promises";
import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
@@ -8,10 +8,11 @@ import {
} from "./lib/advertised-catalog.mjs";
import {
describeSummaryChanges,
serializeToolSummary,
summarizeAdvertisedCatalogs,
toolSummaryFile,
} from "./lib/advertised-catalog-summary.mjs";
import { formatGeneratedFile } from "./lib/format-generated-file.mjs";
import { ensureGeneratedFile } from "./lib/generated-file.mjs";
import {
VerifierFixture,
withVerifierFixture,
@@ -222,40 +223,74 @@ const results = await withVerifierFixture(fixture, async () => {
const problems = [];
// Absolute local paths advertise the host's pattern, so the recorded summary
// is the POSIX advertisement; Windows hosts cannot reproduce it.
const summaryPath = join(directory, "summary.json");
// is the POSIX advertisement; Windows hosts cannot reproduce it. Each tool's
// summary is its own file, so PRs that add different tools do not conflict.
const summaryDirectory = join(directory, "tools");
if (process.platform === "win32")
console.log("Advertised catalog summary: not compared on Windows hosts.");
else {
const summary = summarizeAdvertisedCatalogs(
const current = summarizeAdvertisedCatalogs(
catalogs,
advertisedSchemaPatterns,
);
let recorded;
try {
recorded = JSON.parse(await readFile(summaryPath, "utf8"));
} catch (error) {
if (error?.code !== "ENOENT") throw error;
const recordedFiles = await readdir(summaryDirectory).catch((error) => {
if (error?.code === "ENOENT") return [];
throw error;
});
const recorded = {};
const recordedText = new Map();
for (const file of recordedFiles.filter((name) => name.endsWith(".json"))) {
const text = await readFile(join(summaryDirectory, file), "utf8");
recordedText.set(file, text);
recorded[file.slice(0, -".json".length)] = JSON.parse(text);
}
const changes = describeSummaryChanges(recorded, summary);
const update = options.has("--update-summary");
const changes = describeSummaryChanges(recorded, current);
const expected = new Map(
await Promise.all(
Object.entries(current).map(async ([name, summary]) => {
const file = toolSummaryFile(name);
return [
file,
await formatGeneratedFile(
join(summaryDirectory, file),
serializeToolSummary(summary),
),
];
}),
),
);
const stale = [...expected].filter(
([file, text]) => recordedText.get(file)?.replaceAll("\r\n", "\n") !== text,
);
const removed = [...recordedText.keys()].filter(
(file) => !expected.has(file),
);
if (changes.length > 0)
console.log(
`Advertised catalog summary ${update ? "updated" : "differs"}:\n${changes.map((line) => ` ${line}`).join("\n")}`,
);
try {
await ensureGeneratedFile({
path: summaryPath,
source: await formatGeneratedFile(
summaryPath,
`${JSON.stringify(summary, null, 2)}\n`,
),
check: !update,
generateCommand: "npm run verify:advertised-schemas -- --update-summary",
});
} catch (error) {
if (update) {
await mkdir(summaryDirectory, { recursive: true });
for (const [file, text] of stale)
await writeFile(join(summaryDirectory, file), text, "utf8");
for (const file of removed) await rm(join(summaryDirectory, file));
} else if (stale.length > 0 || removed.length > 0) {
// Print what each file should hold, so a PR that adds or changes a tool
// can commit the summary from this output without a local build.
const relative = (file) =>
`scripts/verify/advertised-schemas/tools/${file}`;
const expectedText = stale
.map(([file, text]) => `--- ${relative(file)}\n${text}`)
.join("");
const removedText = removed
.map((file) => ` delete ${relative(file)}\n`)
.join("");
console.log(
`Expected advertised catalog summary files:\n${expectedText}${removedText}`,
);
problems.push(
`${error.message} Review the changes above; a PR that changes advertised schemas commits the summary with them.`,
`${String(stale.length + removed.length)} advertised catalog summary file(s) are missing or stale. Commit the contents printed above, or run \`npm run verify:advertised-schemas -- --update-summary\`; a PR that changes advertised schemas commits the summary with them.`,
);
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,15 @@
{
"schemas": {
"input compact": "492ec1ac2a1230c5",
"output compact": "9bd80958780175fe"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"^[0-9a-z][\\-.0-9_a-z]{0,62}$"
],
"output": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "f1b0a54d8c702be5",
"output compact": "9e24f29540c4da8a"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "c9d8a29b5ea9eaf2",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "02ac81c718b49410",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "990f691d36bfeeec",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "954672370cc76451",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "3d7959f5cdca863d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "70c17ea61092a8c3",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "d4ebd6a35bc062aa",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "cd55cbd9191fb397",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "32062bdb9024160d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "ea2ae40d88bad772",
"output compact": "9cda19dfa1310afa"
},
"patterns": {
"input": ["^[0-9a-f]{64}$", "^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "5b291bcc2323c4d0",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "a7cd5ce32e774439",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "5270421b8c21c650",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00\\x09-\\x0d \"']+$", "^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "b6594631753958b4",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "1966487f98e87f51",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "699d21a37250979b",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "b16f62e36c31a0cc",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "7ba00cbe6d75c7d9",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "2e039048620b8a11",
"output compact": "86cabbcac4bdb308"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "1650d4dd6dfc3b5e",
"output compact": "67aadfbdedfd0c6e"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,14 @@
{
"schemas": {
"input compact": "3b3f0b6ed9a02890",
"output compact": "b384409a7d0f96ed"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
],
"output": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,11 @@
{
"schemas": {
"input compact": "d5defc56611ce19d",
"output compact": "9ca208e0b4a3ca6f"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,11 @@
{
"schemas": {
"input compact": "d5defc56611ce19d",
"output compact": "377e3b6f9b0db8e3"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,11 @@
{
"schemas": {
"input compact": "d5defc56611ce19d",
"output compact": "9ca208e0b4a3ca6f"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "5270421b8c21c650",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00\\x09-\\x0d \"']+$", "^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "f1b0a54d8c702be5",
"output compact": "9e24f29540c4da8a"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "6e86c4697a074d94",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "633f07e1c25fb0e9",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "65c9f2cad6fee49f",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$", "^ev_[0-9a-f]{64}$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "633f07e1c25fb0e9",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "169fa0bb1123cfed",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "633f07e1c25fb0e9",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "09de9679075c918d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "53e35e56039bbec8",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "87bd558a19485f40",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "762370ff0063b96c",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "9a27667fef6bb852",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "eff327dda5c10d9a",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[0-9a-f]{64}$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "24360903f54081d4",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "4df1857d0f25b9b1",
"output compact": "ffd2432283f65468"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "32062bdb9024160d",
"output compact": "ffd2432283f65468"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "4df1857d0f25b9b1",
"output compact": "ffd2432283f65468"
},
"patterns": {}
}
@@ -0,0 +1,11 @@
{
"schemas": {
"input compact": "b91fd6378ec89ada",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,12 @@
{
"schemas": {
"input compact": "a1b45d95750ca8ef",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": [
"^(?:[a-z]{2,3}(?:-(?:r?[A-Z]{2}|[0-9]{3}))?|b\\+[a-z]{2,3}(?:\\+[0-9A-Za-z]{2,8})*)$",
"^[^\\x00]*$"
]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "0395893cc47e3a89",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "57f1e31eab5d6150",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "f9475f6ca1476ae0",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "365c0a3f3e7ee733",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "ce0ed2a63eb8849e",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x0a]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "fdb69f3d5123e80e",
"output compact": "3e22807c622e44b2"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "4425590849a07d7f",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "4c824f77c8039956",
"output compact": "6eb93bf85f43f04d"
},
"patterns": {
"output": ["^[A-Za-z][\\x2d-\\x3aA-Z_a-z]{0,199}$", "^ev_[0-9a-f]{64}$"]
}
}
@@ -0,0 +1,13 @@
{
"schemas": {
"input compact": "abd06cd2d1a16823",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": [
"^0x[0-9A-Fa-f]{1,16}$",
"^[0-9A-Za-z][+\\-.0-9A-Z_a-z]*$",
"^[^\\x00]*$"
]
}
}
@@ -0,0 +1,11 @@
{
"schemas": {
"input compact": "f2e2ecfc4671d550",
"output compact": "c9f69f0d4856f6f4"
},
"patterns": {
"output": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "61eb02cacceb0fc4",
"output compact": "31f5a06d7bc1ebba"
},
"patterns": {
"input": ["^[0-9a-z]+(?:-[0-9a-z]+)*$", "^[^\\x00]*$", "^ev_[0-9a-f]{64}$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "fc434da7d0233b71",
"output compact": "66a3eb6c5dc33577"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "b18c35aaccafe15a",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "5ecb2020ae1f8f42",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$", "^occ_[0-9a-f]{64}$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "6ca4f62a458ff3d7",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "a8a946736b36ddb8",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "ba6030423e62d130",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,11 @@
{
"schemas": {
"input compact": "31cc6bc09d1bb29d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,11 @@
{
"schemas": {
"input compact": "3a493db9e13845e2",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,14 @@
{
"schemas": {
"input compact": "d5defc56611ce19d",
"output compact": "c29682a2312eb267"
},
"patterns": {
"input": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
],
"output": [
"^([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[1-8][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "5d40cd3080063c1d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "3c840e5bbd9e9894",
"output compact": "9cda19dfa1310afa"
},
"patterns": {
"input": ["^[0-9a-f]{64}$", "^ev_[0-9a-f]{64}$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "4c9f333a998b4999",
"output compact": "f496722f55251654"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "e2e179a75a6a8189",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "32062bdb9024160d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "c9d8a29b5ea9eaf2",
"output compact": "ffd2432283f65468"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "eab443f9a403d9f4",
"output compact": "2fefdacc1c7b9233"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "18d266261424a97c",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "18d266261424a97c",
"output compact": "6c6c35e1ceaeb7ae"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "32ffbbfc8df34d78",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "f1b0a54d8c702be5",
"output compact": "9e24f29540c4da8a"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "32062bdb9024160d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "0eefd4f4245ea66b",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00\\x09-\\x0d \"']+$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "0eefd4f4245ea66b",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00\\x09-\\x0d \"']+$"]
}
}
@@ -0,0 +1,12 @@
{
"schemas": {
"input compact": "2d6b5bb69d217de1",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": [
"^[A-Za-z][0-9A-Z_a-z]*(\\.[A-Za-z][0-9A-Z_a-z]*)*$",
"^[^\\x00\\x09-\\x0d \"']+$"
]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "0eefd4f4245ea66b",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00\\x09-\\x0d \"']+$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "9dd6c6df7b9ea95f",
"output compact": "9cda19dfa1310afa"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "7020930a4af1f37c",
"output compact": "b3a429110120aff1"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "99dbe34c28cd04dd",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "fb8be61f22dca985",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,12 @@
{
"schemas": {
"input compact": "e5d2cfec1580148e",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": [
"^[^\\x00]*$",
"^\\((?:\\[{0,255}(?:[B-DFIJSZ]|L[^\\(\\);]+;))*\\)(?:V|\\[{0,255}(?:[B-DFIJSZ]|L[^\\(\\);]+;))$"
]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "f4d383779c829cc1",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "6f391991d856198a",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "79519ee02b61df07",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "dec153ba3fc1960c",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "32062bdb9024160d",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,9 @@
{
"schemas": {
"input compact": "c55c03a1cfb12bf4",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {
"input": ["^[^\\x00]*$"]
}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "aabcc05db1232b21",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
@@ -0,0 +1,7 @@
{
"schemas": {
"input compact": "72d0fff774075e7c",
"output compact": "9087cdd7aaaf031b"
},
"patterns": {}
}
Loaded 100 of 262 files, more files were not shown because too many files have changed in this diff. Show more