Skip to main content
Clousight Bench 对云产品的运行时工程能力进行基准测试,而非模型智能。 其核心思想是:不同云产品的负载差异悬殊,但流水线完全相同。

生命周期(所有领域共用)

12 个阶段,4 个相位。相位是读懂这台机器的方式,阶段是它下面的失败归因细节。
MEASURE 与 CONCLUDE 之间那条线就是整个信任故事,而且它由函数签名而非约定来保证: task.score() 只接受 ObservationBundle,adapter 和 target 在类型上就够不到判定。 凡是云能影响的,都发生在这条线以上。 各阶段依次为:
  • RESOLVE — 根据 RunSpec 查找 DomainPack、任务和适配器。 不写入 run.stages:RESOLVE 失败根本不会产生记录,所以”RESOLVE: ok”在每条记录里都是常量。
  • VALIDATE — 解析并校验 RunSpec、目标、参数和任务配置(core/validation.py)。RESOLVE 和 VALIDATE 失败均属 UserInputError:CLI 退出码为 2,不写入任何记录。
  • DESCRIBE — 依据插件的声明(workload_identity、provenance、environment_facts)组装本次运行的 identity、environment 与三个指纹。它横跨 preflight 闸门:需要活适配器才能取到的 facts 要等 PREFLIGHT 通过之后才收集,因此 DESCRIBE 只在最后记录一次。插件在这里崩溃会得到 invalid 记录,且不会制备任何资源。(0.6.0 之前这些失败挂在 VALIDATE 名下,导致记录出现”VALIDATE failed、PREFLIGHT ok”这种读不通的组合。)
  • PREFLIGHT — adapter.preflight(task):在制备之前检查凭证、SDK、连通性以及本次基准测试在该云上所需的最低权限。CRITICAL 级失败会生成一条 invalid 记录,且永远不会进入 SETUP。可通过 --skip-preflight 跳过;可使用 csbench doctor 单独运行。
  • SETUP — adapter.setup():通过 Terraform 制备资源,或通过 SDK/HTTP 建立连接。setup() 与 teardown() 都是可选的 no-op 钩子——“创建 → 接入 → 销毁”三段可分离,纯接入运行(经 target.endpoint / credentials_ref 配置接入一个已运行的服务)只用”接入”这一段。一次运行是否制备是显式的适配器能力 provisions_resources()(默认:真实云的 live 运行;*-endpoint 配置接入适配器与模拟器为 False,或继承 ProvisionedCloudAdapter 恒为 True)。制备云机器——live 确认门、成本预算/账本、资源回收(reaper)——仅在 provisions_resources() 为 True 时运行;纯接入运行全部跳过。
  • EXECUTE — task.execute(adapter, params):驱动负载,返回仅含原始证据的 ObservationBundle。
  • SEAL — core/observation.py::seal():验证 bundle 格式完整且可进行规范化编码。它不从云上取任何东西——bundle 是 EXECUTE 已经返回的;这里是打分前的封存。它自成一个阶段,是为了让”套件跑崩了”和”套件返回了编不出来的东西”成为两种可归因的失败。0.6.0 之前叫 COLLECT,旧名仍保留在 STAGES 中,因此 0.5.x 写下的记录照样能读。
  • SCORE — task.score(bundle):纯函数,生成测量值和发现。评分器失败时保留观测值,并记录一条 SCORE 错误。
  • ENRICH — 已安装的各 ResultEnricher 相互隔离运行:失败仅记录为 ENRICH 阶段错误,不会改变 status。
  • PERSIST — core/store.py:写临时文件、刷盘、fsync、原子重命名;当结果目录不可写时,会将紧急转储写入系统临时目录(路径会被打印出来)。
  • PUBLISH — 默认关闭,需注入 ResultPublisher 才生效。在 PERSIST 之后运行,写入仅追加的回执;永远不会改写核心记录。
TEARDOWN 不在上述流程步骤之列。 它是围绕 SETUP → SEAL 的强制性 finally 边界:一旦进入 SETUP,adapter.teardown() 必然执行,包括 setup() 中途失败的情况;teardown 失败会被记录为独立的阶段错误,不会覆盖导致失败的 execute 或 collect 错误。 PREPARE 与 CONNECT 之间还有两道闸门,它们不是独立阶段——live 运行确认(--allow-live)与成本预算(--cost-budget)。两者都在制备任何资源之前拒绝,表现形式也相同:SETUP: skipped、状态 invalid,外加一条 critical 发现,其 details.remediation 写明该怎么做。csbench run 会把这一行打到 stderr,因此被拦下的运行不必去读 stdout 上的 JSON 就能自我解释。

结果契约(schema 0.4)

顶层字段固定为:schema_version、run、identity、environment、fingerprints、measurements、findings、observations、series、artifacts、items、extensions、errors、status。
  • items(schema 0.4,可选)是逐项基座:一组 ItemResult(item_id、group、input/output/reference、逐项 scores 带 4 态 status ∈ ok·fail·skip·error、usage)。标量 measurements 是它们的聚合(core/aggregate.py——mean/ratio/geomean/百分位 + Wilson/正态置信区间 + 按 group 切片)。尚未迁移到逐项打分的套件为空。由 CSBENCH_MAX_PERSISTED_ITEMS(默认 1000)封顶;截断记录在 extensions.core.items_meta,绝不静默。
  • status ∈ completed · failed · invalid · unsupported——这是 execute() 会返回的全部取值。还有第五个值 interrupted,只属于 Ctrl-C:teardown 照常执行、记录照常落盘,随后 KeyboardInterrupt 被重新抛出,因此这个状态只会出现在磁盘上,不会作为返回值出现。不存在布尔型 ok、顶层 metrics、顶层 evidence_layer,也没有 config_hash。
  • environment.execution ∈ simulated · live · unknown,标记数据来自模拟运行时还是真实云端。该字段被折叠进环境指纹,因此模拟结果与真实结果永远不会混入同一分析池。
  • 每条测量值携带 value、unit 和 official,可选字段为 reproducibility_class、aggregation、sample_count、notes 和 ci。
  • 判定型指标(reproducibility_class="judge-based")通过判定基座(core/judge.py)落地:JudgeModel(配置接入的 EndpointJudge,带 SSRF 校验)被要求给出分类判定,再由固定算术映射为分数——刻意拒绝 G-Eval 不可复现的 top-logprob 加权。judge_emit 从任意判定模型取得结构化输出(原生 JSON-schema 模式,否则 prompt + 花括号切片/尾逗号修复)。response-quality 指标是参考实现:带可选自一致性的 rubric 判定;未配置判定模型时干净地 skip(因此 CI 从不调用真实判定模型),并在每条逐项分数中记录判定模型 id 与判定结果。通过”把指标 opt-in + 配置接入一个判定模型”来运行:params: {extra_metrics: [response_quality], judge: {provider: openai-compatible, endpoint: ..., model: ..., credentials_ref: env:KEY, cache: .judge_cache.json}}——配置了判定模型的运行会在打分阶段做网络 I/O,按设计不可离线重打分。config 里给 cache 路径会用内容寻址的 CachingJudge 包裹判定模型,重跑复用判定、不再重复付费 LLM 调用(只缓存判定打分,绝不缓存 environmental 数值)。
  • Golden ↔ 已执行 拆分:benchmark spec = 版本化的 DatasetHandle(version + digest,在库固定)+ 每条 item 的 reference(golden);运行的 output 是已执行侧。没有单独的 Golden 子系统——逐项基座已同时承载两者。
  • 每条发现携带稳定的 code、severity、summary 和 details。
  • 每条阶段错误携带 stage、code、type、message 和 retryable。堆栈跟踪永远不存入记录;csbench run --debug 会将其写入 <results>/debug/<run_id>.log。
  • 所有摘要均为对规范 JSON 编码的完整 SHA-256(core/canonical.py):UTF-8、键排序、无多余空白,NaN/Infinity 被拒绝。
  • extensions["core"] 为核心保留;插件在自己的命名空间下写入(例如 extensions["cb-pricing"])。
Schema 1.0 记录不再受支持。请重新运行基准测试以生成当前的 0.4 记录。

运行计划与统计(Phase 1C)

单一数字不构成测量。csbench run --repeat N --warmup W(ops/runplan.py)将同一 RunSpec 经由上述生命周期运行 warmup + repeat 次——每次运行仍为独立的带摘要 0.4 记录——随后:
  • 丢弃 warmup 次运行(冷启动 / JIT / 缓存效应不代表你要发布的稳态),并在每条记录的 extensions["core"]["run_plan"] 下标注其角色,使选择可审计、永远不成为指纹;
  • 将正式运行的结果每个测量项汇聚为一个分布(core/statistics.py):数值型 → n / mean / stdev / min / max / p50 / p95 / cv,标签型 → 分布 / mode / agreement;
  • 将 run_plan_aggregate(含独立 SHA-256 摘要)写入 results/aggregates/…,报告加载器将其识别为记录汇总而跳过。
可比性经过校验,而非假定。 只有 benchmark 和 environment 指纹均匹配的两次运行才会合并。若某计划的 benchmark 或环境在运行中途发生变化,则只对最大的自洽子组做汇聚,并明确说明;csbench query 和 csbench rollup 暴露了指纹信息,使不可比(或仅在代码变更前提下可比)的情况一目了然。只有 completed / unsupported 的运行会贡献数值——failed 的运行会被计数,但没有可汇聚的结论。 Phase 1C 本身不包含插件 API 版本范围、JSON Schema、合规套件或负载沙箱——这些属于 Phase 1D,现已在开放核心中发布(插件 API 版本范围 + 冲突检测、RunSpec / ResultRecord / manifest 的 JSON Schema、csbench conformance,以及负载沙箱第 1+2 层;详见 ROADMAP.md / CHANGELOG.md)。Phase 1C 仅对标量 measurements 做汇聚,不含时间序列。

分层结构

插件契约

内置包与第三方包(包括闭源商业包)的加载方式完全相同——安装一个 Python 包或放入一个负载目录即可。对接真实云的领域包需要注册一个 RuntimeProvider(以及可选的 CampaignProbeHook 和 ResourceReaper)。开放核心定义这些抽象并现已附带参考实现——Aliyun AgentRun 和 AWS AgentCore 的 RuntimeProvider 及 ResourceReaper 均在源码树内注册(pyproject.toml),因此仅凭开放核心即可复现真实云路径。该接缝对第三方 / 商业 provider 以相同方式注册保持开放。

控制平面与数据平面

execute(接触云端)/ score(纯函数)的拆分同时也是控制平面 / 数据平面的拆分。AgentRuntimeAdapter 额外暴露一个接缝:run_data_plane_probe(name, params) -> ObservationBundle(domains/agent_runtime/adapters/base.py)——延迟类”数据平面”任务的 execute() 简化为 return adapter.run_data_plane_probe("<probe>", {...}),由此由适配器而非任务决定测量在何处运行。基础适配器将请求分发到进程内 packer 注册表(domains/agent_runtime/dataplane_dispatch.py),这正是 local-sim 和所有尚未接线的云所使用的路径。已接线的云可以改写此接缝,将整个测量发送到目标区域内运行的负载探针,使运营商的网络和系统代理不影响测量数值,同时返回相同的 ObservationBundle 供评分。score() 在两种路径下均无需改动。run-plan campaign 的探针生命周期由可选的 CampaignProbeHook 驱动(在任务循环的 try/finally 中启动、同步并回收;默认 --probe local 不触碰此路径)。开放核心定义该接缝和 hook 契约,并在源码树内附带 Aliyun ECI 探针 carrier 及其云传输层的参考实现;其他 carrier(其他云、第三方或商业)以相同方式注册。

证据层

A 文档 · B 环境观测 · C 受控测量 · D 市场宣传。 报告永远不将多个维度合并为单一分数。

Suite / Evaluator 契约层

除领域-任务流水线外,Clousight Bench 还为外部定义的基准套件(如 SWE-bench)提供第二套契约:
  • BenchmarkSuite 原封不动地驱动上游 harness,并返回不透明的 RawArtifacts(一个目录 + 命名文件的 manifest)。核心将 artifacts 视为黑盒;只有配对的 evaluator 才理解其内容。
  • Evaluator 以纯函数方式(无云、无凭证)读取 RawArtifacts,返回 dict[str, Measurement],其中每个 key 均以 "<suite_id>.<metric_name>" 命名空间(官方 evaluator)或 "<evaluator_id>.<metric_name>" 命名空间(自定义 evaluator)。
  • 命名空间 / official 不变量:conformance.check_evaluator(evaluator, suite_id, measurements) 验证官方 evaluator 仅在套件命名空间下发出 official=True 的测量值,自定义 evaluator 仅在自身 id 下发出 official=False 的测量值,且自定义 evaluator 不得抢注已注册套件的命名空间。返回 list[CheckResult];CLI 侧可用 csbench conformance --suite <suite_id> 对套件的 mock 工件跑全部已注册 evaluator,也可与 run_conformance 组合用于 CI 门控。
  • SuiteRunner + Provenance(内部执行器,不是插件契约):将溯源元数据(suite_id、suite_version、evaluator_id、unmodified 标志)线程化传递到每个 TaskResult,并折叠进基准指纹,确保来自不同套件版本或 evaluator 的记录永远不会混入同一分析池。
  • SWE-bench 试点(切片 1):SweBenchSuite(注册入口点 swe-bench)+ OfficialSweEvaluator(发出 swe-bench.resolved 和 swe-bench.cost_per_resolved)+ 内置 fixtures(支持离线 / CI 使用)。真实 Docker 支持的 run() 路径需要 [swebench] 可选包,并由 @pytest.mark.slow 门控。
  • SWE-bench Lite(变体):300 实例的精选子集,以 SweBenchLiteSuite(入口点 swe-bench-lite)+ OfficialSweLiteEvaluator(发出 swe-bench-lite.resolved / swe-bench-lite.cost_per_resolved)提供。它是旗舰的薄子类——harness、报告结构、agent-runtime 接线完全相同,仅数据集固定版本(princeton-nlp/SWE-bench_Lite)、内置真实 fixtures 与命名空间不同。这正是未来变体(Multimodal)复用的参数化接缝:变体只需覆盖 suite_id / suite_version / fixtures_dir / dataset_name 类属性,其余全部继承。
  • SWE-bench Multimodal(变体):来自真实 JavaScript / 前端可视化仓库的图像增强任务,以 SweBenchMultimodalSuite(入口点 swe-bench-multimodal)+ OfficialSweMultimodalEvaluator(发出 swe-bench-multimodal.resolved / .cost_per_resolved)提供。与 Lite 相同的薄子类接缝,外加第 7 个 fixture 字段 image_assets(图像 URL),由 _load_instance 透传给 agent。它刻意绑定 dev split:510 实例的 test 榜单 split 的 gold patch 是隐藏的(经托管 sb-cli 服务评分),而 102 实例的 dev split 带真实 gold patch、可本地 Docker 运行——与 Verified/Lite 一致。接入托管 test-split 路径是已记录的未来(受门控)增项。

当前领域

  • agent-runtime — 会话、工具调用、故障恢复、可观测性、成本、隔离。所有任务均在 local-sim 上运行;完整任务列表和适配器状态由下方注册表生成(从不手动维护——见”文档维护”)。其覆盖范围包括制备、运行时行为、工具注册、可观测性、成本和租户隔离。适配器采用 managed/transport/mode 拆分,同一套代码既能驱动本地模拟运行时,也能在安装 runtime-provider 插件后驱动真实云;延迟类任务通过 run_data_plane_probe 接缝路由(见”控制平面与数据平面”);能力探针触发 CapabilityNotSupported → 记录为一条发现,不会崩溃。

任务与适配器清单

Benchmarks — 10 suites

agent-runtime

Adapters: aliyun-agentrun experimental · aws-agentcore skeleton · huawei-agentarts skeleton · local-sim reference · volcengine-agentkit skeleton

data-warehouse

Adapters: duckdb-local reference

key-value

Adapters: ycsb-endpoint experimental · ycsb-local reference

llm

Adapters: llm-endpoint experimental · llm-mock reference

transactional-db

Adapters: benchbase-local reference · jdbc-endpoint experimental

开发者预览就绪状态

  • reference 和 wired 适配器可以执行。
  • experimental 适配器可在预览注意事项下执行。
  • skeleton 适配器可被发现,但在 preflight 之前会被拒绝。
  • 五个领域各自带有一个可运行的参考适配器:local-sim、duckdb-local、ycsb-local、benchbase-local 和 llm-mock。Aliyun AgentRun(及 AWS AgentCore)的 RuntimeProvider 已在源码树内注册。aliyun-agentrun 适配器为 experimental:在 mode: mock 下可端到端运行,其 live 路径已完成一次真实云 campaign(cn-hangzhou,2026-08-15——25 个 completed + 2 个诚实的 unsupported)。该适配器尚未晋升为 wired(该状态保留给经过稳定、多次验证的 live 路径);AWS AgentCore 及其他云仍为 skeleton。
  • 内置负载位于 clousight_bench.resources.workloads,通过 core.resources.reference_workload_path() 解析,因此 wheel 安装和可编辑安装使用相同的文件。
Phase 1B 发布了 ResultRecord schema 0.4(见上文”结果契约”)。插件 API 现为 3.0(OTel 原生追踪的破坏性变更;注册表拒绝声明 2.x 范围的插件)。 本仓库为公开仓库,采用 Apache-2.0 许可;包含完整的开放核心,包括可复现机制——Aliyun AgentRun RuntimeProvider、ECI 探针 carrier、ResourceReaper、Terraform 以及种子 pricing enricher。护城河在于数据与服务,而非私藏代码。独立的私有仓库 clousight-bench-pro 仅包含:
  • cb-pricing — 更完整 / 更新鲜的私有价格数据源,由开放 pricing enricher 通过 CLOUSIGHT_PRICING_DATA 环境变量消费(非入口点);
  • cb-dataservice — 令牌门控的私有 / 留出数据集,通过 clousight_bench.asset_resolvers 入口点注册为 PrivateAssetResolver,以及托管对象存储上传(占位符);
  • cb-adapters-enterprise — 空占位符,用于未来的托管 SaaS 和私有云 / 国产栈适配器。
开放核心不导入、不依赖、也不因缺少上述组件而降级。

凭证与入门引导(便捷层)

原则:永远不要求用户为基准测试单独生成一套密钥——复用云 provider 自身的默认凭证链。
  • core/credentials.py::resolve_credentials(target, platform) 仅探测凭证来源,从不读取或存储密钥值。解析顺序:auth_env(逃生舱——显式命名的环境变量)→ profile(命名 CLI profile)→ 标准环境变量 → 凭证文件。返回 CredentialResolution(ok, source, identity_hint, remediation);identity_hint 仅包含变量名或 profile 名,从不包含密钥材料。
  • ProviderAdapter.resolve_credentials() 委托给上述解析器(跨领域;provider 从 target.provider 或平台名前缀推断,例如 aliyun-agentrun → aliyun)。真实适配器运行时仍将凭证解析交由官方 SDK 的默认链处理。
  • 每个 provider 的凭证链注册于 PROVIDER_CREDENTIALS(aws / aliyun / huawei / volcengine:标准环境变量、profile 环境变量、凭证文件、SDK 模块、文档链接)。
  • CLI:csbench init <provider> 生成私有 *.local.yaml + .env.example 并写入 .gitignore(配置不含密钥);csbench doctor --config x 执行逐步健康检查(provider → SDK 可导入?→ 凭证链可解析?→ mock_base_url 可达?localhost 立即失败),并为配置接入(config-connect)运行追加目标连通性探测:endpoint 的 TCP 可达性、Redis RESP PING,以及 java -version 门槛(BenchBase 需要 Java ≥ 17、YCSB ≥ 11)——全部带 SSRF 守护;mock 目标跳过这些探测。每一步都提供可操作的修复提示。
PREFLIGHT 阶段:上述检查不仅是独立命令——它们也是一个生命周期阶段。core/preflight.py 提供 Check / PreflightReport 和可复用的检查函数(credential_check / sdk_check / mock_reachable_check);doctor 和编排器共享相同的函数(单一事实来源)。
  • ProviderAdapter.preflight() -> PreflightReport:默认验证凭证 + provider SDK。可跨领域使用。
  • AgentRuntimeAdapter.preflight(task):在 super() 基础上,为真实云平台(非空 provider)追加 mock_base_url 可达性检查 + check_permissions(task)。local-sim(空 provider,自托管 mock)跳过两者,始终通过。
  • 编排器在 RESOLVE 之后、SETUP 之前运行 adapter.preflight(task);任何 CRITICAL 失败触发提前退出(不制备):记录会得到一条 StageError(stage="PREFLIGHT", code="preflight_failed"),外加一条 Finding(code="core.preflight_failed", severity="critical")——其 details.checks 列出每一行检查——且记录的 status 为 invalid。--skip-preflight 禁用此门控。

最小权限:(基准测试 × 云)矩阵

给定基准测试所需的最低权限因云 provider 而异,因此权限验证按任务映射,职责分属两侧:
  • 基准声明 WHAT:suite 的 required_permissions: tuple[str, ...] 列出抽象能力令牌(与云无关)。令牌在 domains/agent_runtime/permissions.py 中定义:session:create / session:state / tool:invoke / tool:register / trace:read / trace:export。
  • 适配器说明 HOW + 验证:每个真实云适配器定义 PERMISSION_MAP(令牌 → 该云具体的最低 IAM/RAM 操作)。required_actions(task) 将任务的令牌解析为云特定的操作集;_probe_permissions(actions) 执行实际的授权检查(默认实现返回 None = 未验证 → 发出 WARNING,列出本次基准测试在该云上所需的最低操作;真实适配器覆盖此方法,调用 STS GetCallerIdentity / RAM policy 模拟 / dry-run,返回 (ok, missing)——任何缺失操作均为 CRITICAL 阻断)。
给定运行的最低权限等于适配器对任务令牌的映射。新增一个基准测试维度只需在任务上声明令牌;新增一个云只需在适配器上提供 PERMISSION_MAP——两侧完全解耦。csbench doctor --domain <d> --platform <p> --task <t> 可直接打印任意(基准测试 × 云)组合的最低操作列表。

数据集分发(三级,单一解析器)

基准测试不只是代码——它还包含资产(数据集、语料库、留出判分键)。方法论公开,数据分级,判分键私有。所有资产均由单一解析器提供;开放/私有边界纯粹取决于配置:
  • manifest 中的 assets: 段(负载 / 任务):
  • core/assets.py:AssetSpec + resolve_asset(spec, base_dir, cache_dir, private_resolver);WorkloadEngine.resolve_assets() 在运行前解析所有资产,并通过 params["assets"] 将 {name: local_path} 暴露给负载。
  • 可复现且不泄露密钥:describe() 将每个资产的 identity()(name@version + sha256)折叠进 config_hash——只存储指纹,永远不存储内容;判分键内容不进入记录。
  • 判分键抗污染:任务的方法论(如何评分)可以开源,而其留出键值声明为 source: private——“如何评分”公开,“答案键”私有,天然防止基准测试泄露。
  • 扩展点:私有解析器实现 PrivateAssetResolver(name + resolve(spec, cache_dir))并通过 clousight_bench.asset_resolvers 注册;开放核心不提供实现。clousight-bench-pro 的 cb-dataservice 组件提供 DataServiceAssetResolver(CLOUSIGHT_BENCH_TOKEN 认证 + sha256 验证)。

数据契约与扩展点

ResultRecord 携带三个相互独立、互不覆盖的通道;消费者按需读取:
  • measurements(标量分数)——报告层用于汇聚和比较的数值(不存在顶层 metrics 字段)。
  • series(时间序列,{name: [[t, value], ...]})——高频采样,如每秒延迟或 GPU 利用率。
  • artifacts({"kind", "path"/"uri", "media", "sha256"} 指针)——大文件,如 OTel 追踪和日志包;record.json 中只存储指纹,不存储内容。
负载协议(WorkloadEngine stdout JSONL)在现有 metric/log/result 事件基础上新增两种事件类型,相互不干扰:
sample 事件按序列名累积进 WorkloadResult.series;artifact 事件的 sha256 由引擎从 workload_dir/path 的文件内容计算——负载本身无需哈希任何内容。 持久化:record.json 保持其历史路径 results/<domain>/<platform>/<task_id>-<run_id>.json 不变(core/store.py::ResultStore 负责此职责;orchestrator._persist 委托给它,签名稳定)。当可选的 [store] 扩展(duckdb + pyarrow)已安装且记录含有 series 数据时,序列会被外部化为运行目录下的 series.parquet 宽表,record.json 中的 series 字段被改写为指针 {"$parquet": "<relative_path>"}。若未安装该扩展,序列将内嵌于 record.json(小数据量下无损)。 Parquet 宽表列(cb-dataservice 和 SaaS 网页前端消费的稳定握手):
unit 列约定:ResultStore 写入 Parquet 时,从 record.measurements[<name>].unit 读取每个序列 <name> 的单位字符串——即与序列同名的测量值(例如 latency_ms 序列的单位取自 latency_ms 测量值);当不存在同名测量值时,该列为空字符串 ""。这是隐式约定,不强制执行——省略该字段仍可持久化行;unit 列仅为空。 ResultStore.query_series(sql=None, glob="**/series.parquet") 通过 DuckDB 直接对 results_dir 下所有 Parquet 文件运行 SQL;glob 路径作为绑定参数传给 read_parquet(?)(无字符串拼接);当 [store] 扩展缺失时抛出 ImportError。 扩展点:clousight_bench.enrichers 入口点组托管 ResultEnricher 子类——name: str + enrich(self, record: ResultRecord) -> ResultRecord。orchestrator.execute(spec, results_dir=None, enrich=True, preflight=True, publisher=None, …)(publisher= 关键字参数为 PUBLISH 阶段注入可选的 ResultPublisher)在记录构建完成后、_persist 之前依次调用它们,顺序由 registry.load_enrichers()(按 name 排序以确保确定性执行顺序)返回的列表决定。核心不提供任何 enricher 实现(如成本估算)——商业插件通过入口点注入;csbench run --no-enrich 跳过整个链路。 插件兼容性契约:clousight_bench.PLUGIN_API_VERSION = "3.1"(SemVer)。只有当 schema 字段、入口点组名称或 ResultEnricher/ResultStore 签名发生不兼容变更时,MAJOR 才会递增。包版本与插件 API 版本是两个独立维度:clousight_bench.__version__(当前为 0.7.0)随每次发布递增;PLUGIN_API_VERSION 仅在插件面向接口有破坏性变更时移动——两者不同步演进。Phase 1A 商业插件的 pyproject.toml 针对当前包版本固定为 clousight-bench>=0.7,<0.8(早期设计文档中出现的 >=1.0,<2.0 形式是针对 PLUGIN_API_VERSION 大版本的目标状态草稿,在 0.2 开发者预览发布时未更新;此处已更正)。 Pro 的三个扩展边界(由 clousight-bench-pro 通过入口点注入;开放核心不提供实现):

文档维护

本文档的一部分由脚本生成,其余部分需要你手动与行为变更同步——在同一次变更中更新。
  • 生成块位于 {/* BEGIN generated:… */} / {/* END generated:… */} 标记之间(目前为基准套件与适配器清单)。它们由领域注册表渲染——与 csbench list --json 的数据来源相同——通过 scripts/gen_docs.py 生成。永远不要手动编辑标记内的内容。新增/重命名基准套件或更改适配器状态后,运行 python scripts/gen_docs.py 并提交结果。CI 会运行 python scripts/gen_docs.py --check 和 tests/test_docs_inventory.py,因此过时的块(手写的”28 tasks”与注册表不符)会导致构建失败,而不会被发布。
  • 散文段落(标记之外的所有内容)是行为变更完成定义的一部分:当某个任务的测量形状、适配器契约或生命周期规则发生变化时,在同一 PR 中更新描述它的段落。比文档落后一个版本更糟糕的是没有文档——审阅者会停止信任它。每次编辑应尽量小而聚焦;生成块吸收机械性事实,散文只需承载意图。