Vyntek
规格机器视觉规格

MVP 可勾选测试契约表(Tool / ToolFlow · v1.9)

www 工作副本(2026-10-21 Asia/Shanghai) 双轨:正文迁自 mvdocs test-contracts。 实现边界:表内勾选保持未勾。外形对拍在薄摘 TC-MEM · TC-SESS · TC-ACQ · TC-OUT · TC-DISP。smoke 与 Controls.Tests 不等于本表通过。 关联:toolflow · examples-scenarios

MVP 可勾选测试契约表(Tool / ToolFlow · v1.9)

目标设计草案,尚未实施。总体边界见设计概述;编排权威见 toolflow.md( v1.9)。

定调(勿回退):Tool / ToolFlow;命名空间 vyntek::toolflow / vyntek::imaging; ToolId; DiagnosticCode。不混 MPF / 旧 DAG;不写第二执行引擎;不写覆盖率 KPI。验收以本表勾选 + 单测/headless 为准。

Alive 拍板(R4):将 toolflow §10.1 / §3.4 H1–H10 / §7.4.6 Diagnostic / 场景 S01–S08 收成「可勾选测试契约」:每条 = 前置 · 动作 · 期望 code/状态 · 对应章节。§10.1 保留摘要并链到本文;场景文提供骨架,不以场景代替本表勾选正文。

Alive 拍板(R6):场景 S09a–d 补齐嵌套/Encapsulation、SourceDisabled、InvalidBinding、IoFailure、停相机≠自动 Cancel、可选 §9.2 两流串联;本表更新场景映射并增 TC-RUN-06/TC-RUN-07。不改 v1.9 语义与 Diagnostic 码表。

Alive 拍板(Arden · R9):将 output-inspection.md T10 集合事件与观察不变量收成可勾选 TC-OUT-*;场景 S10 对齐。不改 T10 事件闭集与 toolflow v1.9 码表/语义。勿与 T15 开放风险 R9(编辑 UI)撞号(对照见 glossary.md §2)。

Alive 拍板(Arden · R10):将 camera-acquisition.md / session-lifecycle.md 已拍板散文收成可勾选 TC-ACQ-* + TC-SESS-*;薄场景 S11 对齐。不改 Diagnostic / T9 停止矩阵语义与 toolflow v1.9 码表。勿与 T15 开放风险 R10(C++ UI·已关闭)撞号(对照见 glossary.md §2)。

Alive 拍板(Arden · R11):将 memory-management.md 已拍板散文(工厂接管 / 最后引用 / pin / 授予·取消竞争 / 初始化·Invalid / 归还隔离)收成可勾选 TC-MEM-*;薄场景 S12 对齐。不改 Diagnostic / T9 停止矩阵与 toolflow v1.9。 T15 无 R11——本回合编号独立(对照见 glossary.md §2)。

Alive 拍板(Arden · R12):将 image-display.md 已拍板散文(登记≠授予 / Share 不接管 / Retain·Snapshot·Detach / 回执四信号 / 失败保留 / 四格式取样 / ROI·负步长 / 卸载·重挂·context / 预算失败不丢旧图 / 显示只观察)收成可勾选 TC-DISP-;薄场景 S13 对齐。不改 Diagnostic / T9 停止矩阵与 toolflow v1.9。显示契约仅 C#*;勿与 T15 开放风险 R10(C++ UI·已关闭)互替(对照见 glossary.md §2)。

关联: toolflow.md §3.4 / §7.4.3 / §7.4.6 / §7.6 / §9 / §10.1 · examples-scenarios.md(S01–S13) · output-inspection.md( T10 · Arden · R9) · camera-acquisition.md / session-lifecycle.md( Arden · R10 · TC-ACQ / TC-SESS) · memory-management.md( Arden · R11 · TC-MEM) · image-display.md( Arden · R12 · TC-DISP;仅 C#) · host-integration.md( R7 · S07 同核;两端都停;TC-CTL-05 交叉) · sketch/README.md(R5 伪树·示意对照,不以碎片代替本表勾选) · glossary.md( R8;Arden · R9 / R10 / R11 / R12 撞号) · validation-and-roadmap.md · cpp-headers.md · csharp-binding.md

用法

约定说明
勾选列实现期单测/headless 通过后勾 [x];文档侧默认全 [ ]
期望列写 DiagnosticCode 名,或明确状态(ok / Outputs 可读 / Access=ReadOnly 等)
Severity未另写时,失败码默认 Severity::Error;成功路径允许空诊断或仅 Info
IDTC-* 供单测命名与回链;S0x 为场景骨架映射,不是第二套验收正文
非目标见文末「非目标门禁」;不得误交付脚本/MPF/DAG/产线 IO

1. 注册 / AddTool / fake 注册

ID勾前置动作期望 code / 状态对应章节场景
TC-REG-01[ ]空 ToolRegistryregister_fake_tools(或等价)注册 §7.6.3 至少 fake_acq / fake_pm_align / fake_passthrough / fake_fail_once均可 Create(type_id);实例非空toolflow §7.6 / §10.1 对象模型S08
TC-REG-02[ ]已注册某 type_id再次 Register 同 type_id拒绝(生产默认);不覆盖既有工厂§7.6.2S08
TC-REG-03[ ]Registry 无该 idCreate("type_id_not_registered", …) 或 Load 含未知 typeDiagnosticCode::UnknownTypeId;无半初始化成功流§7.4.6 / §7.6.2 / §10.1S04 / S08
TC-REG-04[ ]fake 已注册flow->AddTool(registry.Create(…))所有权在 ToolFlow;registry 不保留实例;tool_id 流内稳定§7.4.1 / §7.6.2S01
TC-REG-05[ ]可定义终端AddInput / AddOutput(名称、TypeDesc、稳定 id)终端可 Link;嵌套流仅经终端对外(封装)§3 / §7.4.1 / §10.1S01 / S08 / S09a / S09d
TC-REG-06[ ]fake 与 builtin 同表用同一 Registry Create / Load共用工厂契约;禁止反序列化旁路注册表§7.6 / §10.1(T7)S08
ID勾前置动作期望 code / 状态对应章节场景
TC-LNK-01[ ]两工具类型兼容的端子Link 合法边成功;不留下半条边;Validate 无 Error§4.2 / §5 / §7.4.2S02
TC-LNK-02[ ]类型不兼容(含图像跨格式)Link 或 ValidateDiagnosticCode::TypeMismatch;拒绝建链或 Validate 失败§5 / §7.4.6S02(负例)
TC-LNK-03[ ]源在目标列表之下Link 或 ValidateDiagnosticCode::OrderViolation§4.1 / §7.4.6 / §10.1S02
TC-LNK-04[ ]外层绑内层私有属性Validate / LinkDiagnosticCode::Encapsulation§7.4.6 / §9.3 / §10.1S09a
TC-LNK-05[ ]端点缺失 / 方向非法Validate / Link / LoadDiagnosticCode::InvalidBinding;不留残链§7.4.6 / §6.6.4S09b(主断言;原 S04 附带升格)
TC-LNK-06[ ]源工具 disabled;下游依赖其输出Run 拉值(MVP 严格)DiagnosticCode::SourceDisabled;下游不得假成功§4.3 / §7.4.2 / §7.4.6 / §10.1S09b(S02 负例指针)
TC-LNK-07[ ]已知 type_id,缺必填配置属性Validate(Load 后或内存建流)DiagnosticCode::MissingRequiredProperty;无静默默认使校验通过§6.5 / §7.4.6(T8) / §10.1S04
TC-LNK-08[ ]合法流Validate无 Severity::Error;可进入 Run§7.4.4 / §10.1S01 / S02

3. 顺序 Run / Outputs

ID勾前置动作期望 code / 状态对应章节场景
TC-RUN-01[ ]单工具合法流(如 fake_constant)RunSession::Runr.ok==true;Outputs 可读且值符合配置/链接§7.4 / §9.4 / §10.1S01
TC-RUN-02[ ]多工具合法链(列表序)一次 Run自上而下执行;链接赋值生效;无「边就绪即跑」;Outputs 符合链§4.1 / §4.2 / §9.1S02
TC-RUN-03[ ]§7.6.3 fake 拼装(Acq→PMAlign→Passthrough/Constant)headless Runok;Outputs / 中间属性可读;等价 §9.1§7.6.3 / §9.1 / §10.1S03
TC-RUN-04[ ]同一流连续两次 Run第二次 Run两次独立执行;无环边;第二次覆盖上次 Outputs§4.1 / §10.1S07(批跑)
TC-RUN-05[ ]观察订阅已挂(可选)Run 成功/失败观察不驱动下一次 Run;失败保留上次成功(T10)output-inspection / §10.1 非编排驱动;升格正文见 TC-OUT-05 / TC-OUT-09(Arden · R9)S03 / S10
TC-RUN-06[ ]内层合法流已 Validate;外层 AddTool 嵌套外层只链内层终端后 Runok;Outputs 可读;嵌套 Run=子流完整列表序;绑私有属性见 TC-LNK-04§4.3 / §9.3 / §10.1S09a
TC-RUN-07[ ]两子流(Locate/Defect)各有终端外层列表序串联终端后 Runok;先 Locate 再 Defect;只链终端;非 DAG§9.2 / §4.1 / §10.1S09d(可选)

4. Cancel / 失败中止 / Busy

ID勾前置动作期望 code / 状态对应章节场景
TC-CTL-01[ ]流含 fake_cancel_check + 后续工具Run 中 RequestCancel(协作式)DiagnosticCode::Cancelled;r.ok==false;当前工具合作返回后不再启动后续§4.3 / §7.4.3(T9) / §7.4.6 / §10.1S06
TC-CTL-02[ ]abort_on_tool_failure=true;中途 fake_fail_*RunDiagnosticCode::Aborted;failed_tool_id 指向失败工具;后续不 Run§4.3 / §7.4.3 / §10.1S06
TC-CTL-03[ ]同 RunSession 已有 Run 在途第二次 RunDiagnosticCode::Busy;首次不受损;不排队§7.4.3 / §7.4.6 / §10.1S06
TC-CTL-04[ ]Run 在途宿主停相机不自动 Cancel 在途 Run§7.4.3 停止矩阵 / session-lifecycleS09c(独立步骤;S06 附注)
TC-CTL-05[ ]Run 在途或已结束关闭 ImageDisplay / 显示宿主显示只观察;不停编排 / 不 Cancel Run§7.4.3 / csharp-binding / image-displayS05 / S06 / S07

5. Load / SchemaTooNew / UnknownTypeId / 序列化

ID勾前置动作期望 code / 状态对应章节场景
TC-SER-01[ ]合法流已 SaveLoad → 结构一致 → 再 headless RunLoad ok;序/终端/链接/禁用/参数一致;Run ok§6.3–6.6 / §10.1S04 / S07
TC-SER-02[ ].avtf 的 schema_version 高于加载器LoadDiagnosticCode::SchemaTooNew;严格失败§6.5 / §7.4.6(T8) / §10.1S04
TC-SER-03[ ]文档含未知 type_idLoadDiagnosticCode::UnknownTypeId;无占位成功§6.5 / §7.4.6 / §10.1S04
TC-SER-04[ ]缺或坏 component_version;type 已知Load不拦 Load(与 schema_version 门禁独立)§6.5 / §6.6(T8)S04
TC-SER-05[ ]含未知可选字段Load成功或带 Warning/Info;字段保留不剥掉§6.5 / §10.1(单测)
TC-SER-06[ ]已 Run 过的流默认 Save运行时态(LastRun、注入值)不进配方;金样图不默认内嵌§6.3 / §10.1S03 / S07
TC-SER-07[ ]文件不可读 / 截断Load / SaveDiagnosticCode::IoFailure§7.4.6S09c

6. 图像句柄交接 H1–H10

断言细节以 toolflow §3.4 表为准;本表供 §10.1 / 场景勾选对照。链接 ≠ DAG。

ID勾前置动作期望 code / 状态对应章节场景
TC-H1[ ]工具持有 WritableView 写毕Complete;再对同一 writer Complete/GetPixelRow再写失败(Disposed/InvalidOperation);未 Complete 就 Dispose → Invalid,不得作下游输入§3.4 H1S05
TC-H2[ ]写毕待发布CompleteAndOpenRead → ShareImage原子边界内无第二写者;返回 ReadOnly;access()==ReadOnly§3.4 H2S05 / S08
TC-H3[ ]已有稳定 ReadOnlyViewShareImage新句柄 Access=ReadOnly;OpenWrite → NotSupported;同 BufferId(不因 Share 拷像素)§3.4 H3S05 / S03
TC-H4[ ]源已是 ReadOnly 句柄Share 得第二句柄两句柄皆 ReadOnly;独立关闭;OpenWrite 拒绝§3.4 H4S05
TC-H5[ ]源为 ReadWrite 根仅 Share(未再 Complete/ShareImage)不得冒充稳定 ReadOnly 下游输入;校验/Run 可拒绝不稳定交接§3.4 H5S05(负例单测)
TC-H6[ ]合法图像链接Run 前链接赋值写入下游输入目标输入 access()==ReadOnly;OpenWrite 立即拒绝;列表序不变§3.4 H6 / §4.2S02 / S03 / S05
TC-H7[ ]输出已交下游且下游将/正 Run生产者再 OpenWrite/改已发布存储被稳定读引用挡住或失败;下游两次 OpenRead 所见代次一致§3.4 H7S05
TC-H8[ ]输入 ReadOnly 需改像素Clone → OpenWrite → Complete(…) → 再发布新 BufferId 可写;源仍只读;失败不留半份可交接输出§3.4 H8S05 / S08
TC-H9[ ]ReadOnly 根上 ROIGetRegion 得 ROI 句柄;企图 OpenWriteROI ReadOnly;写入拒绝;不得把根退化为可写§3.4 H9S05
TC-H10[ ]工具失败 / 未 Complete;abort_on_tool_failure=trueRun 失败路径下游拉值不得得假成功 ReadOnly;后续工具不 Run(与 TC-CTL-02 一致)§3.4 H10 / §4.3S06 / S08

7. 输出观察 TC-OUT-*(T10 · Arden · R9)

事件闭集与语义权威见 output-inspection.md( T10);本表只做可勾选断言。不改事件名/码表。对外标识 ToolId。场景骨架 S10。观察侧断言与编排 Run 契约交叉时,以本表 + TC-RUN-05 互指为准。

ID勾前置动作期望 code / 状态对应章节场景
TC-OUT-01[ ]KeepLatest;工具成功且输出集合非空一次 Run 后观察面收到集合事件发 SnapshotReplaced;当前可打开集合身份已更新;不得静默跳过output-inspection §集合级事件S10
TC-OUT-02[ ]KeepLatest;工具成功且输出集合为空一次 Run必须发 EmptySnapshot;禁止静默无事件;不得继续把上次非空集合标为「当前」output-inspection(T10 空快照)S10
TC-OUT-03[ ]KeepLatest;保留/复制失败或配额不足(观察侧)业务工具仍可成功并完成路由观察面发 Unavailable;不得把旧成功集合冒充为本轮新结果;业务 Outputs 路由不受观察失败改写output-inspectionS10
TC-OUT-04[ ]已保留集合;触发会话淘汰/预算回收/策略关闭淘汰已保留集合发 Evicted;此后对该身份 TryOpenLatest 不可用output-inspectionS10
TC-OUT-05[ ]已有上次成功快照;本轮工具失败Run 失败路径不替换最近成功集合;观察「当前成功快照」仍指向上次成功身份,并与最新失败状态区分(对齐 TC-RUN-05)output-inspection;§10.1S10 / S03
TC-OUT-06[ ]KeepLatest;当前已有保留集合(含空)Subscribe(replay_latest=true)再收后续事件连接后立即重放当前保留对应事件(含 EmptySnapshot);之后不漏更新;回调不得隐式 Runoutput-inspection 动态连接S10
TC-OUT-07[ ]已 TryOpen 得查看者句柄;随后集合被 Evicted淘汰 + 继续持有已打开查看者已打开查看者不被强制关闭;新的 TryOpenLatest 对该身份不可用;关闭查看者后不阻挡会话清理契约output-inspection 查看者寿命S10
TC-OUT-08[ ]对照两会话:A=KeepLatest,B=ReleaseAfterRoutingA 跑成功后订阅可重放;B 路由后无保留再连调试器A:可重放当前集合;B:已回收过去结果无法补取;动态连接 ≠ 无限历史;ReleaseAfterRouting 不冒充可恢复output-inspection KeepLatest vs ReleaseAfterRoutingS10
TC-OUT-09[ ]任意观察订阅/重放/TryOpen 已挂仅观察回调或查询(不显式 Run)永不隐式触发 Run、链接赋值或重新采集(升格/对齐 TC-RUN-05;与显示只观察一致)output-inspection;toolflow §7.4.3;TC-RUN-05S10 / S03

8. 采集接入 TC-ACQ-*(阶段 D · Arden · R10)

语义权威见 camera-acquisition.md;本表只做可勾选断言。不改停止矩阵 / Diagnostic 码表。假采集适配(fake SDK 持帧/回调临时指针)即可;不以真实供应商驱动代替本表勾选正文。场景骨架 S11。交叉:停相机 ≠ 自动 Cancel 见 TC-CTL-04 / TC-SESS-05。

ID勾前置动作期望 code / 状态对应章节场景
TC-ACQ-01[ ]SDK 可显式持帧、地址稳定、待归还后复用适配器 ImportNative(ReadOnly);外借结束经一次 releaseAsync 归还在途图像保持该份 SDK 引用;Share 不重复 AddRef SDK;最后归还 Release 一次;新外借周期新 BufferId(即使物理地址相同)camera-acquisition「两种采集接入」S11
TC-ACQ-02[ ]像素仅回调期有效,或 SDK 无法保证后续稳定回调内同步 Copy 到受控自有存储后,按协议立即归还原 SDK 缓冲回调结束后不得再持原 SDK 地址当稳定输入;无法保证时必须走复制,禁止用托管引用计数掩盖 SDK 提前复用camera-acquisitionS11
TC-ACQ-03[ ]已有稳定 ReadOnly 图像且正好一个待交接 handleTryPostOwned(std::move(image)):成功 / 拒绝 / 抛错三路径成功→入口接管所有权;拒绝→关闭未接管 image;抛错→未接管(不得外层 finally 无条件 SDK Release);导入成功后只能经图像关闭触发归还camera-acquisition「入口接管」S11
TC-ACQ-04[ ]自有池或入口预算已满 / 无余量复制前取池与入口预算;满载时 TryPostOwned 或拒绝路径禁止先拷贝再发现无容量;满池/满入口→拒绝入队并可观察;不无限积压camera-acquisitionS11
TC-ACQ-05[ ]图像关闭已触发 releaseAsync;归还泵贯穿采集会话排队归还 → SDK 专属线程确认ReturnCompleted 仅在 SDK 确认归还后完成;归还队列有界或入口预留归还容量;归还失败=会话故障,不吞掉、不对同一 Release 自动重试camera-acquisition「归还泵」S11
TC-ACQ-06[ ]连续采集;预览走 Latest 槽多帧到达;UI 定时/合并取最新有所有权的 Latest 槽;被替换项立即关闭;禁止为每次采集无限 Post 带图像引用的 dispatcher 回调;实时预览默认 Snapshot 口径(UI 暂停最多一显示副本)camera-acquisition「预览解耦」S11
TC-ACQ-07[ ]采集回调线程在途回调内仅 TryPostOwned(或有时限的 SDK 专用接入);不挂起等 UI/算法/同 SDK 线程归还回调不堵 SDK 归还路径;不得在回调内同步等待 ReturnCompleted 或同线程 Releasecamera-acquisitionS11

9. 会话停流 TC-SESS-*(阶段 D · Arden · R10)

语义权威见 session-lifecycle.md;停止矩阵权威仍为 toolflow §7.4.3(T9)——本文不改其语义。本表只做排空/归还/故障可勾选断言。场景骨架 S11。宿主侧分派见 host-integration.md §4。

ID勾前置动作期望 code / 状态对应章节场景
TC-SESS-01[ ]采集会话 Running;有在途帧/工作走完整停流:Quiescing → Draining/Cancelling → Releasing → Returning → Stopped结束须同时:无新回调、队列空、工具工作结束、会话拥有的图像/访问已关闭、SDK 归还已完成;不得边持最后引用边等自己的 ReturnCompletedsession-lifecycle 状态机 / 结束条件S11
TC-SESS-02[ ]宿主已把图像导出到会话外窗口/历史(外部保留)会话停流并企图销毁 SDK停止结果报告「仍有外部保留」;禁止假称设备资源已归还;要立即毁 SDK 须先复制到独立存储并关闭原图session-lifecycle「外部保留」S11
TC-SESS-03[ ]停流等待中;调用方超时触发超时返回返回未排空/故障结果(可含 BufferId、活动访问、pin、归还队列、持有时长);底层安全清理继续;不得强行回收仍被 native 使用的地址session-lifecycle「超时」S11
TC-SESS-04[ ]归还失败 / 相机断线 / 消费者异常等故障注入(fake)进入可观察故障路径;归还不自动再次 Release;清理泵继续处理其他可归还项;最终停止结果汇总失败;ReturnFailed / 断线可观测session-lifecycle「故障处置」S11
TC-SESS-05[ ]Run 在途且采集在跑宿主要「相机与 Run 一起停」必须显式既停采集 又 RequestCancel;二者不隐含联动(对齐停止矩阵 / TC-CTL-04;host-integration「两端都停」)session-lifecycle 停止矩阵;toolflow §7.4.3;host-integration §4S11 / S09c

10. 存储 / pin / 归还 TC-MEM-*(阶段 B · Arden · R11)

语义权威见 memory-management.md;首次根范围 / padding 薄指 image-model.md。本表只做可勾选断言( fake buffer 即可)。不改 Diagnostic / T9 停止矩阵与 toolflow v1.9。场景骨架 S12。交叉:句柄 H1–H10 见 §6;采集归还泵见 TC-ACQ-05(不扩本表)。

ID勾前置动作期望 code / 状态对应章节场景
TC-MEM-01[ ]进程默认或自定义 MemoryPool 可用ImageBuffer::Rent(minimum_capacity, pool) 成功 / 失败两路径成功→框架接管租出 owner;失败→归还内部已租出存储且无半接管实体;ReadOnly + Uninitialized 创建时拒绝;capacity>0memory-management「工厂约束」S12
TC-MEM-02[ ]调用方持有独立 MemoryOwnerTakeOwnership(owner, …) 成功 / 抛错成功→接管 owner,调用方不再访问/释放;抛错→不释放调用方 owner(无双释放)memory-management「工厂约束」S12
TC-MEM-03[ ]调用方已取得有效 SDK/原生引用 + release 回调ImportNative(address, capacity, access, release, …) 成功 / 抛错成功→接管该份引用;抛错→不调用 releaseAsync/release;地址非零、容量合法memory-management「工厂约束」S12
TC-MEM-04[ ]多 handle + 活动读/写 + 已入队权限申请逐个关闭 handle / 结束访问 / 取消或完成排队申请仅当全部 handle、活动访问与排队申请结束后才进入 Returning;关闭单一 handle 不触发归还memory-management「handle、异步等待与清理」S12
TC-MEM-05[ ]调用方持有该实体最后一份存活引用边持引用边 AwaitReturnCompleted / 等自身 ReturnCompleted禁止(等待环);须先关闭自身 handle/引用,再等待可重复的 ReturnCompletedmemory-management「handle、异步等待与清理」S12
TC-MEM-06[ ]已 OpenRead 并 Pin();父 reader 先 Dispose企图 OpenWrite / 推进归还;读 pin 的 access()pin 仍阻止写入与归还直至放 pin;读 pin Access 永为 ReadOnly(不因底层可写而提升)memory-management「span 与 pin 的有效期」S12
TC-MEM-07[ ]已 OpenWrite 并持有写 pinComplete / CompleteAndOpenRead(pin 未放);或父 writer 先 Dispose存在写 pin → Complete 抛 InvalidOperation(或等价);父先 Dispose → 内容 Invalid,但独占权限持续到末写 pin 释放,期间不授新访问memory-management「span 与 pin」/「写入提交」S12
TC-MEM-08[ ]存在冲突读者/写者或排队中;带 CancelTokenOpenRead/OpenWrite + cancel;发起申请的 handle 随后 Dispose取消令牌可撤销等待;发起 handle Dispose 不撤销已入队申请;轮到读时若未初始化/上次写失败 → 立即 InvalidOperation,不无限等未登记写者memory-management「访问授予」/「handle」S12
TC-MEM-09[ ]reader/writer/buffer 上并发 Share/ShareBuffer 与 Dispose竞争双方单一协调点原子裁定;成功返回的子对象始终独立有效;已关闭对象再 Share/申请 → Disposed(或等价)memory-management「访问授予」S12
TC-MEM-10[ ]已获写权限;未 CompleteDispose writer内容 → Invalid;不回滚字节;不得把旧 Generation 重发为有效;新读拒绝memory-management「写入提交」/「首次初始化」S12
TC-MEM-11[ ]类型化 Rent 未首次发布;或已 Ready 后 ROI 写入仅写 ROI 企图首次 Complete;或 ROI 写入中止首次须根范围覆盖全部逻辑像素后 Complete;未完成首次前拒绝不同范围初始化视图;任一写入中止 → 整实体 Invalid(不局限矩形);小 ROI Complete 不能把整份标回有效memory-management「首次初始化、ROI 写入中止与恢复」;image-model 根范围S12
TC-MEM-12[ ]内容已 Invalid带 expectedVersion 的 OpenWrite;以及无期望版本的完整范围恢复写带期望版本 → 拒绝(不授予);无期望版本的完整初始化范围写入 Complete 后可回到 Ready;框架无字节级回滚memory-management「首次初始化…恢复」S12
TC-MEM-13[ ]多实体并行归还;其一 releaseAsync 卡住或失败关闭触发清理;观察各项 ReturnCompleted / ReturnFailedreleaseAsync 恰好一次;一项卡住不串行阻塞其他存储归还;ReturnFailed → 不自动重试、不回可用池、不恢复访问;失败可观察memory-management「handle、异步等待与清理」S12

11. 显示集成 TC-DISP-*(阶段 F · Arden · R12)

语义权威见 image-display.md。显示契约仅 C#(控件封装 / UI 层);像素经绑定自 C++ vyntek::imaging。勿写成 C++ UI;勿与 T15 开放风险 R10(C++ UI·已关闭)互替。本表只做可勾选断言。不改 Diagnostic / T9 停止矩阵与 toolflow v1.9。场景骨架 S13。交叉:显示只观察见 TC-CTL-05(不扩 T9)。

ID勾前置动作期望 code / 状态对应章节场景
TC-DISP-01[ ]UI 线程;合法 IPixelImage(稳定或可写)SetImage / Source 登记同步取得独立 Share 并返回 ImageDisplayUpdate;不承诺已 OpenRead/已安装;可写输入须后台授予时才捕获image-display「请求登记与读取授予」S13
TC-DISP-02[ ]调用方持有有效图像;可多控件同图SetImage 成功后调用方 Dispose/Close 自有 handle;或另一控件再 SetImage 同图控件 不接管、不 Dispose 调用方传入 handle;Source 仅引用非所有权转移;Share 延长稳定内容寿命image-display「多窗口与所有权」S13
TC-DISP-03[ ]已以 RetainInput(默认)安装可写原图企图对同一 Buffer 原地 OpenWrite / 写入显示快照持稳定读 → 原地写入等待控件及其他读者退出;属性改 InputRetention 不偷偷改当前已装内容存储image-display「输入保留与显示副本」S13
TC-DISP-04[ ]以 Snapshot 提交并完成安装等待 InputReleased 后对原图写入;屏幕仍可显示旧图InputReleased 后控件不再阻止原图写入;Source 不因释放而置空;刷新须再次 SetImageimage-display「输入保留与显示副本」S13
TC-DISP-05[ ]当前为 RetainInput 已装 / 或在途候选update.DetachInputAsync;含预算不足路径成功 → Released 且 InputReleased 已完成,公开 CurrentImageInfo/CurrentVersion 保持来源身份;CpuBudgetExceeded → 不破坏当前内容及原图读取,可重试image-display「脱离和清空」S13
TC-DISP-06[ ]一次成功/失败更新在途分别观察 Completion、InputReleased、ImageRendered、底层 ReturnCompleted四信号互不等价:Installed ≠ Rendered;InputReleased 可先/后于 Completion;ImageRendered 可重复或从未发生;ReturnCompleted 属 SDK/owner 归还,≠ 控件 InputReleasedimage-display「回执、绘制和输入释放」S13
TC-DISP-07[ ]控件已有已装旧画面新请求 Failed(含 VersionMismatch / ReadFailed / UnsupportedImage 等)保留旧画面;失败回执 Info/Version 为空、带 Failure;不得让新 Source 信息与旧画面混合image-display「内部显示快照」/「回执」S13
TC-DISP-08[ ]当前已装 Gray8 / Rgb24 / Bgr24 / Depth16 之一TryGetPixel → TryGetGray8/Rgb24/Bgr24/Depth16仅格式相符时成功;无隐式跨格式转换;Depth 无效码仍可 TryGetDepth16(IsValid=false);TryGetDepthMeters 仅尺度已声明且有效时成功image-display「多格式像素查询」S13
TC-DISP-09[ ]已装含 ROI 偏移和/或负步长的图像TryGetPixel(viewPosition, …)按控件逆变换到逻辑像素坐标(ROI 内 X/Y);负步长/ROI 由临时读取封装处理;禁止用 viewPosition 直接作缓冲偏移;界外 → falseimage-display「多格式像素查询与坐标」S13
TC-DISP-10[ ]有在途候选/已装内容;含隐藏或零尺寸卸载控件;随后重挂载仍有效 Source;或图形 context 重建卸载:取消候选、清 UI 快照、通知 render 退出,安全排空异步完成(不 UI 同步死等);重挂载 = 新请求,不复用已失效读取;context 重建从显示副本/快照恢复,不改公开来源身份image-display「内部显示快照」/「多格式渲染」S13
TC-DISP-11[ ]已装旧图;新请求将超 CPU/GPU 预算SetImage / Snapshot 复制 / Detach 复制致预算不足登记 Failed(如 CpuBudgetExceeded);释放本次取得的引用;保留旧画面;不先丢旧图凑预算;无自动重试队列image-display「预算、线程与资源归还」S13
TC-DISP-12[ ]Run 在途或已结束;显示已挂卸图 / ClearImageAsync / Dispose ImageDisplay / 关显示宿主显示只观察:不停编排、不 RequestCancel、不停相机(交叉升格/对齐 TC-CTL-05;不扩 T9)image-display 文首 T9;toolflow §7.4.3;TC-CTL-05S13 / S05 / S07

12. 场景 S01–S13 映射(每场景 ≥1 条)

场景至少覆盖的契约 ID主期望(摘要)文档回链
S01TC-RUN-01、TC-REG-04、TC-LNK-08ok;Outputs 可读;Validate 无 Errorexamples-scenarios S01;§7.4 / §9.4
S02TC-RUN-02、TC-LNK-01、TC-LNK-03顺序链 ok;坏序 → OrderViolationS02;§4.1 / §5
S03TC-RUN-03、TC-H6、TC-REG-01、TC-RUN-05(薄)fake 流水线 Outputs 可读;观察不驱动 Run(细项见 S10 / TC-OUT-*)S03;§7.6.3 / §9.1;Arden · R9
S04TC-SER-02、TC-SER-03、TC-LNK-07、TC-SER-04SchemaTooNew / UnknownTypeId / MissingRequiredProperty;component 不拦 LoadS04;§6.5–6.6
S05TC-H1…TC-H9(主路径)、TC-CTL-05Complete→ReadOnly;显示仅 C#S05;§3.4
S06TC-CTL-01、TC-CTL-02、TC-CTL-03、TC-H10Cancelled / Aborted / Busy;H10S06;§4.3 / §7.4.3
S07TC-RUN-04、TC-SER-01、TC-CTL-05headless 批跑 ok;带显示宿主不改编排语义S07;§7.2–7.3; host-integration.md
S08TC-REG-01…TC-REG-06、TC-H2、TC-H8、TC-H10fake 注册 + 最小 ITool;未知 → UnknownTypeIdS08;§7.6
S09aTC-RUN-06、TC-LNK-04、TC-REG-05嵌套合法 ok;私有属性 → EncapsulationS09a;§9.3 / §7.4.6
S09bTC-LNK-06、TC-LNK-05SourceDisabled;InvalidBinding 主断言S09b;§4.3 / §7.4.6
S09cTC-SER-07、TC-CTL-04IoFailure;停相机 ≠ 自动 CancelS09c;§7.4.3 / §7.4.6
S09dTC-RUN-07、TC-LNK-01、TC-REG-05§9.2 两流终端串联 ok(可选)S09d;§9.2
S10TC-OUT-01…TC-OUT-09;TC-RUN-05(交叉)T10 集合事件可勾选;观察永不驱动 Run;KeepLatest vs ReleaseAfterRoutingS10;output-inspection; Arden · R9
S11TC-ACQ-01…TC-ACQ-07;TC-SESS-01…TC-SESS-05;交叉 TC-CTL-04持帧/Copy、TryPostOwned、满池预算、归还泵、Latest、回调不堵归还;停流结束条件、外保留、超时续清、ReturnFailed/断线、两端都停须显式S11;camera-acquisition;session-lifecycle; Arden · R10
S12TC-MEM-01…TC-MEM-13工厂接管;最后引用→Returning;禁等自身 ReturnCompleted;pin 阻写/归还;写 pin 阻 Complete;授予/取消与 Share/Dispose 原子;未 Complete→Invalid;首次根范围/ROI 中止整实体;Invalid 恢复;releaseAsync 一次与归还隔离/ReturnFailedS12;memory-management; Arden · R11
S13TC-DISP-01…TC-DISP-12;交叉 TC-CTL-05登记≠授予;Share 不接管;Retain/Snapshot/Detach;四回执互不等价;失败/VersionMismatch 保留旧图;四格式 TryGet 无隐式转换;ROI/负步长;卸载/重挂/context;预算失败不丢旧图;显示只观察S13;image-display; Arden · R12(仅 C#;≠ T15 R10)

13. Diagnostic 码覆盖清单(对照 §7.4.6)

Code本表代表契约出现于
TypeMismatchTC-LNK-02Validate / Link / Run 拉值
OrderViolationTC-LNK-03Validate / Link
EncapsulationTC-LNK-04Validate / Link;S09a
BusyTC-CTL-03Run
UnknownTypeIdTC-REG-03 / TC-SER-03Load / Create
SchemaTooNewTC-SER-02Load
IoFailureTC-SER-07Load / Save;S09c
SourceDisabledTC-LNK-06Run 拉值;S09b
InvalidBindingTC-LNK-05Validate / Load / Run;S09b
MissingRequiredPropertyTC-LNK-07Validate
AbortedTC-CTL-02Run
CancelledTC-CTL-01Run

成功路径期望:无上述 Error,或明确状态 ok / Outputs 可读 / Access=ReadOnly。

14. 非目标门禁(MVP 不得误交付)

ID勾断言(负向)对应
TC-NG-01[ ]无脚本引擎合入 MVP 交付面toolflow §10.2
TC-NG-02[ ]无 MPF_ToolBlock / .vpp 加载§1.2 / §10.2
TC-NG-03[ ]无 DAG 拓扑调度器;链接不是调度边§3.4 / §4.1 / §10.2
TC-NG-04[ ]无完整产线 IO 协议§10.2
TC-NG-05[ ]ImageDisplay 不是 C++ UI(显示契约仅 C#; Arden · R12 / ≠ T15 R10)csharp-binding / examples T12;image-display;TC-DISP-*

15. 与 §10.1 / T13 的关系

建议测试阶段(T13)本表章节
注册§1
建流§1(终端)+ §3 前置
Link / Validate§2
Run§3
Cancel / 失败中止§4
Load 复载§5
句柄 H1–H10§6
输出观察(T10)§7(TC-OUT-* · Arden · R9)
采集接入(阶段 D)§8(TC-ACQ-* · Arden · R10)
会话停流(阶段 D)§9(TC-SESS-* · Arden · R10)
存储/pin/归还(阶段 B)§10(TC-MEM-* · Arden · R11)
显示集成(阶段 F)§11(TC-DISP-* · Arden · R12;仅 C#;≠ T15 R10)
fake 注册与 headless§1 + §3(TC-RUN-03)+ §12(S03/S08/S10/S11/S12/S13)

§10.1 摘要仍留在 toolflow.md;全文可勾选契约以本文为准。场景骨架见 examples-scenarios.md(含 S09a–d / R6; S10 / Arden · R9; S11 / Arden · R10; S12 / Arden · R11; S13 / Arden · R12)。 Arden · R13:toolflow §10.1 T13 阶段索引已与上表 OUT/ACQ/SESS/MEM/DISP + S10–S13 对齐(仅索引/回链,不开新域)。

文档状态:测试契约草案(2026-10-21,Asia/Shanghai),对齐 toolflow v1.9(R4; R6 增 S09 映射 / TC-RUN-06·07; R7 S07↔host-integration; R8 术语索引; Arden · R9 增 TC-OUT- / S10; Arden · R10 增 TC-ACQ-* / TC-SESS-* / S11; Arden · R11 增 TC-MEM-* / S12; Arden · R12 增 TC-DISP-* / S13,显示仅 C#,≠ T15 R10; Arden · R13 §10.1 T13 索引对齐,本批横切收束)。实施以代码与本表勾选为准;不写覆盖率 KPI。*

本仓对拍

本表是可勾选契约迁入。实现是否够起草测试,看上面五份薄摘的「实现对拍状态」。没有一项在本表打勾。

单测覆盖度记录(2026-10-21 Asia/Shanghai)

按本文档 line 3 与五份薄摘的约定,单测通过 ≠ 本表验收通过(验收另需供应商适配、真实渲染 / GPU 预算 / context 重建等实机条件,见各薄摘「实现对拍状态」与 image-display.md:340)。故本表勾选列保持全 [ ] 未勾。以下只记录「哪些契约已有单测断言覆盖」,供验收时对照,不代表验收结论:

契约族条数单测覆盖位置验收仍缺
TC-REG / LNK / RUN / CTL / SER / H / NG6+8+7+5+7+10+5tests/orchestration_contracts.cpp供应商实机链路
TC-OUT9tests/smoke_headers.cpp同上
TC-ACQ7tests/smoke_headers.cpp(含本轮新增 03/04/05/06)供应商 SDK 适配未关(tc-acq.md:31)
TC-SESS5tests/smoke_headers.cpp(含本轮新增 01/03/04)实机停流时序
TC-MEM13tests/smoke_headers.cpp(含本轮新增 02/03/09)真实池压力
TC-DISP12bindings/csharp/Vyntek.Controls.Tests/(37 项)无 UI 框架:真实渲染 / GPU 预算 / context 重建不可验(image-display.md:340)

本轮验证口径:cmake --build --preset ninja-debug-tests 与 ninja-debug-shared 均构建通过、ctest 全绿;dotnet test 控件测试 37 项全过。TC-MEM-02/03/09、TC-ACQ-03/04/05/06、TC-SESS-01/03/04 为本轮新增断言,并经变异测试(故意注入缺陷后如期失败)确认具判别力,非恒真通过。

本轮同时修掉的实现缺陷:TC-DISP-04 的 Snapshot 策略此前未做像素私有副本(只 Dispose 读视图却仍持原图 Share 就发 InputReleased),违反 image-display.md:159/168;已新增 ManagedPixelCopy 物化副本并在安装后关闭原图引用,像素隔离断言改为真实断言(改写调用方像素后控件仍返回旧值)。

已修(原记债项):DetachInputAsync 把 RetainInput 转 Snapshot 的路径已物化私有副本——三阶段实现(锁内校验+原子预留预算 → 锁外物化副本,符合「复制仍在后台完成」→ 锁内以 _generation + ReferenceEquals 双重校验后 AdoptPrivateCopy 换入副本并关闭原引用)。并发脱离复用同一份工作(后到者 JOIN 同一 Task,预算只计一次),陈旧或失败路径按语义退还预留。回归测试见 TC_DISP_05b/05c/05d,其中 05d 用取样门做确定性会合,并经变异验证(禁用复用后如期失败于「B must wait on A's in-flight work」,即双重计费被当场捕获)。

On this page