diff --git a/README.md b/README.md index 1df4a8e..c4a9388 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ WaveBench 是一个用 Python 编写的实验室自动测量台,面向电子设计竞赛调试和日常实验。它把仪器控制、实验步骤和采集证据放在同一条命令链中,支持先离线检查 plan,再决定是否连接硬件。 -当前仓库开发线为 `0.8.23`,最新稳定 tag 为 `v0.8.0`。不同版本的命令和能力可能不同,以对应 tag 中的文档为准。 +当前仓库开发线为 `0.8.24`,最新稳定 tag 为 `v0.8.0`。不同版本的命令和能力可能不同,以对应 tag 中的文档为准。 ## 🌟 特别鸣谢 diff --git a/docs/README.md b/docs/README.md index 3971f68..11d2f06 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,7 @@ [English](README_EN.md) · 中文 -WaveBench 是一个用 Python 编写的实验室自动测量台,提供 CLI、实验性 TUI、显式 run plan、采集包和离线报告。当前开发线为 `0.8.22`,最新稳定 tag 为 `v0.8.0`。版本变化见 [更新日志](../CHANGELOG.md);旧版本原始文档可切换到对应 Git tag 查看。 +WaveBench 是一个用 Python 编写的实验室自动测量台,提供 CLI、实验性 TUI、显式 run plan、采集包和离线报告。当前开发线为 `0.8.24`,最新稳定 tag 为 `v0.8.0`。版本变化见 [更新日志](../CHANGELOG.md);旧版本原始文档可切换到对应 Git tag 查看。 > [!WARNING] > 部分命令会连接并控制真实仪器。示例会区分离线检查、连接读取和硬件写入;执行写入前,应确认接线和限制值。 diff --git a/docs/README_EN.md b/docs/README_EN.md index 6f322f9..d379500 100644 --- a/docs/README_EN.md +++ b/docs/README_EN.md @@ -2,7 +2,7 @@ [中文文档](README.md) · English -WaveBench is a Python measurement bench for laboratory debugging. It combines explicit instrument commands, run plans, capture packages, and offline reports. It requires Python 3.11 or newer. The current development line is `0.8.22`; the latest stable tag is `v0.8.0`. +WaveBench is a Python measurement bench for laboratory debugging. It combines explicit instrument commands, run plans, capture packages, and offline reports. It requires Python 3.11 or newer. The current development line is `0.8.24`; the latest stable tag is `v0.8.0`. > [!WARNING] > Some commands connect to and change real instruments. Check wiring, input impedance, output state, and voltage/current limits before running a hardware action. diff --git a/docs/project/README.md b/docs/project/README.md index fb316ec..721c94f 100644 --- a/docs/project/README.md +++ b/docs/project/README.md @@ -28,6 +28,9 @@ ## rfcs:接口提案与决策 - [RFC 索引](rfcs/README.md) +- [Source V2 能力、状态与复合输出安全 RFC](rfcs/WaveBench_source能力状态与复合输出安全RFC.md): + `Accepted R6`;核心 `0.8.24` 开发线已实现 P0、M1–M4、M4.5、C1、M5-A 至 M5-D 与 C2, + M6-A、M6-B 与 M6-C 已完成核心离线合同;真实插件验收与发布审计仍按里程碑推进。 - [transport 重放与 session 健康 RFC](rfcs/WaveBench_transport重放与session健康RFC.md) ## contributing:开发和接入 diff --git "a/docs/project/contributing/WaveBench_\346\217\222\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/docs/project/contributing/WaveBench_\346\217\222\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" index 542edd5..bec1ae8 100644 --- "a/docs/project/contributing/WaveBench_\346\217\222\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ "b/docs/project/contributing/WaveBench_\346\217\222\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" @@ -147,6 +147,103 @@ capability 名必须与 `kind` 同前缀。例如 scope 只能声明 `scope.*` 未采用新增 capability 的旧插件不需要提高核心版本下限。旧 `scope capture --screenshot` 不承载 新 `scope.screenshot_v2`;新插件应使用独立截图 Service 或 `wavebench scope screenshot capture`。 +### 采用 Source V2 扩展 + +准备提供完整信号源状态快照时,先阅读 +[Source V2 能力、状态与复合输出安全 RFC](../rfcs/WaveBench_source能力状态与复合输出安全RFC.md)。 +只读 snapshot 采用条件如下: + +- wheel 依赖和 descriptor 均要求 WaveBench `0.8.24` 或更高的 `0.8.x` 版本; +- descriptor 追加 `source_extensions`,显式声明 topology、read feature profile 和 pure-read query contract; +- driver 实现 `execute_source_query_plan_v2(plan)`,返回 `SourceQueryExecutionRecord`; +- 插件负责具体协议、合法查询顺序和解析,核心负责 semantic plan、availability、runtime narrowing 和 consistency; +- fake transport 覆盖组合响应、标量查询、activation、语义缺字段、query limit、deadline 和传输异常; +- descriptor 导入、snapshot 和 capability 校验均不得写入仪器、触发、切换输出或消费状态。 + +`source_extensions` 不能单独启用能力,必须同时声明 `source.snapshot_v2`。未声明该能力的旧插件 +继续走 Source V1。 + +基础写能力使用 `source.basic_configure_v2` 与 `source.output_v2`;它们的写入 contract、fresh snapshot、 +回读与失败恢复都由核心 Service 组织。Harmonic 预设配置使用独立的 +`source.harmonics_configure_v2`,driver 必须实现 `configure_source_harmonics_v2(request)`,且 descriptor 必须 +声明 Harmonic `READ`/`CONFIGURE`、可配置 order 区间、允许预设,以及 configured order、preset 与输出状态 +可读。该 capability 只覆盖 `all`、`even`、`odd` 预设,不得借此支持 USER mask、逐分量幅度/相位或隐式输出 ON。 + +Harmonic 关闭使用独立的 `source.harmonics_disable_v2`,driver 必须实现 +`disable_source_harmonics_v2(request)`。descriptor 必须声明同一通道的 Harmonic `READ`/`DISABLE` 与 output +state readback;request 只有 channel,结果和独立回读都必须证明 Harmonic、输出均为 OFF。它不能作为隐式 +basic reset,也不要求 order 或 preset readback。 + +内部 AM 使用独立的 `source.modulation_configure_v2`,driver 必须实现 +`configure_source_modulation_v2(request)`。descriptor 必须声明 Modulation `READ`/`CONFIGURE`、`am`、 +`internal`、`depth_percent` 和 `configuration_readable = true`,并能回读同一 channel 的 output state。 +该 capability 只覆盖输出 OFF 时的内部正弦 AM:深度为 `[0, 100]`,内部频率为有限正值;不得借此支持 +disable、外部调制源、内部波形选择、FM/PM/PWM 或隐式输出 ON。 + +内部 PM 使用独立的 `source.modulation_pm_configure_v2`,driver 必须实现 +`configure_source_pm_modulation_v2(request)`。descriptor 必须声明 Modulation `READ`/`CONFIGURE`、`pm`、 +`internal`、`phase_deviation_deg` 和 `configuration_readable = true`,并能回读同一 channel 的 output state。 +该 capability 只覆盖输出 OFF 时的内部正弦 PM:相位偏差为 `[0, 360]`,内部频率为有限正值;不得借此支持 +disable、外部调制源、内部波形选择、AM/FM/PWM 或隐式输出 ON。 + +内部 FM 使用独立的 `source.modulation_fm_configure_v2`,driver 必须实现 +`configure_source_fm_modulation_v2(request)`。descriptor 必须声明 Modulation `READ`/`CONFIGURE`、`fm`、 +`internal`、`frequency_deviation_hz` 和 `configuration_readable = true`,并能回读同一 channel 的 output state。 +该 capability 只覆盖输出 OFF 时的内部正弦 FM:frequency deviation 与内部频率均为有限正值;不得借此支持 +disable、外部调制源、内部波形选择、AM/PM/PWM 或隐式输出 ON。 + +内部 PWM 使用独立的 `source.modulation_pwm_configure_v2`,driver 必须实现 +`configure_source_pwm_modulation_v2(request)`。descriptor 必须声明 Modulation `READ`/`CONFIGURE`、`pwm`、 +`internal`、`configuration_readable = true`,且 `parameter_kinds` 至少包含 `duty_deviation_percent` 或 +`width_deviation_s` 之一,并能回读同一 channel 的 output state。该 capability 只覆盖输出 OFF 时的内部正弦 PWM: +request 包含有限正值的内部频率,以及恰好一个分支——`[0, 50]` 的 DUTY deviation 或 `[0, 500000]` 秒的 WIDTH +deviation;不得借此支持 disable、外部调制源、内部波形选择、AM/FM/PM 或隐式输出 ON。 + +内部 Sweep 使用独立的 `source.sweep_configure_v2`,driver 必须实现 +`configure_source_sweep_v2(request)`。descriptor 必须声明 Sweep `READ`/`CONFIGURE`、至少一个 spacing、internal +trigger、timing/marker 与 `configuration_readable = true`;同一 channel 的 Basic `READ` 必须声明 `sweep` frequency +mode,Output `READ` 也必须能够回读 output state。该 capability 只覆盖输出 OFF 时的内建 Sweep:request 包含 start/stop、一个已声明的 +spacing、`[2, 2048]` 的 steps 和 `[0.001, 300]` 秒的 sweep time;不得借此支持 center/span、marker、外部/手动 trigger、 +arm、fire、输出 ON 或返回固定频率。 + +内部 Triggered Burst 使用独立的 `source.burst_configure_v2`,driver 必须实现 +`configure_source_burst_v2(request)`。descriptor 必须声明 Burst `READ`/`CONFIGURE`、`triggered`、`internal`、 +`timing_readable = true` 和 `triggered_internal_configuration_readable = true`,并能回读同一 channel 的 output state。 +该 capability 只覆盖输出 OFF 时的 enabled internal Triggered Burst:request 包含 cycles、phase、internal period 与 delay; +不得借此支持 Gated、Infinity、外部/手动 trigger、arm、fire、输出 ON 或隐式恢复。 + +WIDTH Pulse 使用独立的 `source.pulse_configure_v2`,driver 必须实现 +`configure_source_pulse_v2(request)`。descriptor 必须声明 Pulse `READ`/`CONFIGURE`、WIDTH hold、 +delay 与 transition 可读,以及 `width_configuration_readable = true`,并能回读同一 channel 的 output state。 +该 capability 只覆盖输出 OFF 时的完整 WIDTH 形状:width 不小于 `4 ns`,delay 为有限非负值,两个 transition +为有限正值且各自不超过 width 的 `0.625` 倍;不得借此支持 DUTY hold、partial patch、trigger、输出 ON 或隐式波形切换。 + +ARB storage 与 selection 分别使用 `source.arbitrary_storage_v2` 和 `source.arbitrary_select_v2`。storage driver +必须同时实现 `read_source_arbitrary_storage_v2(channel, slot_id)` 与 +`mutate_source_arbitrary_storage_v2(request, payload)`;前者返回指定命名槽位的 exists、SHA-256 与大小,后者必须在 +设备侧以 create-only 或 compare-and-replace 语义执行单次 mutation。payload 只作为独立 `bytes` 参数传递,不能进入 +request、descriptor evidence 或 operation artifact。声明 storage capability 的 ARB profile 必须显式给出 +`storage_slot_metadata_readable`、`storage_write_modes` 与 `storage_max_payload_bytes`,并能回读 selection 与 output state。 +storage 不选择波形、不改变输出,也不要求其它独立端口关闭。 + +selection driver 实现 `select_source_arbitrary_v2(request)`。descriptor 必须声明 ARB `READ`/`CONFIGURE`、可读的 +selection 与 storage digest、允许 playback mode;true-ARB 还要求 sample rate 可读,Basic 必须支持可读的 +`arbitrary` waveform,Output 必须能回读 state。DDS 只接受 playback frequency,true-ARB 只接受 sample rate; +selection 只允许目标输出 OFF,完成后仍为 OFF,不会隐式 ON。声明任一 ARB V2 capability 后,V1 +`upload_arbitrary_waveform` 会在本地文件读取和仪器 I/O 前被拒绝,不能把混合 upload/selection/ON 的旧 route 部分映射。 + +跨通道 Combine、Coupling、Tracking 和相位关系分别使用 `source.combine_configure_v2`、 +`source.coupling_configure_v2`、`source.tracking_configure_v2` 与 `source.phase_relation_configure_v2`。每项都使用 +独立 driver method,request 只包含递增且唯一的 channel set 与 enabled state。descriptor 必须为该 relation 的 +channel set 声明 `READ`/`CONFIGURE`,在 `SourceCrossChannelCapabilityProfile` 中列出 relation kind、支持的 channel set 和 +`configuration_readable = true`;同 feature 还必须有 instrument-scope 的纯读 relation graph facet。 +核心只要求 graph 展开后实际受影响的端口 OFF,未连通的独立端口可以继续 ON。driver result 必须回读 relation 与每个 +受影响端口的 OFF 状态;无法证明 graph、端口范围或 readback 时不得声明此 capability。声明 Coupling V2 后,V1 +`configure_coupling` 在 I/O 前拒绝;声明任一这四项 capability 后,V1 restore 也在 I/O 前拒绝。 + +实际插件声明任一 Source V2 写 capability 前,至少完成该 capability 的 A0 离线 fixture;声明的方向、profile、 +方法与版本门必须同时通过核心校验。没有实机证据时,不得把核心合同注册描述为已完成设备写能力验收。 + ## 配置 options 插件私有配置放在对应的 `[.options]` 表中,并为每个键定义 `OptionSpec`。适合 `OptionSpec` 的内容包括分块点数、插件专用超时和明确枚举;resource、backend、通用 timeout、安全限制和输出状态仍由核心配置管理。 diff --git "a/docs/project/guides/WaveBench_CLI\345\275\242\346\200\201.md" "b/docs/project/guides/WaveBench_CLI\345\275\242\346\200\201.md" index ebcb8fd..3a0d2c5 100644 --- "a/docs/project/guides/WaveBench_CLI\345\275\242\346\200\201.md" +++ "b/docs/project/guides/WaveBench_CLI\345\275\242\346\200\201.md" @@ -31,7 +31,7 @@ wavebench run --help | 类别 | 示例 | 行为 | |---|---|---| | 离线 | `run schema`、`run template`、`run check`、`run intent`、`run report`、`run compare`、`run resume`、`capability explain`、`lock status`、`capture inspect`、`tui --fake` | 不连接仪器;报告、比较、检查、能力解释、锁查询和意图生成只读取本地文件 | -| 连接读取 | `doctor`、`net`、`scope idn`、`scope status`、`run verify` | 查询资源、身份或状态,不应修改实验设置 | +| 连接读取 | `doctor`、`net`、`scope idn`、`scope status`、`source snapshot-v2`、`run verify` | 查询资源、身份或状态,不应修改实验设置 | | 显式写入或触发 | `scope auto`、`scope fetch/capture`、source / power setter、`run plan` | 可能改变设置、触发采集或切换输出 | 执行硬件写入前,应先确认接线、输入阻抗、输出状态和安全限制。CLI 不会自动发送 `*RST`,也不会因为设置电压或幅度而自动打开输出。 @@ -68,6 +68,29 @@ wavebench capability explain source.output --candidates --json `--candidates` 只筛选当前本地 registry 中的驱动,不安装、不下载插件。 +完整的只读信号源状态使用: + +```bash +wavebench source snapshot-v2 --config wavebench.toml +wavebench --json source snapshot-v2 --config wavebench.toml +``` + +该命令要求插件声明 `source.snapshot_v2`,按 descriptor topology 查询全部通道、输入和跨通道 +关系,不接受单通道或 raw query 参数。普通模式输出缩进 JSON;`--json` 使用 +`wavebench.cli.result.v1` envelope。命令不授权任何 Source V2 写入。 + +已声明对应写 capability 的插件还可以配置跨通道关系: + +```bash +wavebench source combine-configure-v2 --channel 1 --channel 2 on --config wavebench.toml +wavebench source coupling-configure-v2 --channel 1 --channel 2 off --config wavebench.toml +wavebench source tracking-configure-v2 --channel 1 --channel 2 on --config wavebench.toml +wavebench source phase-relation-configure-v2 --channel 1 --channel 2 on --config wavebench.toml +``` + +`--channel` 必须重复给出至少两个递增且唯一的参与端口。核心只要求 relation graph 展开后的受影响端口为 OFF; +没有连通关系的其它端口可以继续 ON。命令不设置厂商私有联动参数,也不开启输出。 + `--json` 可以放在命令行任意位置。非交互命令输出 `wavebench.cli.result.v1`;错误输出 `wavebench.error.v1`,诊断信息写入 stderr。TUI 和 HTTP MCP 不使用 one-shot JSON 包装。 diff --git "a/docs/project/guides/WaveBench_run_plan_\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/project/guides/WaveBench_run_plan_\344\275\277\347\224\250\346\214\207\345\215\227.md" index edd8049..2875b05 100644 --- "a/docs/project/guides/WaveBench_run_plan_\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/project/guides/WaveBench_run_plan_\344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -361,6 +361,158 @@ state = "on" 这看起来啰嗦,但它能避免现场调试时被隐藏动作吓到。 +### Source V2 基础、高级配置与 ARB 写 step + +声明 `source.snapshot_v2` 与对应写 capability 的插件可以使用十七个 Source V2 step。基础配置只在目标输出已关闭时执行;输出 ON 与 OFF 分别使用不同 step: + +```toml +[[steps]] +kind = "source.basic_configure_v2" +channel = 1 +waveform_kind = "sine" +frequency_hz = 1000 +amplitude_vpp = 1.0 +offset_v = 0.0 + +[[steps]] +kind = "source.output_enable_v2" +channel = 1 + +[[steps]] +kind = "source.output_disable_v2" +channel = 1 + +[[steps]] +kind = "source.harmonics_configure_v2" +channel = 1 +order = 8 +preset = "odd" + +[[steps]] +kind = "source.harmonics_disable_v2" +channel = 1 + +[[steps]] +kind = "source.modulation_configure_v2" +channel = 1 +depth_percent = 80 +internal_frequency_hz = 25 + +[[steps]] +kind = "source.modulation_pm_configure_v2" +channel = 1 +phase_deviation_deg = 90 +internal_frequency_hz = 25 + +[[steps]] +kind = "source.modulation_fm_configure_v2" +channel = 1 +frequency_deviation_hz = 12500 +internal_frequency_hz = 25 + +[[steps]] +kind = "source.modulation_pwm_configure_v2" +channel = 1 +internal_frequency_hz = 25 +duty_deviation_percent = 30 + +[[steps]] +kind = "source.sweep_configure_v2" +channel = 1 +start_hz = 100 +stop_hz = 1000 +spacing = "linear" +steps = 101 +sweep_time_s = 1 + +[[steps]] +kind = "source.burst_configure_v2" +channel = 1 +cycles = 12 +phase_deg = 30 +internal_period_s = 0.25 +delay_s = 0.5 + +[[steps]] +kind = "source.pulse_configure_v2" +channel = 1 +width_s = 1e-6 +delay_s = 0 +leading_transition_s = 1e-8 +trailing_transition_s = 1e-8 + +[[steps]] +kind = "source.arbitrary_storage_v2" +channel = 1 +slot_id = "slot_a" +file = "payload.bin" +write_mode = "create_only" + +[[steps]] +kind = "source.arbitrary_select_v2" +channel = 1 +slot_id = "slot_a" +playback_mode = "dds" +playback_frequency_hz = 1000 + +[[steps]] +kind = "source.combine_configure_v2" +channels = [1, 2] +enabled = true +``` + +`source.basic_configure_v2` 的 `channel` 必填,五个 basic 字段中至少写一个;缺失字段保持当前值。 +`source.output_enable_v2`、`source.output_disable_v2` 和 `source.harmonics_disable_v2` 都只接受 `channel`。`source.harmonics_configure_v2` +要求 `channel`、整数 `order >= 2` 与 `all`、`even`、`odd` 之一的 `preset`;核心还会在执行前检查运行时 +profile 是否支持该 order 和预设。`source.modulation_configure_v2` 要求 `channel`、位于 `[0, 100]` 的 +`depth_percent` 与有限正值 `internal_frequency_hz`;它只配置内部正弦 AM。 +`source.modulation_pm_configure_v2` 要求 `channel`、位于 `[0, 360]` 的 `phase_deviation_deg` 与有限正值 +`internal_frequency_hz`;它只配置内部正弦 PM。 +`source.modulation_fm_configure_v2` 要求 `channel`、有限正值 `frequency_deviation_hz` 与有限正值 +`internal_frequency_hz`;它只配置内部正弦 FM。 +`source.modulation_pwm_configure_v2` 要求 `channel`、有限正值 `internal_frequency_hz`,以及恰好一个显式单位分支: +位于 `[0, 50]` 的 `duty_deviation_percent` 或位于 `[0, 500000]` 秒的 `width_deviation_s`;它只配置内部正弦 PWM。 +`source.sweep_configure_v2` 要求 `channel`、有限正值且 start 不大于 stop 的 `start_hz`/`stop_hz`、`linear`、 +`logarithmic`、`step` 之一的 `spacing`、位于 `[2, 2048]` 的整数 `steps` 与位于 `[0.001, 300]` 秒的 `sweep_time_s`; +它只配置内建 Sweep,不会 fire 或开启输出。 +`source.burst_configure_v2` 要求 `channel`、位于 `[1, 500000]` 的整数 `cycles`、位于 `[0, 360]` 的 +`phase_deg`、有限正值 `internal_period_s` 与位于 `[0, 85]` 的 `delay_s`;它只配置内部 Triggered Burst, +不会 trigger 或开启输出。 +`source.pulse_configure_v2` 要求 `channel`、不小于 `4 ns` 的 `width_s`、有限非负 `delay_s`,以及有限正值 +`leading_transition_s`/`trailing_transition_s`;两个 transition 都不能超过 width 的 `0.625` 倍,且它只配置 WIDTH 脉冲形状。 + +`source.arbitrary_storage_v2` 要求 `channel`、安全 token 形式的 `slot_id`、相对或绝对的 `file`,以及 +`create_only` 或 `replace_if_digest_matches` 的 `write_mode`。replace mode 还必须给出 +`expected_previous_sha256`。执行时会从 plan 所在目录解析相对文件,计算 payload 的 SHA-256 和大小;这些字节不会 +写入执行意图或 Source operation artifact。storage 不选择波形、不改变输出,目标或其它独立端口不需要因上传被关闭。 + +`source.arbitrary_select_v2` 要求 `channel`、`slot_id` 与 `dds`/`true_arb` 之一的 `playback_mode`。DDS 只接受 +正的 `playback_frequency_hz`;true-ARB 只接受正的 `sample_rate_hz`。该 step 必须在目标输出已关闭时执行,完成后仍关闭; +它不包含 output ON。 + +`source.combine_configure_v2`、`source.coupling_configure_v2`、`source.tracking_configure_v2` 和 +`source.phase_relation_configure_v2` 都要求递增且唯一的 `channels` 数组(至少两个通道)与布尔 `enabled`。核心按 +descriptor relation graph 展开实际受影响端口;只有展开后的端口必须 OFF,未连通端口可以继续 ON。它们不会开启输出、 +不会设置厂商私有关系参数,也不会为之后的 output ON 提供额外授权。 + +Harmonic、内部 AM、内部 PM、内部 FM、内部 PWM、内部 Sweep、内部 Triggered Burst 与 WIDTH Pulse step 都必须在目标输出已关闭时执行,完成后仍保持关闭;它们不会隐式开启输出。现有 +`restore.source_state` 只恢复 basic 状态,不恢复 Harmonic、调制、Burst 或 Pulse 配置。双合同插件声明 +`source.harmonics_configure_v2` 或 `source.harmonics_disable_v2` 后,V1 `configure_harmonics` 会在仪器 I/O 前被拒绝;声明 +`source.modulation_configure_v2` 后,V1 `configure_am_modulation` 会在仪器 I/O 前被拒绝。未声明对应能力的 +旧插件继续使用 V1 路径。声明 `source.modulation_pm_configure_v2` 后,V1 `configure_pm_modulation` 也会在 +仪器 I/O 前被拒绝。声明 `source.modulation_fm_configure_v2` 后,V1 `configure_fm_modulation` 和 restore 也会在 +仪器 I/O 前被拒绝。声明 `source.modulation_pwm_configure_v2` 后,V1 `configure_pwm_modulation` 和 restore 也会在 +仪器 I/O 前被拒绝。声明 `source.sweep_configure_v2` 后,V1 `configure_sweep`、`trigger_sweep` 和 restore 也会在 +仪器 I/O 前被拒绝。声明 `source.burst_configure_v2` 后,V1 `configure_burst`、`trigger_burst` 和 restore 也会在 +仪器 I/O 前被拒绝。声明 `source.pulse_configure_v2` 后,V1 `configure_pulse` 也会在仪器 I/O 前被拒绝, +因为 V1 route 还允许 DUTY hold。该 step 不会让 `source.output_enable_v2` 获得 Pulse 输出 ON 授权。 + +声明 `source.coupling_configure_v2` 后,V1 `configure_coupling` 在仪器 I/O 前拒绝;声明任一跨通道 V2 capability +后,V1 restore 也会在仪器 I/O 前拒绝,避免它在未知 relation state 下重开输出。 + +执行意图会记录十八个 Source V2 operation,实际执行时的完整 Source V2 artifact 会写入 +`run.json.source_operations`;storage payload 只以文件名、SHA-256 与大小出现。没有声明 V2 capability 的旧插件继续使用 V1 step。 + ## 常见 `run check` 报错 ### step kind 拼错 @@ -493,6 +645,7 @@ data/runs/YYYYMMDD_HHMMSS_