mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
perf(mcp): record catalog identities for all schema profiles (#5415)
Share compiled schema conversion while recording all four built-in catalog profiles. Preserve canonical hashes, output validation and custom-budget fallback. Refs #723. Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
This commit is contained in:
1 parent
1417bf943b
commit
c23e161629
10 files changed
+1395
-55
No files matched your search
@@ -0,0 +1,74 @@
|
|||||||
|
"""Summarize recorded Codex discovery tasks; tiktoken==0.12.0 is a proxy only."""
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import tiktoken
|
||||||
|
|
||||||
|
|
||||||
|
def compact(value):
|
||||||
|
return json.dumps(value, ensure_ascii=False, separators=(",", ":"), allow_nan=False)
|
||||||
|
|
||||||
|
|
||||||
|
def inspect(path, encoding):
|
||||||
|
report = json.loads((path / "report.json").read_text())
|
||||||
|
catalog = json.loads((path / "catalog.json").read_text())
|
||||||
|
transcript = json.loads((path / "transcript.json").read_text())
|
||||||
|
log = path.with_suffix(".log")
|
||||||
|
scope = next(json.loads(line) for line in reversed(log.read_text().splitlines())
|
||||||
|
if line.startswith('{"resource_scope":'))
|
||||||
|
observed = scope.get("payload_resource_observation") or {}
|
||||||
|
completed = (report["status"] == "passed" and not report["cleanup_failures"]
|
||||||
|
and report["appserver_exit_code"] == 0 and scope["abort"] is None
|
||||||
|
and scope.get("payload_resource_observation_verified") is True
|
||||||
|
and observed.get("payload_cleanup_verified") is True
|
||||||
|
and observed.get("payload_exit_code") == 0)
|
||||||
|
tools = list(catalog["data"][0]["tools"].values())
|
||||||
|
messages = [event["message"] for event in transcript]
|
||||||
|
ids = {m["id"] for m in messages if m.get("method") == "mcpServer/tool/call"}
|
||||||
|
replies = [m["result"] for m in messages if m.get("id") in ids and "result" in m]
|
||||||
|
arguments = [m["params"] for m in messages if m.get("method") == "mcpServer/tool/call"]
|
||||||
|
count = lambda text: len(encoding.encode(text, disallowed_special=()))
|
||||||
|
input_catalog = count(compact([{k: t[k] for k in ["name", "description", "inputSchema"]} for t in tools]))
|
||||||
|
argument_tokens = sum(count(compact(a)) for a in arguments)
|
||||||
|
text_tokens = sum(count(c["text"]) for r in replies for c in r["content"] if c["type"] == "text")
|
||||||
|
return {
|
||||||
|
"recording": path.name, "completed_with_verified_cleanup": completed,
|
||||||
|
"input_profile": report["input_profile"], "output_profile": report["output_profile"],
|
||||||
|
"catalog": report["catalog"], "calls": report["calls"],
|
||||||
|
# Codex returns tools as a map; JSON member order varies by process.
|
||||||
|
"catalog_semantic_sha256": hashlib.sha256(json.dumps(
|
||||||
|
catalog, ensure_ascii=False, sort_keys=True, separators=(",", ":"),
|
||||||
|
allow_nan=False).encode()).hexdigest(),
|
||||||
|
"digests": [r["structuredContent"]["result"]["server_identity"]["catalog"]["digests"] for r in replies],
|
||||||
|
"token_proxy": {"input_facing_catalog": input_catalog, "arguments": argument_tokens,
|
||||||
|
"text_replies": text_tokens, "combined": input_catalog + argument_tokens + text_tokens,
|
||||||
|
"complete_discovered_catalog": count(compact(catalog))},
|
||||||
|
"wall_seconds": scope["elapsed_seconds"],
|
||||||
|
"cpu_seconds": observed["cpu_stat"]["usage_usec"] / 1e6,
|
||||||
|
"kernel_family_peak_bytes_including_file_cache": observed.get("memory_peak_bytes"),
|
||||||
|
"observed_resource_events": observed.get("resource_events"),
|
||||||
|
"final_whole_scope_events": scope.get("resource_events_final"),
|
||||||
|
"sha256": {p.name: hashlib.sha256(p.read_bytes()).hexdigest()
|
||||||
|
for p in [path / "report.json", path / "catalog.json", path / "transcript.json", log]},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--output", type=Path, required=True)
|
||||||
|
parser.add_argument("cases", type=Path, nargs="+")
|
||||||
|
args = parser.parse_args()
|
||||||
|
encoding = tiktoken.get_encoding("cl100k_base")
|
||||||
|
records = [inspect(path, encoding) for path in args.cases]
|
||||||
|
result = {"tiktoken": tiktoken.__version__, "encoding": encoding.name,
|
||||||
|
"actual_model_usage": None,
|
||||||
|
"unmeasured": ["actual host model schema injection and rendering", "model input/output/cached tokens", "model reasoning and application investigation"],
|
||||||
|
"recordings": records}
|
||||||
|
args.output.write_text(json.dumps(result, indent=2) + "\n")
|
||||||
|
assert all(r["completed_with_verified_cleanup"] for r in records)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { pathToFileURL } from "node:url";
|
||||||
|
import { resolve } from "node:path";
|
||||||
|
const [root, input, output] = process.argv.slice(2);
|
||||||
|
const start = performance.now();
|
||||||
|
const { createCatalogIdentity } = await import(
|
||||||
|
pathToFileURL(resolve(root, "dist/catalogIdentity.js"))
|
||||||
|
);
|
||||||
|
const imported = performance.now();
|
||||||
|
const cpu = process.cpuUsage();
|
||||||
|
const identity = createCatalogIdentity(
|
||||||
|
input === "compact" ? { budgetBytes: 13 * 1024 } : undefined,
|
||||||
|
output,
|
||||||
|
);
|
||||||
|
const digests = identity.digests;
|
||||||
|
const end = performance.now();
|
||||||
|
console.log(
|
||||||
|
JSON.stringify({
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
import_ms: imported - start,
|
||||||
|
digest_ms: end - imported,
|
||||||
|
digest_cpu_us: process.cpuUsage(cpu),
|
||||||
|
digests,
|
||||||
|
}),
|
||||||
|
);
|
||||||
@@ -0,0 +1,808 @@
|
|||||||
|
{
|
||||||
|
"issue": 723,
|
||||||
|
"source_base": "d532b18123916a9e88f98c7880ba4f984e23d715",
|
||||||
|
"runtimes": {
|
||||||
|
"baseline-runtime-d532b1812": {
|
||||||
|
"source_revision": "d532b18123916a9e88f98c7880ba4f984e23d715",
|
||||||
|
"archive_sha256": "79832e2571112400892ec1aae429b030de38c8c672a8acfa6680a2568362fed3",
|
||||||
|
"manifest_sha256": "89cbc1688e4702a47b9a5cc66ac38d18de46b74eb550e44227f0ec2119c5e7af"
|
||||||
|
},
|
||||||
|
"candidate-runtime-1": {
|
||||||
|
"source_base": "d532b18123916a9e88f98c7880ba4f984e23d715",
|
||||||
|
"patch_sha256": "cfb0eee1ee7f3ceecff7cb77ac63e569dfcfc020e4252cb11869644628f4f743",
|
||||||
|
"archive_sha256": "7e4275b1db784545335a4eab373a3db11b1eb5cc6bac7611521a698b0cffce56",
|
||||||
|
"manifest_sha256": "356b3baa153650b330cea6bc7e28163565f3201b8d80aa2d6bb69f66faa8705a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node": "24.18.0",
|
||||||
|
"npm": "11.16.0",
|
||||||
|
"mcp_sdk": "2.3.1",
|
||||||
|
"client": "Codex app-server 0.163.0",
|
||||||
|
"negotiated_protocol": "2025-06-18",
|
||||||
|
"model_turns_started": 0,
|
||||||
|
"actual_model_usage": null,
|
||||||
|
"task": "Complete 209-tool discovery, then verify no target open, no cleanup pending, no bound provider, package version and tool count twice.",
|
||||||
|
"run_order": [
|
||||||
|
"baseline-d532-1",
|
||||||
|
"candidate-1-1 (reversed profiles)",
|
||||||
|
"baseline-d532-2 (reversed profiles)",
|
||||||
|
"candidate-1-2"
|
||||||
|
],
|
||||||
|
"resource_bounds": {
|
||||||
|
"cpu_affinity": [15],
|
||||||
|
"cpu_quota_percent": 100,
|
||||||
|
"hard_memory_gib": 4,
|
||||||
|
"early_stop_gib": 3,
|
||||||
|
"node_heap_gib": 2,
|
||||||
|
"swap": 0,
|
||||||
|
"task_ceiling": 192,
|
||||||
|
"accounting": "Kernel cgroup process-family peak including file cache, Codex, controller and server; CPU counters at payload exit with only observer alive. Final whole-scope counters unavailable.",
|
||||||
|
"oom_events": 0,
|
||||||
|
"verified_payload_cleanup_recordings": 16
|
||||||
|
},
|
||||||
|
"tiktoken": "0.12.0",
|
||||||
|
"encoding": "cl100k_base",
|
||||||
|
"token_proxy_limit": "Input-facing catalog + RPC params + text result serialization; no model turn/usage, schema injection, prompts or reasoning measured. Identity paths/timestamps cause small reply token differences.",
|
||||||
|
"scripts_sha256": {
|
||||||
|
"codex-host-probe.py": "d0da9b39e0343b5e84f05328f56df3e82b712fd3fb32ee375cf3735a448fb80e",
|
||||||
|
"digest-probe.mjs": "e2f8950014bb40806aef147196ca5d432c6400941d3901e1c0a0e78ce5266bcf",
|
||||||
|
"build-digest-probe.mjs": "46060b75c014ca39f9efe317a0445a0220ea7166a08dbdacf04706670e958e6d",
|
||||||
|
"run-cohort.py": "1cc5db864b4fe1b2d657ddfe72d468d9e72bddf5118b0bf10c9fce344ec45e9c"
|
||||||
|
},
|
||||||
|
"profile_digest_oracle": {
|
||||||
|
"full": {
|
||||||
|
"full": {
|
||||||
|
"tools_sha256": "c3e7950408c9005ae3ae0633966609bf1c0f72a36392bc0e0c0fdfe9ea584ae6",
|
||||||
|
"prompts_sha256": "7152916ab48bd2a9677a5ad9cdbde0a51dc53c113934952ad096e93f5f18aa7e",
|
||||||
|
"combined_sha256": "e0b2715af8312fb565f14d75296adc947b94252e53643f08d831ca8fc8aee941"
|
||||||
|
},
|
||||||
|
"off": {
|
||||||
|
"tools_sha256": "5ad649af53472a1d789b26997cb26a4e8d5d1f2a97c587ad1a6b16030ef5d764",
|
||||||
|
"prompts_sha256": "7152916ab48bd2a9677a5ad9cdbde0a51dc53c113934952ad096e93f5f18aa7e",
|
||||||
|
"combined_sha256": "cd84cff526daa360e30e299002e7d14427fde9c2b00f59f622fccf89ff2535c7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compact": {
|
||||||
|
"full": {
|
||||||
|
"tools_sha256": "774c1b7c2c2f57beea9bed62171f046da0f17f2b3bbd7900a90855ecdd26ba79",
|
||||||
|
"prompts_sha256": "7152916ab48bd2a9677a5ad9cdbde0a51dc53c113934952ad096e93f5f18aa7e",
|
||||||
|
"combined_sha256": "2cbc9ae351fe4f1204a4c2b5e2e92fff8a2ecd87bc14c7ef068d6691c17dff15"
|
||||||
|
},
|
||||||
|
"off": {
|
||||||
|
"tools_sha256": "efe7a17bad5617171162414df88529ff54807b870b5d510e2838ce18e2ba8bd8",
|
||||||
|
"prompts_sha256": "7152916ab48bd2a9677a5ad9cdbde0a51dc53c113934952ad096e93f5f18aa7e",
|
||||||
|
"combined_sha256": "07d379697201b70d45579d0811e137a0df088be88498fc9fae6806adba26c976"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recordings": [
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-full-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 3322571,
|
||||||
|
"catalog_semantic_sha256": "799cc997a9573b5c3dfce3ac22e1fb5eb1637e81b489392f37cc81767b334359",
|
||||||
|
"discovery_ms": 5074.2612921167165,
|
||||||
|
"first_status_ms": 1699.8079400509596,
|
||||||
|
"warm_status_ms": 981.8687399383634,
|
||||||
|
"wall_seconds": 8.919,
|
||||||
|
"cpu_seconds": 8.480822,
|
||||||
|
"kernel_family_peak_bytes": 802246656,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187005,
|
||||||
|
"arguments": 86,
|
||||||
|
"text_replies": 22702,
|
||||||
|
"combined": 209793,
|
||||||
|
"complete_discovered_catalog": 845872
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "f36f889ab241f704977241443ad55176de6607805f6c82013a287e968dbb428d",
|
||||||
|
"catalog.json": "ad5dcfb828d4524f97b494884deed42389ab3e29e2f7839a12b5e95bd1c50ff1",
|
||||||
|
"transcript.json": "7d019f379100f45ff1c3f55e66d79e233f7b736886be1823da11e4b843d5fdc1",
|
||||||
|
"baseline-d532-1-full-full.log": "3709d55fe5412f49ee880bfee4be818711c977b026ad3133a3f8abb91111f9a7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-full-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 3322571,
|
||||||
|
"catalog_semantic_sha256": "799cc997a9573b5c3dfce3ac22e1fb5eb1637e81b489392f37cc81767b334359",
|
||||||
|
"discovery_ms": 5847.158181015402,
|
||||||
|
"first_status_ms": 1123.013640055433,
|
||||||
|
"warm_status_ms": 911.4040599670261,
|
||||||
|
"wall_seconds": 8.905,
|
||||||
|
"cpu_seconds": 8.452489,
|
||||||
|
"kernel_family_peak_bytes": 803254272,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187004,
|
||||||
|
"arguments": 86,
|
||||||
|
"text_replies": 22702,
|
||||||
|
"combined": 209792,
|
||||||
|
"complete_discovered_catalog": 845872
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "b85792959c6838010ebd622d1cf213d2eb1cd9562da14fc49a2555bda03a0eee",
|
||||||
|
"catalog.json": "f588658a13bc1b559008508954f2ce7f34815b326686b4c167c0c27b521cad1b",
|
||||||
|
"transcript.json": "5326f37ffdeae98ad4679cf53f462a41fddd71eb9891040753e716489dcc1b68",
|
||||||
|
"baseline-d532-2-full-full.log": "147000d226f6cfb3450af51ade419b20c6b0b7d7409c22e876c98830762b39eb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-compact-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 2723927,
|
||||||
|
"catalog_semantic_sha256": "d18f02920b84d39b90dc488db89a8f403f6ec35139a39a3329375a18078af1ea",
|
||||||
|
"discovery_ms": 11450.75011299923,
|
||||||
|
"first_status_ms": 4571.937991073355,
|
||||||
|
"warm_status_ms": 1836.9912200141698,
|
||||||
|
"wall_seconds": 18.99,
|
||||||
|
"cpu_seconds": 16.522676,
|
||||||
|
"kernel_family_peak_bytes": 808927232,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 82,
|
||||||
|
"text_replies": 22714,
|
||||||
|
"combined": 66303,
|
||||||
|
"complete_discovered_catalog": 702182
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "b27141e7af05b3dd43930c0df30f4872709d8db72cc953478150084e99e032f4",
|
||||||
|
"catalog.json": "8ff7b639d3409b52761d483283c674e3670e42169ddfda0c1e2a87a207c4dcbd",
|
||||||
|
"transcript.json": "1f91daa9703495ca6519459124e9564f0c96f5542b61563bf10029a1f6337926",
|
||||||
|
"baseline-d532-1-compact-full.log": "fb187f2b9255e4fc1ecd2c15f9df3c7f1efc76aaba528589f5eed81e7e80e835"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-compact-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 2723927,
|
||||||
|
"catalog_semantic_sha256": "d18f02920b84d39b90dc488db89a8f403f6ec35139a39a3329375a18078af1ea",
|
||||||
|
"discovery_ms": 5926.411310909316,
|
||||||
|
"first_status_ms": 2899.308810941875,
|
||||||
|
"warm_status_ms": 1365.2960499748588,
|
||||||
|
"wall_seconds": 11.148,
|
||||||
|
"cpu_seconds": 10.613801,
|
||||||
|
"kernel_family_peak_bytes": 816377856,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 82,
|
||||||
|
"text_replies": 22714,
|
||||||
|
"combined": 66303,
|
||||||
|
"complete_discovered_catalog": 702182
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "df856c2a486c513923b3c67db30bc60ca28ba3b1d0e3418d28d9d6429eca9366",
|
||||||
|
"catalog.json": "407ff33fd8e57f2842b76ce190c2089930add6c9a4f618cc90320045f6a67ed2",
|
||||||
|
"transcript.json": "d11dfb4c28c5355e733943e3504d3b4e11f056f0f7625e835e5cdc916a451716",
|
||||||
|
"baseline-d532-2-compact-full.log": "0485a806e815ecb91862d37cb9200b7cb0877a3d8c69882e8299100d13769a57"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-full-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 832191,
|
||||||
|
"catalog_semantic_sha256": "e537c521b5dd0ac369dee706815579d9d7803497a8fc7f7d683fec267042b81c",
|
||||||
|
"discovery_ms": 11546.154452953488,
|
||||||
|
"first_status_ms": 4629.906311165541,
|
||||||
|
"warm_status_ms": 2057.3992100544274,
|
||||||
|
"wall_seconds": 19.588,
|
||||||
|
"cpu_seconds": 16.963204,
|
||||||
|
"kernel_family_peak_bytes": 709857280,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187005,
|
||||||
|
"arguments": 86,
|
||||||
|
"text_replies": 22710,
|
||||||
|
"combined": 209801,
|
||||||
|
"complete_discovered_catalog": 195042
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "4963559eafd97d6aa72e2265651d9f6d3d0cd3a04965677d6fdedfe0378e7c11",
|
||||||
|
"catalog.json": "aef1822a088446790e14373a6b9b1039cda640598d19620fdd776f6d7c49d890",
|
||||||
|
"transcript.json": "203f7f00eca7617cdaa8c7fd45fdde3d4502cd29cf36ee0c724181ad3178410b",
|
||||||
|
"baseline-d532-1-full-off.log": "84e5a67f6f1e97fb3c429d96d7b3de33e08eddc56b21b453fa2b3abf19dbd15b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-full-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 832191,
|
||||||
|
"catalog_semantic_sha256": "e537c521b5dd0ac369dee706815579d9d7803497a8fc7f7d683fec267042b81c",
|
||||||
|
"discovery_ms": 5198.2202511280775,
|
||||||
|
"first_status_ms": 2726.173529867083,
|
||||||
|
"warm_status_ms": 1434.7798710223287,
|
||||||
|
"wall_seconds": 10.325,
|
||||||
|
"cpu_seconds": 9.75455,
|
||||||
|
"kernel_family_peak_bytes": 703328256,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187005,
|
||||||
|
"arguments": 86,
|
||||||
|
"text_replies": 22710,
|
||||||
|
"combined": 209801,
|
||||||
|
"complete_discovered_catalog": 195042
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "e603556898f606d6804c73a227ef6d809f09f516316255b316e5afb473170ff9",
|
||||||
|
"catalog.json": "8200cccc7a0d7bdcf288cab0225269acadbd532aed69da7d7e8a3b4cf34b9c16",
|
||||||
|
"transcript.json": "4d2a862a24282cac2581a36ca46fd99474835cba247203556c04015ea02096fe",
|
||||||
|
"baseline-d532-2-full-off.log": "90b720806f3f5756408501a1f9d5dd724108647706e38aca10cbc0a35e56a37a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-compact-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 233547,
|
||||||
|
"catalog_semantic_sha256": "0b81bdd81251ddd527a9c9ecbb5e6048e9c8a3be1f6195465a803d206f03fe73",
|
||||||
|
"discovery_ms": 12976.338863139972,
|
||||||
|
"first_status_ms": 6152.441991027445,
|
||||||
|
"warm_status_ms": 3121.8184099998325,
|
||||||
|
"wall_seconds": 23.47,
|
||||||
|
"cpu_seconds": 19.234341,
|
||||||
|
"kernel_family_peak_bytes": 665423872,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 82,
|
||||||
|
"text_replies": 22690,
|
||||||
|
"combined": 66279,
|
||||||
|
"complete_discovered_catalog": 51352
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "c3c21635cf212eba3902ad64f956244ddfe122425fa3b39ec280b5296ebe23c6",
|
||||||
|
"catalog.json": "e5a4444ea91913e68705a6bd6afee2b8ea0a43b2f91f8628ada597e57afab5db",
|
||||||
|
"transcript.json": "58df156c85a8b1ec325945db08e4e84e8174dfd739f48e4d83b2a3537f7a52b9",
|
||||||
|
"baseline-d532-1-compact-off.log": "8d5b2ddcf5b31ad4635269837e217dd2242a91d82ea961d01e2ab3a2076b9e35"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-compact-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 233547,
|
||||||
|
"catalog_semantic_sha256": "0b81bdd81251ddd527a9c9ecbb5e6048e9c8a3be1f6195465a803d206f03fe73",
|
||||||
|
"discovery_ms": 5907.094460912049,
|
||||||
|
"first_status_ms": 2939.780990127474,
|
||||||
|
"warm_status_ms": 1040.7937010750175,
|
||||||
|
"wall_seconds": 10.742,
|
||||||
|
"cpu_seconds": 10.176561,
|
||||||
|
"kernel_family_peak_bytes": 667668480,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 82,
|
||||||
|
"text_replies": 22690,
|
||||||
|
"combined": 66279,
|
||||||
|
"complete_discovered_catalog": 51352
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "14aed217fcad50915b211e4ee9894ebf9cb4abd8d4c4a4e007cc6fe2b397d44a",
|
||||||
|
"catalog.json": "e55a5b2cba59b09ac4f63831c2af6682d162bf5b05259b3c0f9db8eb2bc67e44",
|
||||||
|
"transcript.json": "e9a9ac8b657da35501e577bf1d1e18c89923c5bcdbb1307c8254d512bbdc7b53",
|
||||||
|
"baseline-d532-2-compact-off.log": "e7c0c68bd1088f11107a6713df1efb74f01ff3479d1913977fe22935814c912c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-full-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 3322571,
|
||||||
|
"catalog_semantic_sha256": "799cc997a9573b5c3dfce3ac22e1fb5eb1637e81b489392f37cc81767b334359",
|
||||||
|
"discovery_ms": 7035.046560922638,
|
||||||
|
"first_status_ms": 1280.1523089874536,
|
||||||
|
"warm_status_ms": 962.2103709261864,
|
||||||
|
"wall_seconds": 10.309,
|
||||||
|
"cpu_seconds": 9.82015,
|
||||||
|
"kernel_family_peak_bytes": 806117376,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187004,
|
||||||
|
"arguments": 84,
|
||||||
|
"text_replies": 22690,
|
||||||
|
"combined": 209778,
|
||||||
|
"complete_discovered_catalog": 845872
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "4e6d4cb20d4b435b47164535930c60902eed44c4efec0665d9eeb2bd0635fd39",
|
||||||
|
"catalog.json": "f0700961a2a999671107dc5e5274098a5d97047e834654c7c3c7ee0c420a91b5",
|
||||||
|
"transcript.json": "4d0b64606c913325ce83bd797b2286d0e9758f09c526dacfce422756cf5212d8",
|
||||||
|
"candidate-1-1-full-full.log": "9d37d44776cfd9f41811e0a608c79ed63257383218e01f602317c2dc5a9de10f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-full-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 3322571,
|
||||||
|
"catalog_semantic_sha256": "799cc997a9573b5c3dfce3ac22e1fb5eb1637e81b489392f37cc81767b334359",
|
||||||
|
"discovery_ms": 5431.887832004577,
|
||||||
|
"first_status_ms": 1290.1408409234136,
|
||||||
|
"warm_status_ms": 1058.6841800250113,
|
||||||
|
"wall_seconds": 8.819,
|
||||||
|
"cpu_seconds": 8.06667,
|
||||||
|
"kernel_family_peak_bytes": 801071104,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187004,
|
||||||
|
"arguments": 78,
|
||||||
|
"text_replies": 22690,
|
||||||
|
"combined": 209772,
|
||||||
|
"complete_discovered_catalog": 845872
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "e2853484e579376a8edb168f84ad2add2ffdd30ce78e123b2dfcdd17d524344e",
|
||||||
|
"catalog.json": "5c918daeb3f8b10625927a87f3f95367a2a2823cc7c098aa8ad3d8d5b47aa6ad",
|
||||||
|
"transcript.json": "1e22387d227134741eac842b8000c5bb73a42e2368c3c53e21bc1d45c17ed819",
|
||||||
|
"candidate-1-2-full-full.log": "877a3bdfe67875bb5ab1981850da2fe519428708184eef55a28c5fa18bb727ea"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-compact-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 2723927,
|
||||||
|
"catalog_semantic_sha256": "d18f02920b84d39b90dc488db89a8f403f6ec35139a39a3329375a18078af1ea",
|
||||||
|
"discovery_ms": 5128.74938105233,
|
||||||
|
"first_status_ms": 1351.6553710214794,
|
||||||
|
"warm_status_ms": 1321.080510970205,
|
||||||
|
"wall_seconds": 8.815,
|
||||||
|
"cpu_seconds": 8.478922,
|
||||||
|
"kernel_family_peak_bytes": 781271040,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 80,
|
||||||
|
"text_replies": 22702,
|
||||||
|
"combined": 66289,
|
||||||
|
"complete_discovered_catalog": 702182
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "ee38fcca794a959271af78a6c65377f411fdbe3b7b97068835b36586ec804ddf",
|
||||||
|
"catalog.json": "db8f1cbaa97c09672537d87ac48457bdb599ae439bca2d8a9216a032edbbdd88",
|
||||||
|
"transcript.json": "22d7a8b00909ad82e40ca7beb21d793bff61dacd88ba0d345ef82eeacf177516",
|
||||||
|
"candidate-1-1-compact-full.log": "ae17a479c9f094e522e15b58617302bf098464a4f55cea21cc913d18ba02afd2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-compact-full",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "full"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 2723927,
|
||||||
|
"catalog_semantic_sha256": "d18f02920b84d39b90dc488db89a8f403f6ec35139a39a3329375a18078af1ea",
|
||||||
|
"discovery_ms": 5686.0627620480955,
|
||||||
|
"first_status_ms": 1266.2633110303432,
|
||||||
|
"warm_status_ms": 1025.3590901847929,
|
||||||
|
"wall_seconds": 8.893,
|
||||||
|
"cpu_seconds": 8.191988,
|
||||||
|
"kernel_family_peak_bytes": 780988416,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 82,
|
||||||
|
"text_replies": 22702,
|
||||||
|
"combined": 66291,
|
||||||
|
"complete_discovered_catalog": 702182
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "1ae8930195ef5d5b6d5118ffaad3d0d2bedaaf114b3887a28357504be023821f",
|
||||||
|
"catalog.json": "7e65fcac2fe7257a2f1c058f2b9ad1200772072fd7cabd4ea315bf4c48307303",
|
||||||
|
"transcript.json": "5a0220b5fe36ae31af91f9eb7f8006290fcf790c774096b838f7287c472e94c1",
|
||||||
|
"candidate-1-2-compact-full.log": "2e4baa5d7e627be27f87739d03f2a4e762ae1675a63e14cc7b5adf883c24192c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-full-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 832191,
|
||||||
|
"catalog_semantic_sha256": "e537c521b5dd0ac369dee706815579d9d7803497a8fc7f7d683fec267042b81c",
|
||||||
|
"discovery_ms": 5637.611771002412,
|
||||||
|
"first_status_ms": 1178.2668600790203,
|
||||||
|
"warm_status_ms": 1036.6536700166762,
|
||||||
|
"wall_seconds": 8.791,
|
||||||
|
"cpu_seconds": 8.201682,
|
||||||
|
"kernel_family_peak_bytes": 656801792,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187005,
|
||||||
|
"arguments": 82,
|
||||||
|
"text_replies": 22698,
|
||||||
|
"combined": 209785,
|
||||||
|
"complete_discovered_catalog": 195042
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "cd706d0ab9a3dd9662ec73ecc45deefdbd40a4a42cd9ee2735be0f8798cc1933",
|
||||||
|
"catalog.json": "9d1fd380d490edf4b6403e3daed015b72bc654b96dfb06dbe7d776e6a6146d76",
|
||||||
|
"transcript.json": "0e3f0c66a2b638729d341af8d8a379576d267b53c1dcea5563e1afa4f9245cc8",
|
||||||
|
"candidate-1-1-full-off.log": "1baf3976c762923680cd17cbef36778b3982e90005eb34bb8ec3ce8030ebd3fb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-full-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["full", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 832191,
|
||||||
|
"catalog_semantic_sha256": "e537c521b5dd0ac369dee706815579d9d7803497a8fc7f7d683fec267042b81c",
|
||||||
|
"discovery_ms": 5316.555531928316,
|
||||||
|
"first_status_ms": 1383.681601146236,
|
||||||
|
"warm_status_ms": 1108.902801061049,
|
||||||
|
"wall_seconds": 8.698,
|
||||||
|
"cpu_seconds": 8.19166,
|
||||||
|
"kernel_family_peak_bytes": 662822912,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 187004,
|
||||||
|
"arguments": 82,
|
||||||
|
"text_replies": 22698,
|
||||||
|
"combined": 209784,
|
||||||
|
"complete_discovered_catalog": 195042
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "89c5f579cb8f8a1860b3f605042ffc51db4aaae69f7a22213256f93e42b91672",
|
||||||
|
"catalog.json": "0301c40f667a17a9238ad8d9abdbb8e8c7b07a7d0dcc6ae062f5885e0b19dfc7",
|
||||||
|
"transcript.json": "7e884d99d3335707f9108a63528fd2830b1c21e7888cfc320852d75924d833cb",
|
||||||
|
"candidate-1-2-full-off.log": "ba34788aa92aa60e79e832659c48f304396d1df41f493a509ff474a152fa7c6c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-compact-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 233547,
|
||||||
|
"catalog_semantic_sha256": "0b81bdd81251ddd527a9c9ecbb5e6048e9c8a3be1f6195465a803d206f03fe73",
|
||||||
|
"discovery_ms": 4922.329220920801,
|
||||||
|
"first_status_ms": 813.2044598460197,
|
||||||
|
"warm_status_ms": 1415.0590698700398,
|
||||||
|
"wall_seconds": 7.982,
|
||||||
|
"cpu_seconds": 7.401054,
|
||||||
|
"kernel_family_peak_bytes": 629260288,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 80,
|
||||||
|
"text_replies": 22678,
|
||||||
|
"combined": 66265,
|
||||||
|
"complete_discovered_catalog": 51352
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "89ae06a9c0e8f4c9b85aa711fc6f71204798c990e582f5702713f78612c4fce2",
|
||||||
|
"catalog.json": "d6a231b2babd7885d58f9712881f96fa9dc2b763cc7efd802bc5676dd71fe28a",
|
||||||
|
"transcript.json": "65fbdb48a9bc2aa65a815ea405d1210e298f908ddbab5e60f815c4e01a0f0e98",
|
||||||
|
"candidate-1-1-compact-off.log": "76501971a3698b13435b96647b59ee092689397012d453e62c821e4ecf40e988"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-compact-off",
|
||||||
|
"verified_complete": true,
|
||||||
|
"profiles": ["compact", "off"],
|
||||||
|
"catalog_tools": 209,
|
||||||
|
"catalog_bytes": 233547,
|
||||||
|
"catalog_semantic_sha256": "0b81bdd81251ddd527a9c9ecbb5e6048e9c8a3be1f6195465a803d206f03fe73",
|
||||||
|
"discovery_ms": 4839.713891968131,
|
||||||
|
"first_status_ms": 1174.165149917826,
|
||||||
|
"warm_status_ms": 1409.5584598835558,
|
||||||
|
"wall_seconds": 8.289,
|
||||||
|
"cpu_seconds": 7.764389,
|
||||||
|
"kernel_family_peak_bytes": 627363840,
|
||||||
|
"token_proxy": {
|
||||||
|
"input_facing_catalog": 43507,
|
||||||
|
"arguments": 80,
|
||||||
|
"text_replies": 22678,
|
||||||
|
"combined": 66265,
|
||||||
|
"complete_discovered_catalog": 51352
|
||||||
|
},
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "a4ef1220b73c39421ccfc22c2102c613fd0a33900cbc8683dad1dc3bc034cf5a",
|
||||||
|
"catalog.json": "39ae1d7385fe8684f037e354ec2ab1126243fd31667be1b1cc559a9d1e40149c",
|
||||||
|
"transcript.json": "d60eae5fdbfb4095f040d54103a6e9b1d2ff8b8f64126976d14b0a3e024969f7",
|
||||||
|
"candidate-1-2-compact-off.log": "0e195ca040565e29e1f6d25b087a706d0d500ff1752a24bff54ad30704bd6d6b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"digest_phases": [
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-compact-full-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 3827.9035209999997,
|
||||||
|
"digest_ms": 2916.01332,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 2587474,
|
||||||
|
"system": 151462
|
||||||
|
},
|
||||||
|
"raw_sha256": "28a8e0b5c847978be9d71e4d5ed6953758e266e697b820f45f1d2141861c95e3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-compact-off-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 3873.5359620000004,
|
||||||
|
"digest_ms": 3790.342601,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 3121749,
|
||||||
|
"system": 212457
|
||||||
|
},
|
||||||
|
"raw_sha256": "b88dd91f159a1763d547f1e26637afaf3a03b28faad3295c2deff8c90e7d7707"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-full-full-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 1766.4657209999998,
|
||||||
|
"digest_ms": 0.06419000000005326,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 65,
|
||||||
|
"system": 12
|
||||||
|
},
|
||||||
|
"raw_sha256": "0f18c0d63def7df73b6183240c49011aca9cd85899a221fdb01908da1d79120f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-1-full-off-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 5377.792571,
|
||||||
|
"digest_ms": 3209.784441,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 2585090,
|
||||||
|
"system": 252879
|
||||||
|
},
|
||||||
|
"raw_sha256": "2de37e6aac00f37003f619c4b4a5a747637e0b188e9892d5a37a091ae568400a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-compact-full-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 1807.87952,
|
||||||
|
"digest_ms": 1512.0799399999999,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 1421207,
|
||||||
|
"system": 88507
|
||||||
|
},
|
||||||
|
"raw_sha256": "a330124a6cec474e5337aa5a40c33d31fa0bdce304554c1c68f79954bf5cdd33"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-compact-off-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 1854.8867300000002,
|
||||||
|
"digest_ms": 1402.711411,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 1284446,
|
||||||
|
"system": 116933
|
||||||
|
},
|
||||||
|
"raw_sha256": "02f19af3b9836796d85f81effd5e86bab0aa4978eeae0c59b8c35e57d03dd17b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-full-full-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 1572.84796,
|
||||||
|
"digest_ms": 0.0849799999998595,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 85,
|
||||||
|
"system": 15
|
||||||
|
},
|
||||||
|
"raw_sha256": "a9fca1656b8763f5ef305548eceb7bbd27cdeb426c6d6934a891c82823a54f31"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "baseline-d532-2-full-off-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 1814.550491,
|
||||||
|
"digest_ms": 1280.248369,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 1166910,
|
||||||
|
"system": 108321
|
||||||
|
},
|
||||||
|
"raw_sha256": "350a276f6f408de517db2b19af7cd7490c243b71338854d4acb54418f1a00b64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-compact-full-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 1760.5044,
|
||||||
|
"digest_ms": 0.08051999999997861,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 76,
|
||||||
|
"system": 14
|
||||||
|
},
|
||||||
|
"raw_sha256": "3ebc2dac6cff195b54918e5afaedc0b73fe9f1a63ef12ebb253d9a1aca683c8c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-compact-off-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 1922.20413,
|
||||||
|
"digest_ms": 0.07567999999992026,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 75,
|
||||||
|
"system": 11
|
||||||
|
},
|
||||||
|
"raw_sha256": "d5916e1e5760f9c7ce5a42ee8b7635477464a5a7cb7d379309666357b6fbe35f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-full-full-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 1777.54332,
|
||||||
|
"digest_ms": 0.08724099999994905,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 93,
|
||||||
|
"system": 13
|
||||||
|
},
|
||||||
|
"raw_sha256": "ed68a8c592c9556b7a279a90b7324d5549f9dc197fe593d27c55c5de24827481"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-1-full-off-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 2062.896171,
|
||||||
|
"digest_ms": 0.06988900000033027,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 69,
|
||||||
|
"system": 12
|
||||||
|
},
|
||||||
|
"raw_sha256": "166dcdaa064c334dcc882429c2434c0353b0f6d2ccdea986138a2149ccccf10a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-compact-full-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 1813.35421,
|
||||||
|
"digest_ms": 0.06941099999994549,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 73,
|
||||||
|
"system": 10
|
||||||
|
},
|
||||||
|
"raw_sha256": "86497ee4962fd03fcad4f2bcc31e95f5f57d9c4270cc0578d4b43a076ec01b53"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-compact-off-digest",
|
||||||
|
"input": "compact",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 2024.0317209999998,
|
||||||
|
"digest_ms": 0.08607000000029075,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 89,
|
||||||
|
"system": 13
|
||||||
|
},
|
||||||
|
"raw_sha256": "82b47ed9bc203f1417f5f76de808d493c171f95598934fc9ebbd6f63be43b938"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-full-full-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "full",
|
||||||
|
"import_ms": 1917.6121309999999,
|
||||||
|
"digest_ms": 0.07732000000009975,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 77,
|
||||||
|
"system": 11
|
||||||
|
},
|
||||||
|
"raw_sha256": "410395499363c55e53fe4d8488b5e83c54170786fe1814389fd3bf4ec317c6ac"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "candidate-1-2-full-off-digest",
|
||||||
|
"input": "full",
|
||||||
|
"output": "off",
|
||||||
|
"import_ms": 1715.96008,
|
||||||
|
"digest_ms": 0.08907999999996719,
|
||||||
|
"digest_cpu_us": {
|
||||||
|
"user": 104,
|
||||||
|
"system": 15
|
||||||
|
},
|
||||||
|
"raw_sha256": "f6ea0fffc2974e02bdab1348736533c8dbd677c2311e339a945d760bd9337f9a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"build_digest_phase": [
|
||||||
|
{
|
||||||
|
"phase": "before",
|
||||||
|
"operation": "createCatalogDigests",
|
||||||
|
"import_ms": 2103.978981,
|
||||||
|
"compute_ms": 1640.0212299999998,
|
||||||
|
"compute_cpu_us": {
|
||||||
|
"user": 1487510,
|
||||||
|
"system": 148234
|
||||||
|
},
|
||||||
|
"raw_sha256": "3a4bfe5e4297e95cf0ab3b832bb34c81edeca02e7f884db7dd5a6944c2ee1674"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": "after",
|
||||||
|
"operation": "createCatalogDigestProfiles",
|
||||||
|
"import_ms": 1752.475121,
|
||||||
|
"compute_ms": 2379.7143199999996,
|
||||||
|
"compute_cpu_us": {
|
||||||
|
"user": 2232836,
|
||||||
|
"system": 140061
|
||||||
|
},
|
||||||
|
"raw_sha256": "b25120373c7433457e30ff00925ca2771c0d61ba96828fe89e63be651b4f6e4a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"failed_attempts": [
|
||||||
|
{
|
||||||
|
"recording": "codex-host-full-1",
|
||||||
|
"outcome": "Harness expected counts.tools rather than canonical counts.mcp_tools; corrected oracle, not a completed task.",
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "ac3d531a9dad31e31cb9a5957ed1f5e6415534fda1e52c64bd93a07a36ef7d0f",
|
||||||
|
"codex-host-full-1.log": "7c5f13e2976efef59306b9a2fabd2e2031277d3c5aed2b74f4ff2ad80c25a61c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recording": "codex-host-matrix-compact-off-1",
|
||||||
|
"outcome": "Functional checks passed but MCP child remained at payload exit. Excluded from qualified cohort. Controller now waits for allocated scope to drain without targeting a PID.",
|
||||||
|
"raw_sha256": {
|
||||||
|
"report.json": "1cbc9df5aff972538629ed695271f0c3a66fcfe546208b392d09b3b7cf72f97c",
|
||||||
|
"codex-host-matrix-compact-off-1.log": "997e13a9ea7b3c5247d5037279fbef1d0dfd238eed0781748cc2ddf3afc706e7"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unverified": [
|
||||||
|
"Model selection/injection and actual model tokens",
|
||||||
|
"Provider analysis, target execution and end-to-end reverse-engineering application quality",
|
||||||
|
"Source-mode speedup: absent build records still use dynamic fallback",
|
||||||
|
"Other MCP clients/OS compatibility not established by this Codex experiment"
|
||||||
|
],
|
||||||
|
"validation": [
|
||||||
|
{
|
||||||
|
"check": "check-profiles",
|
||||||
|
"payload_exit_code": 1,
|
||||||
|
"owned_cleanup_verified": true,
|
||||||
|
"raw_sha256": "04dd1ad8142e61e9c2960ec55a3a7f0421f4c22f5cb5b9702761a0d7f29d3cc4",
|
||||||
|
"source_head": "pre-rebase candidate",
|
||||||
|
"outcome": "Unused build-only export identified; existing output-policy coverage extended to the profile builder."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "build-latest",
|
||||||
|
"payload_exit_code": 0,
|
||||||
|
"owned_cleanup_verified": true,
|
||||||
|
"raw_sha256": "f430e38ecb205aa7bde17b48ff7ad97805b18511dbbfee8bdbab605f4f93b86e",
|
||||||
|
"source_head": "7ad06628df042a7c8034155a98fc51c35fa0704c",
|
||||||
|
"outcome": "passed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "tests-latest",
|
||||||
|
"payload_exit_code": 0,
|
||||||
|
"owned_cleanup_verified": true,
|
||||||
|
"raw_sha256": "58b06f5be6ae5c0cb871cba6788b3f84581289a47ffe26aaad8897b606c94e2d",
|
||||||
|
"source_head": "7ad06628df042a7c8034155a98fc51c35fa0704c",
|
||||||
|
"outcome": "passed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "check-latest",
|
||||||
|
"payload_exit_code": 0,
|
||||||
|
"owned_cleanup_verified": true,
|
||||||
|
"raw_sha256": "2373fec55a74515f6e3036d46becd4ed76149d9a70731a64c5dddacaeeb920cc",
|
||||||
|
"source_head": "7ad06628df042a7c8034155a98fc51c35fa0704c",
|
||||||
|
"outcome": "passed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "docs-latest",
|
||||||
|
"payload_exit_code": 0,
|
||||||
|
"owned_cleanup_verified": true,
|
||||||
|
"raw_sha256": "23ef004935364b7a1ad2634610b67c1d739bde4f4c455552a473a05b346920ee",
|
||||||
|
"source_head": "7ad06628df042a7c8034155a98fc51c35fa0704c",
|
||||||
|
"outcome": "passed"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"post_rebase_qualification": {
|
||||||
|
"head": "7ad06628df042a7c8034155a98fc51c35fa0704c",
|
||||||
|
"base": "e84468c0b",
|
||||||
|
"client": "Codex app-server 0.163.0",
|
||||||
|
"profiles": ["compact", "off"],
|
||||||
|
"outcome": "Complete discovery and first/warm status facts pass; allocated scope drains; no model turns. Qualification only; not relabeled as the pinned before/after measurements.",
|
||||||
|
"raw_sha256": {
|
||||||
|
"final-latest-compact-off/report.json": "ba6f549fe087f55dc48011daf92bd18f4bfc2a32e6185081ab2b7436bf39b1b8",
|
||||||
|
"final-latest-compact-off/transcript.json": "461a25723c2a4bb4c18675ffa613e98a8592a4e933054fa8643f1da73fc4686f",
|
||||||
|
"final-latest-compact-off.log": "4efc56e69b8f0d1111345bce10d0d0792b510e18901f52d10e538374257e1d61"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
# MCP schema profile identity startup
|
||||||
|
|
||||||
|
Continues [#723](https://github.com/morluto/rea/issues/723). The default catalog
|
||||||
|
identity was already recorded at build time (#4041). Compact input and omitted
|
||||||
|
output advertisement profiles still converted and hashed the complete catalog
|
||||||
|
on demand. This change records the four built-in combinations at the same
|
||||||
|
owning build step. Canonical tool facts and output-schema conversion are shared
|
||||||
|
while building those records. Only immutable hash triples reach the runtime:
|
||||||
|
the generated module grows from 411 to 1,320 bytes.
|
||||||
|
|
||||||
|
Exact full/compact and full/off selections choose their matching record. Source
|
||||||
|
execution and custom compact budgets retain lazy dynamic calculation, including
|
||||||
|
snapshotting the caller's budget. The build consumes the compiled contracts and
|
||||||
|
pinned converter before bundling; rebuilding invalidates the records. No live
|
||||||
|
provider state is cached. Output-off identities still cover canonical output
|
||||||
|
contracts, as before. All four digest triples match the pre-change runtime.
|
||||||
|
|
||||||
|
## Completed task and oracle
|
||||||
|
|
||||||
|
A fresh **actual Codex app-server 0.163.0** discovers every tool, then reports
|
||||||
|
whether a target is open, cleanup is pending, a provider is bound, and whether
|
||||||
|
the package version and catalog count match, twice in the same session.
|
||||||
|
The oracle is the selected package metadata, the pinned 209-tool contract,
|
||||||
|
no-target state, text/structured-result agreement and original pre-change
|
||||||
|
identities. Canonicalized actual-client catalogs agree before/after within
|
||||||
|
each profile; JSON object order in Codex's tool map varies by process.
|
||||||
|
|
||||||
|
The [driver](mcp-profile-identity.py) uses the installed client's version-specific
|
||||||
|
`initialize`, `thread/start`, `mcpServerStatus/list` and `mcpServer/tool/call`
|
||||||
|
protocol ([official app-server documentation](https://learn.chatgpt.com/docs/app-server)).
|
||||||
|
It uses a fresh temporary account/configuration and starts **no model turns**.
|
||||||
|
This establishes actual-client schema discovery and direct tool-call
|
||||||
|
compatibility, not model analysis quality or actual model token savings.
|
||||||
|
Existing compact/off choices remain explicit; neither becomes a new default.
|
||||||
|
|
||||||
|
Baseline: main `d532b18123916a9e88f98c7880ba4f984e23d715`. Both packaged runtimes
|
||||||
|
are frozen before measurement; their source patch, package/manifests and raw
|
||||||
|
transcripts/resource observations are retained outside Git, pinned by the
|
||||||
|
[receipt](mcp-profile-identity.json). Later validation does not relabel timings.
|
||||||
|
Node 24.18.0/npm 11.16.0, MCP SDK 2.3.1, negotiated protocol `2025-06-18`, Linux
|
||||||
|
x86-64. Two repetitions alternate baseline/candidate cohorts and reverse profile
|
||||||
|
order. Every recording starts a fresh server and includes discovery, first and
|
||||||
|
warm status calls, verification and cleanup. OS caches are unflushed.
|
||||||
|
|
||||||
|
The existing guard admits one CPU, a 4 GiB hard/3 GiB early memory boundary,
|
||||||
|
2 GiB Node heaps, no swap and 192 tasks. Kernel family peaks include file cache,
|
||||||
|
Codex, REA and controller; they are not provider heap measurements. All 16
|
||||||
|
qualified recordings exit successfully with only the observer remaining, no
|
||||||
|
resource stop and zero observed OOM events. Final whole-scope counters are
|
||||||
|
unavailable. The host's CPU is shared with unrelated work; ranges retain the
|
||||||
|
observed variation.
|
||||||
|
|
||||||
|
## Measurements
|
||||||
|
|
||||||
|
Ranges show both repetitions. Times include the whole task and shutdown.
|
||||||
|
|
||||||
|
| Input / output profile | Wall seconds before → after | CPU seconds before → after | Family peak MiB before → after |
|
||||||
|
| ---------------------- | --------------------------- | -------------------------- | ------------------------------ |
|
||||||
|
| full / full | 8.91–8.92 → 8.82–10.31 | 8.45–8.48 → 8.07–9.82 | 765–766 → 764–769 |
|
||||||
|
| compact / full | 11.15–18.99 → 8.82–8.89 | 10.61–16.52 → 8.19–8.48 | 772–779 → 745–745 |
|
||||||
|
| full / off | 10.33–19.59 → 8.70–8.79 | 9.76–16.96 → 8.19–8.20 | 671–677 → 626–632 |
|
||||||
|
| compact / off | 10.74–23.47 → 7.98–8.29 | 10.18–19.23 → 7.40–7.76 | 635–637 → 598–600 |
|
||||||
|
|
||||||
|
First/warm call times remain separately recorded in the receipt. Across the
|
||||||
|
three non-default profiles the first call ranges from 2.73–6.15 s before to
|
||||||
|
0.81–1.38 s after; warm calls range from 1.04–3.12 s before to 1.03–1.42 s after.
|
||||||
|
The default profile has no established gain; one candidate repetition is slower.
|
||||||
|
|
||||||
|
Fresh-process [identity probes](mcp-profile-digest.mjs) isolate the lazy read
|
||||||
|
from module loading. The non-default digest computation takes 1.28–3.79 s
|
||||||
|
before and under 0.2 ms after. Building all four identities shares schema
|
||||||
|
conversion: isolated compute CPU increases from 1.636 s (one identity) to
|
||||||
|
2.373 s (four). Full uncached builds were 42.59 → 81.09 s wall, 41.59 → 68.27 s
|
||||||
|
CPU, 3318.5 → 3216.4 MiB peak. These single builds include TypeScript, bundling
|
||||||
|
and concurrent host contention, so their difference is not attributed solely
|
||||||
|
to digest generation. The isolated phase is one observation per version.
|
||||||
|
|
||||||
|
There is **no token reduction from this change**. Each profile's complete
|
||||||
|
catalog size and serialization-token estimate are unchanged. Full/full remains
|
||||||
|
3,322,571 bytes as exposed by this client; compact/off remains 233,547 bytes
|
||||||
|
through existing configuration. The input-facing catalog plus both argument
|
||||||
|
and text replies is about 209.8k proxy tokens with full input and 66.3k with
|
||||||
|
compact input, before and after. Small differences come from fresh timestamps
|
||||||
|
and runtime paths. The [cost script](mcp-profile-costs.py) uses
|
||||||
|
`tiktoken==0.12.0`/`cl100k_base`; these estimates are not actual model usage or a
|
||||||
|
claim about what the host injects. Output schemas, hidden prompts and model
|
||||||
|
reasoning must not be inferred from that projection.
|
||||||
|
|
||||||
|
## Validation and remaining scope
|
||||||
|
|
||||||
|
Executed: four files / 46 tests pass, including real production stdio doctor
|
||||||
|
for all four profiles, source catalog/schema consistency, output-off identity
|
||||||
|
coverage, malformed replies, startup cancellation/cleanup, generated immutable
|
||||||
|
record reuse and caller-selected custom budgets. The pre-change runtime is
|
||||||
|
also an independent oracle for all four complete hash triples.
|
||||||
|
|
||||||
|
After rebasing onto main `e84468c0b`, the four files / 46 tests pass again,
|
||||||
|
as do `npm run check` (types, lint, format, knip, metadata and architecture)
|
||||||
|
and `npm run docs:check` (including five README consistency tests). Actual
|
||||||
|
Codex compact/off discovery and both status calls pass again with verified
|
||||||
|
cleanup. This final qualification does not replace the pinned timing cohort.
|
||||||
|
An initial static check identified the build-only export as untracked; the
|
||||||
|
existing output-policy regression now directly exercises its four profiles.
|
||||||
|
|
||||||
|
Earlier exploratory attempts remain excluded: one controller expected the
|
||||||
|
wrong count key; one functional compact/off run left a child alive at payload
|
||||||
|
exit. The corrected controller waits for its allocated scope to drain without
|
||||||
|
killing individual PIDs; all later qualified runs verify that drain. Neither
|
||||||
|
failed attempt establishes a production regression.
|
||||||
|
|
||||||
|
SDK 2.3.1 already supports a named `toolDefinition`, used by REA's doctor to
|
||||||
|
avoid preparing every output validator for its one probe. Generic external SDK
|
||||||
|
callers still incur their own catalog preparation. Input presentation and
|
||||||
|
output refs already have owning reuse; these were not duplicate fixes.
|
||||||
|
Target/provider investigations, other clients/platforms and actual model
|
||||||
|
analysis cost remain unverified by this no-target startup task.
|
||||||
|
|
||||||
|
To reproduce with the pinned client and a built runtime, run under the existing
|
||||||
|
resource guard:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python3 experiments/analysis-efficiency/resource-run.py --observe-payload-exit -- \
|
||||||
|
python3 experiments/analysis-efficiency/mcp-profile-identity.py \
|
||||||
|
--output /tmp/rea-profile-case --runtime /absolute/built/rea \
|
||||||
|
--node /absolute/node24/bin/node --codex /absolute/codex-0.163.0 \
|
||||||
|
--input-profile compact --output-profile off
|
||||||
|
```
|
||||||
|
|
||||||
|
Retain the resource output as `/tmp/rea-profile-case.log` for the cost script.
|
||||||
|
The driver is pinned to Codex 0.163.0's experimental protocol and the 209-tool
|
||||||
|
catalog in this receipt; update its oracle deliberately for another revision.
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
"""Exercise real Codex MCP discovery/calls without starting a model turn."""
|
||||||
|
import argparse
|
||||||
|
import asyncio
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--output", type=Path, required=True)
|
||||||
|
parser.add_argument("--runtime", type=Path, required=True)
|
||||||
|
parser.add_argument("--codex", type=Path, required=True)
|
||||||
|
parser.add_argument("--node", type=Path, required=True)
|
||||||
|
parser.add_argument("--input-profile", choices=["full", "compact"], default="full")
|
||||||
|
parser.add_argument("--output-profile", choices=["full", "off"], default="full")
|
||||||
|
args = parser.parse_args()
|
||||||
|
args.output.mkdir(mode=0o700)
|
||||||
|
audit_home = args.output / "account"
|
||||||
|
codex_state = audit_home / ".codex"
|
||||||
|
mcp_home = audit_home / "mcp"
|
||||||
|
workspace = audit_home / "workspace"
|
||||||
|
for directory in [codex_state, mcp_home, workspace]:
|
||||||
|
directory.mkdir(parents=True)
|
||||||
|
task_path = f"{args.node.parent}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
mcp_env = {"HOME": str(mcp_home), "PATH": task_path,
|
||||||
|
"NODE_OPTIONS": "--max-old-space-size=2048", "UV_THREADPOOL_SIZE": "1",
|
||||||
|
"REA_LOG_LEVEL": "silent", "REA_MCP_INPUT_SCHEMA_PROFILE": args.input_profile,
|
||||||
|
"REA_MCP_OUTPUT_SCHEMA_PROFILE": args.output_profile}
|
||||||
|
config = '[analytics]\nenabled = false\n[mcp_servers.rea_audit]\n'
|
||||||
|
config += f'command = {json.dumps(str(args.node))}\n'
|
||||||
|
config += f'args = {json.dumps([str(args.runtime / "scripts/rea.mjs"), "mcp"])}\n'
|
||||||
|
config += 'startup_timeout_sec = 60\ntool_timeout_sec = 60\n'
|
||||||
|
config += '[mcp_servers.rea_audit.env]\n'
|
||||||
|
config += ''.join(f'{key} = {json.dumps(value)}\n' for key, value in mcp_env.items())
|
||||||
|
(codex_state / "config.toml").write_text(config)
|
||||||
|
(args.output / "declared-config.toml").write_text(config)
|
||||||
|
environment = {"HOME": str(audit_home), "CODEX_HOME": str(codex_state), "PATH": task_path,
|
||||||
|
"NODE_OPTIONS": "--max-old-space-size=2048", "UV_THREADPOOL_SIZE": "1"}
|
||||||
|
report = {"question": "Discover the complete canonical tool catalog and report no-target session/cleanup state, selected provider, package version and catalog tool count twice.",
|
||||||
|
"client": "Codex app-server 0.163.0", "model_turns_started": 0,
|
||||||
|
"actual_model_usage": None, "input_profile": args.input_profile,
|
||||||
|
"output_profile": args.output_profile, "calls": [], "observations": [],
|
||||||
|
"unexpected_server_requests": [], "cleanup_failures": []}
|
||||||
|
transcript = []
|
||||||
|
pending = {}
|
||||||
|
next_id = 0
|
||||||
|
stderr = (args.output / "server.log").open("wb")
|
||||||
|
process = await asyncio.create_subprocess_exec(str(args.codex), "app-server", "--stdio",
|
||||||
|
stdin=asyncio.subprocess.PIPE, stdout=asyncio.subprocess.PIPE, stderr=stderr,
|
||||||
|
cwd=workspace, env=environment, limit=16 * 1024 * 1024)
|
||||||
|
|
||||||
|
async def send(message):
|
||||||
|
encoded = (json.dumps(message, separators=(",", ":")) + "\n").encode()
|
||||||
|
transcript.append({"direction": "client", "bytes": len(encoded), "message": message})
|
||||||
|
process.stdin.write(encoded)
|
||||||
|
await process.stdin.drain()
|
||||||
|
|
||||||
|
async def read_messages():
|
||||||
|
try:
|
||||||
|
while line := await process.stdout.readline():
|
||||||
|
value = json.loads(line)
|
||||||
|
transcript.append({"direction": "server", "bytes": len(line), "message": value})
|
||||||
|
if "id" in value and "method" not in value:
|
||||||
|
future = pending.pop(value["id"], None)
|
||||||
|
if future and not future.done():
|
||||||
|
future.set_result(value)
|
||||||
|
elif "id" in value:
|
||||||
|
report["unexpected_server_requests"].append(value["method"])
|
||||||
|
await send({"id": value["id"], "error": {"code": -32601, "message": "Unexpected request in read-only discovery probe"}})
|
||||||
|
raise RuntimeError("app-server stdout closed")
|
||||||
|
except Exception as error:
|
||||||
|
for future in pending.values():
|
||||||
|
if not future.done():
|
||||||
|
future.set_exception(error)
|
||||||
|
|
||||||
|
reader = asyncio.create_task(read_messages())
|
||||||
|
|
||||||
|
async def request(method, params):
|
||||||
|
nonlocal next_id
|
||||||
|
assert method in ["initialize", "thread/start", "mcpServerStatus/list", "mcpServer/tool/call"]
|
||||||
|
next_id += 1
|
||||||
|
message = {"id": next_id, "method": method, "params": params}
|
||||||
|
future = asyncio.get_running_loop().create_future()
|
||||||
|
pending[next_id] = future
|
||||||
|
start = time.monotonic()
|
||||||
|
await send(message)
|
||||||
|
reply = await asyncio.wait_for(future, 90)
|
||||||
|
report["calls"].append({"method": method, "elapsed_ms": (time.monotonic() - start) * 1000,
|
||||||
|
"error": reply.get("error")})
|
||||||
|
if "error" in reply:
|
||||||
|
raise RuntimeError(json.dumps(reply["error"])[:4000])
|
||||||
|
return reply["result"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
await request("initialize", {"clientInfo": {"name": "rea_host_probe", "title": "REA host compatibility probe", "version": "1"},
|
||||||
|
"capabilities": {"experimentalApi": True, "explicitGatewayOauth": True}})
|
||||||
|
await send({"method": "initialized"})
|
||||||
|
created = await request("thread/start", {"cwd": str(workspace), "ephemeral": True,
|
||||||
|
"approvalPolicy": "never", "sandbox": "read-only"})
|
||||||
|
thread_id = created["thread"]["id"]
|
||||||
|
assert not created["thread"].get("turns", [])
|
||||||
|
inventory = await request("mcpServerStatus/list", {"threadId": thread_id,
|
||||||
|
"serverName": "rea_audit", "detail": "toolsAndAuthOnly", "limit": 10})
|
||||||
|
assert inventory.get("nextCursor") is None
|
||||||
|
assert len(inventory["data"]) == 1
|
||||||
|
server = inventory["data"][0]
|
||||||
|
assert server["name"] == "rea_audit" and server.get("toolsError") is None
|
||||||
|
tools = list(server["tools"].values())
|
||||||
|
names = [tool["name"] for tool in tools]
|
||||||
|
assert len(names) == len(set(names)) == 209
|
||||||
|
assert "binary_session" in names
|
||||||
|
output_schemas = sum(tool.get("outputSchema") is not None for tool in tools)
|
||||||
|
assert output_schemas == (209 if args.output_profile == "full" else 0)
|
||||||
|
raw = json.dumps(inventory, separators=(",", ":"), ensure_ascii=False).encode()
|
||||||
|
(args.output / "catalog.json").write_bytes(raw)
|
||||||
|
report["catalog"] = {"tools": len(tools), "output_schemas": output_schemas,
|
||||||
|
"bytes": len(raw), "sha256": hashlib.sha256(raw).hexdigest(),
|
||||||
|
"server_info": server.get("serverInfo"), "runtime_status": server.get("runtimeStatus")}
|
||||||
|
version = json.loads((args.runtime / "package.json").read_text())["version"]
|
||||||
|
for phase in ["first", "warm"]:
|
||||||
|
reply = await request("mcpServer/tool/call", {"threadId": thread_id,
|
||||||
|
"server": "rea_audit", "tool": "binary_session", "arguments": {}})
|
||||||
|
assert reply.get("isError") is not True
|
||||||
|
structured = reply["structuredContent"]
|
||||||
|
texts = [c["text"] for c in reply["content"] if c.get("type") == "text"]
|
||||||
|
assert len(texts) == 1 and json.loads(texts[0]) == structured
|
||||||
|
facts = structured["result"]
|
||||||
|
assert facts["open"] is False and facts["cleanup_pending"] is False
|
||||||
|
assert facts["analysis_provider_binding"] is None
|
||||||
|
assert facts["server_identity"]["package"]["version"] == version
|
||||||
|
assert facts["server_identity"]["catalog"]["counts"]["mcp_tools"] == 209
|
||||||
|
report["observations"].append({"phase": phase, "open": facts["open"],
|
||||||
|
"cleanup_pending": facts["cleanup_pending"], "selected_provider": facts["analysis_provider_binding"],
|
||||||
|
"package_version": version, "catalog_tools": 209,
|
||||||
|
"negotiated_protocol": facts["server_identity"]["negotiated_protocol_version"],
|
||||||
|
"structured_bytes": len(json.dumps(structured, separators=(",", ":"), ensure_ascii=False).encode())})
|
||||||
|
selected_facts = lambda observation: {key: value for key, value in observation.items()
|
||||||
|
if key not in ["phase", "structured_bytes"]}
|
||||||
|
assert selected_facts(report["observations"][0]) == selected_facts(report["observations"][1])
|
||||||
|
assert not report["unexpected_server_requests"]
|
||||||
|
report["status"] = "passed"
|
||||||
|
except Exception:
|
||||||
|
report["status"] = "failed"
|
||||||
|
report["failure"] = traceback.format_exc()[-6000:]
|
||||||
|
finally:
|
||||||
|
process.stdin.close()
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(process.wait(), 15)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
report["cleanup_failures"].append("app-server did not exit after stdin close; terminated owned process")
|
||||||
|
process.terminate()
|
||||||
|
try:
|
||||||
|
await asyncio.wait_for(process.wait(), 5)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
process.kill()
|
||||||
|
await process.wait()
|
||||||
|
await reader
|
||||||
|
# app-server can acknowledge exit before its MCP child finishes EOF
|
||||||
|
# cleanup. Wait on the allocated resource scope; never target a PID.
|
||||||
|
try:
|
||||||
|
groups = [line[3:] for line in Path("/proc/self/cgroup").read_text().splitlines()
|
||||||
|
if line.startswith("0::")]
|
||||||
|
assert len(groups) == 1
|
||||||
|
group = Path("/sys/fs/cgroup") / groups[0].lstrip("/")
|
||||||
|
assert re.fullmatch(r"rea-efficiency-[0-9a-f]{32}\.scope", group.name)
|
||||||
|
observer = os.getppid()
|
||||||
|
observer_args = Path(f"/proc/{observer}/cmdline").read_bytes().split(b"\0")
|
||||||
|
assert any(Path(os.fsdecode(value)).name == "resource_payload.py" for value in observer_args if value)
|
||||||
|
expected = {os.getpid(), observer}
|
||||||
|
until = time.monotonic() + 10
|
||||||
|
while True:
|
||||||
|
actors = {int(value) for value in (group / "cgroup.procs").read_text().splitlines()}
|
||||||
|
assert expected <= actors
|
||||||
|
remaining = sorted(actors - expected)
|
||||||
|
if not remaining or time.monotonic() >= until:
|
||||||
|
break
|
||||||
|
await asyncio.sleep(0.05)
|
||||||
|
report["owned_scope_drain"] = {"remaining_processes": remaining}
|
||||||
|
if remaining:
|
||||||
|
report["cleanup_failures"].append("owned MCP child did not settle after app-server exit")
|
||||||
|
except (OSError, ValueError, AssertionError) as error:
|
||||||
|
report["owned_scope_drain"] = {"status": "unavailable", "reason": type(error).__name__}
|
||||||
|
report["cleanup_failures"].append("allocated resource-scope cleanup could not be verified")
|
||||||
|
stderr.close()
|
||||||
|
report["appserver_exit_code"] = process.returncode
|
||||||
|
if process.returncode != 0:
|
||||||
|
report["cleanup_failures"].append(f"app-server exit code: {process.returncode}")
|
||||||
|
(args.output / "transcript.json").write_text(json.dumps(transcript) + "\n")
|
||||||
|
(args.output / "report.json").write_text(json.dumps(report, indent=2) + "\n")
|
||||||
|
print(json.dumps({key: report.get(key) for key in ["status", "failure", "catalog", "observations", "cleanup_failures", "appserver_exit_code"]}))
|
||||||
|
return 0 if report["status"] == "passed" and not report["cleanup_failures"] else 1
|
||||||
|
|
||||||
|
|
||||||
|
raise SystemExit(asyncio.run(main()))
|
||||||
@@ -2,18 +2,31 @@ import { writeFile } from "node:fs/promises";
|
|||||||
import { dirname, join, resolve } from "node:path";
|
import { dirname, join, resolve } from "node:path";
|
||||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||||
|
|
||||||
// Record the default catalog digests into the compiled runtime. Run after
|
// Record built-in catalog profile digests into the compiled runtime. Run after
|
||||||
// `tsc` and before bundling, so the digests come from the same compiled
|
// `tsc` and before bundling, so the digests come from the same compiled
|
||||||
// contracts and pinned schema converter that the runtime serves.
|
// contracts and pinned schema converter that the runtime serves.
|
||||||
const compiledRoot = resolve(
|
const compiledRoot = resolve(
|
||||||
dirname(fileURLToPath(import.meta.url)),
|
dirname(fileURLToPath(import.meta.url)),
|
||||||
"../dist",
|
"../dist",
|
||||||
);
|
);
|
||||||
const { createCatalogDigests } = await import(
|
const { createCatalogDigestProfiles } = await import(
|
||||||
pathToFileURL(join(compiledRoot, "catalogIdentity.js")).href
|
pathToFileURL(join(compiledRoot, "catalogIdentity.js")).href
|
||||||
);
|
);
|
||||||
|
// Retain only hashes, with every shared record frozen. Schemas remain owned by
|
||||||
|
// the compiled contracts and are converted once for all four identities.
|
||||||
|
const profiles = Object.entries(createCatalogDigestProfiles())
|
||||||
|
.map(
|
||||||
|
([input, outputs]) =>
|
||||||
|
`${JSON.stringify(input)}: Object.freeze({${Object.entries(outputs)
|
||||||
|
.map(
|
||||||
|
([output, digests]) =>
|
||||||
|
`${JSON.stringify(output)}: Object.freeze(${JSON.stringify(digests)})`,
|
||||||
|
)
|
||||||
|
.join(",")}})`,
|
||||||
|
)
|
||||||
|
.join(",");
|
||||||
await writeFile(
|
await writeFile(
|
||||||
join(compiledRoot, "recordedCatalogDigests.js"),
|
join(compiledRoot, "recordedCatalogDigests.js"),
|
||||||
`/** Recorded from the compiled default catalog by scripts/record-catalog-digests.mjs; do not edit. */\nexport const RECORDED_CATALOG_DIGESTS = Object.freeze(${JSON.stringify(createCatalogDigests())});\n`,
|
`/** Recorded from compiled catalog profiles by scripts/record-catalog-digests.mjs; do not edit. */\nexport const RECORDED_CATALOG_DIGEST_PROFILES = Object.freeze({${profiles}});\n`,
|
||||||
"utf8",
|
"utf8",
|
||||||
);
|
);
|
||||||
+81
-27
@@ -17,7 +17,11 @@ import {
|
|||||||
type CompactInputSchemaPresentation,
|
type CompactInputSchemaPresentation,
|
||||||
} from "./contracts/compactInputSchema.js";
|
} from "./contracts/compactInputSchema.js";
|
||||||
import type { McpOutputSchemaProfile } from "./config/mcpOutputSchemaProfile.js";
|
import type { McpOutputSchemaProfile } from "./config/mcpOutputSchemaProfile.js";
|
||||||
import { RECORDED_CATALOG_DIGESTS } from "./recordedCatalogDigests.js";
|
import {
|
||||||
|
COMPACT_INPUT_SCHEMA_BUDGET_BYTES,
|
||||||
|
type McpInputSchemaProfile,
|
||||||
|
} from "./config/mcpInputSchemaProfile.js";
|
||||||
|
import { RECORDED_CATALOG_DIGEST_PROFILES } from "./recordedCatalogDigests.js";
|
||||||
|
|
||||||
const sortByName = (
|
const sortByName = (
|
||||||
contracts: readonly ToolContract[],
|
contracts: readonly ToolContract[],
|
||||||
@@ -34,10 +38,7 @@ const sortedToolContracts = sortByName(TOOL_CONTRACTS);
|
|||||||
* that predates the untrusted-content framing must not digest equal to one
|
* that predates the untrusted-content framing must not digest equal to one
|
||||||
* that emits `_meta.provenance`, or a stale process would report aligned.
|
* that emits `_meta.provenance`, or a stale process would report aligned.
|
||||||
*/
|
*/
|
||||||
const createToolCatalog = (
|
const createToolCatalog = (contracts: readonly ToolContract[]) =>
|
||||||
contracts: readonly ToolContract[],
|
|
||||||
compactPresentation: CompactInputSchemaPresentation | undefined,
|
|
||||||
) =>
|
|
||||||
contracts.map((contract) => ({
|
contracts.map((contract) => ({
|
||||||
name: contract.name,
|
name: contract.name,
|
||||||
title: contract.title,
|
title: contract.title,
|
||||||
@@ -46,15 +47,26 @@ const createToolCatalog = (
|
|||||||
effects: { ...contract.effects },
|
effects: { ...contract.effects },
|
||||||
returns_target_content: contract.returnsTargetContent,
|
returns_target_content: contract.returnsTargetContent,
|
||||||
annotations: contract.annotations,
|
annotations: contract.annotations,
|
||||||
input_schema: presentAdvertisedInputSchema(
|
input_schema: advertisedInputJsonSchema(contract),
|
||||||
advertisedInputJsonSchema(contract),
|
|
||||||
compactPresentation,
|
|
||||||
),
|
|
||||||
output_schema: toolOutputSchemaWithMetadata(contract)[
|
output_schema: toolOutputSchemaWithMetadata(contract)[
|
||||||
"~standard"
|
"~standard"
|
||||||
].jsonSchema.output({ target: "draft-2020-12" }),
|
].jsonSchema.output({ target: "draft-2020-12" }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const presentToolCatalog = (
|
||||||
|
catalog: ReturnType<typeof createToolCatalog>,
|
||||||
|
presentation: CompactInputSchemaPresentation | undefined,
|
||||||
|
) =>
|
||||||
|
presentation === undefined
|
||||||
|
? catalog
|
||||||
|
: catalog.map((tool) => ({
|
||||||
|
...tool,
|
||||||
|
input_schema: presentAdvertisedInputSchema(
|
||||||
|
tool.input_schema,
|
||||||
|
presentation,
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
const createPromptCatalog = (contracts: readonly PromptContract[]) =>
|
const createPromptCatalog = (contracts: readonly PromptContract[]) =>
|
||||||
contracts
|
contracts
|
||||||
.map((contract) => ({
|
.map((contract) => ({
|
||||||
@@ -76,22 +88,15 @@ const digest = (value: unknown): string => {
|
|||||||
return createHash("sha256").update(encoded).digest("hex");
|
return createHash("sha256").update(encoded).digest("hex");
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
const digestCatalogs = (
|
||||||
* Catalog digests over the given tool contracts. Exported so tests can prove
|
catalog: ReturnType<typeof createToolCatalog>,
|
||||||
* which contract fields the identity covers; production uses
|
prompts: ReturnType<typeof createPromptCatalog>,
|
||||||
* {@link CATALOG_IDENTITY}.
|
outputSchemaProfile: McpOutputSchemaProfile,
|
||||||
*/
|
|
||||||
export const createCatalogDigests = (
|
|
||||||
contracts: readonly ToolContract[] = TOOL_CONTRACTS,
|
|
||||||
promptContracts: readonly PromptContract[] = PROMPT_CONTRACTS,
|
|
||||||
compactPresentation: CompactInputSchemaPresentation | undefined = undefined,
|
|
||||||
outputSchemaProfile: McpOutputSchemaProfile = "full",
|
|
||||||
) => {
|
) => {
|
||||||
const tools = {
|
const tools = {
|
||||||
output_schema_profile: outputSchemaProfile,
|
output_schema_profile: outputSchemaProfile,
|
||||||
catalog: createToolCatalog(sortByName(contracts), compactPresentation),
|
catalog,
|
||||||
};
|
};
|
||||||
const prompts = createPromptCatalog(promptContracts);
|
|
||||||
return {
|
return {
|
||||||
tools_sha256: digest(tools),
|
tools_sha256: digest(tools),
|
||||||
prompts_sha256: digest(prompts),
|
prompts_sha256: digest(prompts),
|
||||||
@@ -103,7 +108,50 @@ export const createCatalogDigests = (
|
|||||||
} as const;
|
} as const;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CatalogDigests = ReturnType<typeof createCatalogDigests>;
|
/**
|
||||||
|
* Catalog digests over the given tool contracts. Exported so tests can prove
|
||||||
|
* which contract fields the identity covers; production uses
|
||||||
|
* {@link CATALOG_IDENTITY}.
|
||||||
|
*/
|
||||||
|
export const createCatalogDigests = (
|
||||||
|
contracts: readonly ToolContract[] = TOOL_CONTRACTS,
|
||||||
|
promptContracts: readonly PromptContract[] = PROMPT_CONTRACTS,
|
||||||
|
compactPresentation: CompactInputSchemaPresentation | undefined = undefined,
|
||||||
|
outputSchemaProfile: McpOutputSchemaProfile = "full",
|
||||||
|
) =>
|
||||||
|
digestCatalogs(
|
||||||
|
presentToolCatalog(
|
||||||
|
createToolCatalog(sortByName(contracts)),
|
||||||
|
compactPresentation,
|
||||||
|
),
|
||||||
|
createPromptCatalog(promptContracts),
|
||||||
|
outputSchemaProfile,
|
||||||
|
);
|
||||||
|
|
||||||
|
export type CatalogDigests = ReturnType<typeof digestCatalogs>;
|
||||||
|
export type CatalogDigestProfiles = Readonly<
|
||||||
|
Record<
|
||||||
|
McpInputSchemaProfile,
|
||||||
|
Readonly<Record<McpOutputSchemaProfile, CatalogDigests>>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
/** Build-time identities share schema conversion across the four supported profiles. */
|
||||||
|
export const createCatalogDigestProfiles = (
|
||||||
|
contracts: readonly ToolContract[] = TOOL_CONTRACTS,
|
||||||
|
promptContracts: readonly PromptContract[] = PROMPT_CONTRACTS,
|
||||||
|
): CatalogDigestProfiles => {
|
||||||
|
const full = createToolCatalog(sortByName(contracts));
|
||||||
|
const compact = presentToolCatalog(full, {
|
||||||
|
budgetBytes: COMPACT_INPUT_SCHEMA_BUDGET_BYTES,
|
||||||
|
});
|
||||||
|
const prompts = createPromptCatalog(promptContracts);
|
||||||
|
const outputProfiles = (catalog: typeof full) => ({
|
||||||
|
full: digestCatalogs(catalog, prompts, "full"),
|
||||||
|
off: digestCatalogs(catalog, prompts, "off"),
|
||||||
|
});
|
||||||
|
return { full: outputProfiles(full), compact: outputProfiles(compact) };
|
||||||
|
};
|
||||||
|
|
||||||
export const createCatalogIdentity = (
|
export const createCatalogIdentity = (
|
||||||
compactPresentation: CompactInputSchemaPresentation | undefined = undefined,
|
compactPresentation: CompactInputSchemaPresentation | undefined = undefined,
|
||||||
@@ -113,12 +161,18 @@ export const createCatalogIdentity = (
|
|||||||
compactPresentation === undefined
|
compactPresentation === undefined
|
||||||
? undefined
|
? undefined
|
||||||
: { budgetBytes: compactPresentation.budgetBytes };
|
: { budgetBytes: compactPresentation.budgetBytes };
|
||||||
// Building and canonicalizing every advertised schema dominates doctor and
|
// Only the exact built-in presentations have build-time identities. Source
|
||||||
// server startup, so the compiled runtime records the default digests once.
|
// runs and custom budgets still compute from their selected schemas lazily.
|
||||||
|
const inputProfile =
|
||||||
|
selectedPresentation === undefined
|
||||||
|
? "full"
|
||||||
|
: selectedPresentation.budgetBytes === COMPACT_INPUT_SCHEMA_BUDGET_BYTES
|
||||||
|
? "compact"
|
||||||
|
: undefined;
|
||||||
let catalogDigests: CatalogDigests | undefined =
|
let catalogDigests: CatalogDigests | undefined =
|
||||||
selectedPresentation === undefined && outputSchemaProfile === "full"
|
inputProfile === undefined
|
||||||
? RECORDED_CATALOG_DIGESTS
|
? undefined
|
||||||
: undefined;
|
: RECORDED_CATALOG_DIGEST_PROFILES?.[inputProfile][outputSchemaProfile];
|
||||||
return {
|
return {
|
||||||
counts: {
|
counts: {
|
||||||
cli_commands: CLI_COMMAND_NAMES.length,
|
cli_commands: CLI_COMMAND_NAMES.length,
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import type { CatalogDigests } from "./catalogIdentity.js";
|
import type { CatalogDigestProfiles } from "./catalogIdentity.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Digests of the default catalog (full input and output schemas), recorded
|
* Digests of the four built-in input/output schema profiles, recorded
|
||||||
* from the compiled contracts by `scripts/record-catalog-digests.mjs` after
|
* from the compiled contracts by `scripts/record-catalog-digests.mjs` after
|
||||||
* compilation. Source runs leave this undefined and compute them on first use.
|
* compilation. Source runs leave this undefined and compute them on first use.
|
||||||
*/
|
*/
|
||||||
export const RECORDED_CATALOG_DIGESTS: CatalogDigests | undefined = undefined;
|
export const RECORDED_CATALOG_DIGEST_PROFILES:
|
||||||
|
| CatalogDigestProfiles
|
||||||
|
| undefined = undefined;
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
import { Client } from "@modelcontextprotocol/client";
|
import { Client } from "@modelcontextprotocol/client";
|
||||||
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
||||||
|
import { execFile } from "node:child_process";
|
||||||
import { readFile, writeFile } from "node:fs/promises";
|
import { readFile, writeFile } from "node:fs/promises";
|
||||||
import { join, resolve } from "node:path";
|
import { join, resolve } from "node:path";
|
||||||
|
import { promisify } from "node:util";
|
||||||
|
|
||||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
@@ -22,6 +24,40 @@ import { MCP_STARTUP_POLICY } from "../../../src/mcpStartupPolicy.js";
|
|||||||
afterEach(() => vi.useRealTimers());
|
afterEach(() => vi.useRealTimers());
|
||||||
|
|
||||||
describe("production MCP doctor", () => {
|
describe("production MCP doctor", () => {
|
||||||
|
it("reuses immutable compiled profile digests and preserves custom-budget identity", async () => {
|
||||||
|
// Exercise the generated module with Node, outside Vitest's source loader.
|
||||||
|
await promisify(execFile)(
|
||||||
|
process.execPath,
|
||||||
|
[
|
||||||
|
"--input-type=module",
|
||||||
|
"--eval",
|
||||||
|
`
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { createCatalogIdentity, createCatalogDigests } from "./dist/catalogIdentity.js";
|
||||||
|
import { RECORDED_CATALOG_DIGEST_PROFILES as profiles } from "./dist/recordedCatalogDigests.js";
|
||||||
|
import { COMPACT_INPUT_SCHEMA_BUDGET_BYTES as budgetBytes } from "./dist/config/mcpInputSchemaProfile.js";
|
||||||
|
assert.ok(Object.isFrozen(profiles));
|
||||||
|
for (const input of ["full", "compact"]) {
|
||||||
|
assert.ok(Object.isFrozen(profiles[input]));
|
||||||
|
for (const output of ["full", "off"]) {
|
||||||
|
const identity = createCatalogIdentity(input === "compact" ? { budgetBytes } : undefined, output);
|
||||||
|
assert.equal(identity.digests, profiles[input][output]);
|
||||||
|
assert.ok(Object.isFrozen(identity.digests));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const selection = { budgetBytes: 1 };
|
||||||
|
const custom = createCatalogIdentity(selection, "off");
|
||||||
|
selection.budgetBytes = budgetBytes;
|
||||||
|
const expected = createCatalogDigests(undefined, undefined, { budgetBytes: 1 }, "off");
|
||||||
|
assert.deepEqual(custom.digests, expected);
|
||||||
|
assert.notEqual(custom.digests.tools_sha256, profiles.compact.off.tools_sha256);
|
||||||
|
assert.equal(custom.digests, custom.digests);
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
{ timeout: 30_000 },
|
||||||
|
);
|
||||||
|
}, 35_000);
|
||||||
|
|
||||||
it("preserves the full-output envelope for startup failures", async () => {
|
it("preserves the full-output envelope for startup failures", async () => {
|
||||||
const result = await runProductionMcpDoctorCli(
|
const result = await runProductionMcpDoctorCli(
|
||||||
["--json", "--full-output"],
|
["--json", "--full-output"],
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|||||||
import { machoImage } from "../../../src/artifacts/apple/MachoImage.fixture.js";
|
import { machoImage } from "../../../src/artifacts/apple/MachoImage.fixture.js";
|
||||||
import {
|
import {
|
||||||
CATALOG_IDENTITY,
|
CATALOG_IDENTITY,
|
||||||
|
createCatalogDigestProfiles,
|
||||||
createCatalogDigests,
|
createCatalogDigests,
|
||||||
} from "../../../src/catalogIdentity.js";
|
} from "../../../src/catalogIdentity.js";
|
||||||
import { CLI_COMMAND_NAMES } from "../../../src/cliCommandNames.js";
|
import { CLI_COMMAND_NAMES } from "../../../src/cliCommandNames.js";
|
||||||
@@ -141,17 +142,7 @@ describe("server and catalog identity", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("binds output schema profile and canonical output contracts into identity", () => {
|
it("binds output schema profile and canonical output contracts into identity", () => {
|
||||||
const full = createCatalogDigests();
|
const profiles = createCatalogDigestProfiles();
|
||||||
const off = createCatalogDigests(
|
|
||||||
TOOL_CONTRACTS,
|
|
||||||
PROMPT_CONTRACTS,
|
|
||||||
undefined,
|
|
||||||
"off",
|
|
||||||
);
|
|
||||||
expect(off.tools_sha256).not.toBe(full.tools_sha256);
|
|
||||||
expect(off.combined_sha256).not.toBe(full.combined_sha256);
|
|
||||||
expect(off.prompts_sha256).toBe(full.prompts_sha256);
|
|
||||||
|
|
||||||
const changedOutput = TOOL_CONTRACTS.map((contract, index) =>
|
const changedOutput = TOOL_CONTRACTS.map((contract, index) =>
|
||||||
index === 0
|
index === 0
|
||||||
? {
|
? {
|
||||||
@@ -160,17 +151,24 @@ describe("server and catalog identity", () => {
|
|||||||
}
|
}
|
||||||
: contract,
|
: contract,
|
||||||
);
|
);
|
||||||
const changedFull = createCatalogDigests(changedOutput);
|
const changed = createCatalogDigestProfiles(changedOutput);
|
||||||
const changedOff = createCatalogDigests(
|
for (const input of ["full", "compact"] as const) {
|
||||||
changedOutput,
|
const { full, off } = profiles[input];
|
||||||
PROMPT_CONTRACTS,
|
expect(off.tools_sha256).not.toBe(full.tools_sha256);
|
||||||
undefined,
|
expect(off.combined_sha256).not.toBe(full.combined_sha256);
|
||||||
"off",
|
expect(off.prompts_sha256).toBe(full.prompts_sha256);
|
||||||
);
|
for (const output of ["full", "off"] as const) {
|
||||||
expect(changedFull.tools_sha256).not.toBe(full.tools_sha256);
|
expect(changed[input][output].tools_sha256).not.toBe(
|
||||||
expect(changedOff.tools_sha256).not.toBe(off.tools_sha256);
|
profiles[input][output].tools_sha256,
|
||||||
expect(changedFull.combined_sha256).not.toBe(full.combined_sha256);
|
);
|
||||||
expect(changedOff.combined_sha256).not.toBe(off.combined_sha256);
|
expect(changed[input][output].combined_sha256).not.toBe(
|
||||||
|
profiles[input][output].combined_sha256,
|
||||||
|
);
|
||||||
|
expect(changed[input][output].prompts_sha256).toBe(
|
||||||
|
profiles[input][output].prompts_sha256,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("changes catalog identity when advertised input examples change", () => {
|
it("changes catalog identity when advertised input examples change", () => {
|
||||||
|
|||||||
Reference in new issue
Block a user