diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..362ddc7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +* text=auto eol=lf +*.png binary +*.jpg binary +*.jpeg binary diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..900f719 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,18 @@ +name: validate + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + repository: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - run: python scripts/validate_repository.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..46453c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +__pycache__/ +*.pyc +*.blend1 +*.blend2 +*.log +.DS_Store +Thumbs.db +vendor-cad/ +*.step +*.stp diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..0d82986 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,10 @@ +cff-version: 1.2.0 +message: "If OpticalModeler helps your optical-path workflow, cite this repository." +title: "OpticalModeler: A Physically Auditable Blender Optical-Path Skill" +type: software +authors: + - family-names: "telux" +repository-code: "https://github.com/k-telux/OpticalModeler" +license: MIT +version: 1.0.0 +date-released: 2026-07-15 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..352db6a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing + +Contributions are welcome when they improve transferable optical, mechanical, or evidence rules. + +1. Open an issue describing the experimental role, hardware family, failure mode, and evidence. +2. Keep one rule per change and distinguish universal guidance from scene-specific measurements. +3. Add or update a representative case only when the saved-scene readback and visual evidence agree. +4. Do not commit vendor CAD, credentials, private laboratory documents, raw agent conversations, or absolute local paths. +5. Run `python scripts/validate_repository.py` before opening a pull request. + +Rule changes must preserve fail-closed semantics. If the evidence cannot prove an assembly, use `UNVERIFIED`; do not weaken a global gate to make one example pass. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c5204f4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 k-telux + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.ja.md b/README.ja.md new file mode 100644 index 0000000..cd8f43e --- /dev/null +++ b/README.ja.md @@ -0,0 +1,45 @@ +
+ +# OpticalModeler + +**2D 光学回路図から、物理的に監査可能な Blender 光学テーブルへ。** + +[English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) + +[![Validation](https://github.com/k-telux/OpticalModeler/actions/workflows/validate.yml/badge.svg)](https://github.com/k-telux/OpticalModeler/actions/workflows/validate.yml) +[![Agent Skills](https://img.shields.io/badge/Agent%20Skills-compatible-111827)](https://agentskills.io/) +[![License: MIT](https://img.shields.io/badge/License-MIT-2563EB.svg)](LICENSE) + +物理監査済み G1/G2 光学テーブルの Nature スタイルレンダー + +
+ +OpticalModeler は、実験室の光路を Blender で再構築する証拠優先の Agent Skill です。光学トポロジー、実開口、メーカー CAD、締結部、荷重経路、ファイバー配線、証拠の系譜を必須の受け入れゲートとして扱います。 + +> **独立したコミュニティプロジェクトです。** Thorlabs, Inc. との提携・承認関係はありません。製品名は互換ハードウェアの識別にのみ使用します。レンダリングされた CAD は、機械・分光・レーザー安全・実験性能の認証ではありません。 + +## 主な特徴 + +| 物理アセンブリ | 光学的整合性 | Fail-closed 証拠 | +|---|---|---| +| ポスト優先配置、実テーブル穴、締結部、荷重経路。 | 開口中心、ビームスプリッター面、分岐連続性、内部細線ビーム、ファイバー曲率。 | 再オープン監査、レイ/BVH 検査、ハッシュ、マニフェスト、注釈付きレンダー、明示的な状態。 | + +## 2D 入力 → 検証済み 3D 出力 + +| 元の光学回路図 | 注釈付き 3D 再構築 | +|---|---| +| 元の G1/G2 回路図 | 3D 光学テーブルの注釈付き上面図 | + +匿名化済みの [G1/G2 ケーススタディ](examples/g1g2/README.md)には、2D 入力、3D レンダー、機械可読の受け入れ記録が含まれます。メーカー STEP/CAD と大容量の実験用 `.blend` は Git に含めません。 + +## インストール + +```bash +npx skills add k-telux/OpticalModeler +``` + +または `skills/thorlabs-blender-optical-path` を Agent の skills ディレクトリへコピーします。 + +英語版 Skill が技術的な正本です。[日本語 Skill](i18n/ja/SKILL.md) は日本語の入口を提供し、形状・証拠ルールは英語版を継承します。 + +Maintainer: [telux](https://github.com/k-telux) · [MIT License](LICENSE) diff --git a/README.md b/README.md index 6f2177e..d86d53a 100644 --- a/README.md +++ b/README.md @@ -1 +1,88 @@ -# OpticalModeler \ No newline at end of file +
+ +# OpticalModeler + +**From 2D photonics schematics to physically auditable Blender optical tables.** + +[English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) + +[![Validation](https://github.com/k-telux/OpticalModeler/actions/workflows/validate.yml/badge.svg)](https://github.com/k-telux/OpticalModeler/actions/workflows/validate.yml) +[![Agent Skills](https://img.shields.io/badge/Agent%20Skills-compatible-111827)](https://agentskills.io/) +[![Blender](https://img.shields.io/badge/Blender-4.x-E87D0D?logo=blender&logoColor=white)](https://www.blender.org/) +[![License: MIT](https://img.shields.io/badge/License-MIT-2563EB.svg)](LICENSE) + +Nature-style render of a physically audited G1/G2 optical table + +
+ +OpticalModeler is an evidence-first Agent Skill for reconstructing laboratory optical paths in Blender. It treats optical topology, real apertures, manufacturer CAD, fasteners, load paths, fiber routing, and artifact lineage as hard acceptance gates—not decorative details. + +> **Independent community project.** Not affiliated with or endorsed by Thorlabs, Inc. Product names identify compatible hardware only. A rendered CAD assembly is not a mechanical, spectral, laser-safety, or experimental certification. + +## Why OpticalModeler + +| Physical assembly | Optical truth | Fail-closed evidence | +|---|---|---| +| Post-first placement, real table holes, fasteners, load paths, and supported hardware. | Centered apertures, splitter planes, branch continuity, internal fine beams, and fiber bend constraints. | Reopened-scene audits, ray/BVH checks, hashes, manifests, annotated renders, and explicit `PASS` / `BLOCKED` / `UNVERIFIED` states. | + +## 2D input → verified 3D output + +| Original schematic | Annotated 3D reconstruction | +|---|---| +| Original G1/G2 schematic | Annotated top view of the reconstructed optical table | + +The sanitized [G1/G2 case study](examples/g1g2/README.md) includes the original 2D input, editorial 3D renders, and a machine-readable acceptance record. Vendor STEP/CAD files and the large laboratory `.blend` are intentionally excluded. + +## Install + +With a compatible Agent Skills installer: + +```bash +npx skills add k-telux/OpticalModeler +``` + +Or copy `skills/thorlabs-blender-optical-path` into your agent's skills directory. + +## Quick start + +```text +Use $thorlabs-blender-optical-path to reconstruct this pump-probe schematic in Blender and produce a fail-closed physical audit. +``` + +```text +Audit this optical table for real post/load paths, centered apertures, beam clearance, fiber bend radius, and stale evidence. +``` + +The skill guides the agent to: + +1. map schematic nodes to experimental roles, real assets, ports, and support paths; +2. solve optical centers, surfaces, splitter planes, and branch continuity; +3. assemble hardware post-first from verified table holes; +4. prove one representative instance before propagation; +5. reopen the saved scene and run mesh, ray, and BVH checks; +6. package visual, GLB, report, manifest, hash, and rule-compliance evidence consistently. + +## Repository map + +```text +skills/thorlabs-blender-optical-path/ canonical English skill +i18n/zh-CN/ Simplified Chinese edition +i18n/ja/ Japanese edition +rules/ reusable project-memory template +examples/g1g2/ sanitized 2D-to-3D case study +scripts/validate_repository.py dependency-free release gate +``` + +The English skill is the technical source of truth. Localized editions are maintained as language entry points and explicitly defer to the canonical geometry and evidence references. + +## Validation and limits + +- Manufacturer CAD is an asset source, never proof of correct assembly. +- Free-space rays, guided fiber, and electrical cables remain semantically distinct. +- Whole-project success requires an active-rule compliance matrix; scoped evidence stays `PARTIAL/SCOPED`. +- The repository excludes third-party CAD, private paths, oversized Blend files, and unsupported real-world performance claims. +- Every release is checked for skill metadata, links, file size, privacy leaks, forbidden CAD binaries, and acceptance-state consistency. + +See [CONTRIBUTING.md](CONTRIBUTING.md) for rule proposals and case-study submissions, and [SECURITY.md](SECURITY.md) for responsible disclosure. + +Maintained by [telux](https://github.com/k-telux). Released under the [MIT License](LICENSE). diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..0a31c27 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,51 @@ +
+ +# OpticalModeler + +**从二维光路示意图到可物理审计的 Blender 光学平台。** + +[English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) + +[![Validation](https://github.com/k-telux/OpticalModeler/actions/workflows/validate.yml/badge.svg)](https://github.com/k-telux/OpticalModeler/actions/workflows/validate.yml) +[![Agent Skills](https://img.shields.io/badge/Agent%20Skills-compatible-111827)](https://agentskills.io/) +[![License: MIT](https://img.shields.io/badge/License-MIT-2563EB.svg)](LICENSE) + +经过物理审计的 G1/G2 光学平台 Nature 风格渲染 + +
+ +OpticalModeler 是一个证据优先的 Agent Skill,用于在 Blender 中重建实验室光路。它把光路拓扑、真实孔径、厂家 CAD、紧固件、承载链、光纤布线和证据血缘作为硬性验收门槛,而不是装饰细节。 + +> **独立社区项目。** 与 Thorlabs, Inc. 无隶属或背书关系。产品名称仅用于识别兼容硬件。渲染的 CAD 装配不构成机械、光谱、激光安全或实验性能认证。 + +## 核心能力 + +| 物理装配 | 光学真实性 | Fail-closed 证据 | +|---|---|---| +| 立柱优先、真实台孔、紧固件、承载链与受支撑硬件。 | 孔径居中、分束平面、支路连续、内部细束与光纤弯曲约束。 | 重开场景审计、光线/BVH 检查、哈希、清单、标注渲染与明确状态。 | + +## 二维输入 → 已验证三维输出 + +| 原始光路图 | 标注后的三维重建 | +|---|---| +| 原始 G1/G2 光路图 | 三维光学平台标注俯视图 | + +脱敏的 [G1/G2 案例](examples/g1g2/README.md)包含二维原始输入、编辑级三维渲染和机器可读验收记录。厂家 STEP/CAD 与大型实验 `.blend` 不进入 Git。 + +## 安装 + +```bash +npx skills add k-telux/OpticalModeler +``` + +也可以把 `skills/thorlabs-blender-optical-path` 复制到 Agent 的 skills 目录。 + +## 调用示例 + +```text +使用 $thorlabs-blender-optical-path 把这张 pump-probe 示意图重建为 Blender 光学平台,并生成 fail-closed 物理审计。 +``` + +英文 Skill 是技术权威源;[简体中文 Skill](i18n/zh-CN/SKILL.md)提供中文入口,并明确继承英文版的几何与证据合同。仓库还包含[项目规则模板](rules/OPTICAL_PATH_PROJECT_MEMORY_TEMPLATE.md)和无第三方依赖的发布验证器。 + +维护者:[telux](https://github.com/k-telux) · [MIT License](LICENSE) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..33052d4 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security and safety + +Report credential exposure or unsafe automation privately through GitHub's security-advisory interface. + +This project produces modeling and audit guidance, not laser-safety, structural, electrical, or manufacturer certification. Validate real hardware with the relevant datasheets, laboratory procedures, qualified personnel, and calibrated measurements. diff --git a/examples/g1g2/README.md b/examples/g1g2/README.md new file mode 100644 index 0000000..1da313f --- /dev/null +++ b/examples/g1g2/README.md @@ -0,0 +1,12 @@ +# G1/G2 reconstruction example + +This sanitized case study shows the transformation from a 2D pump-probe/G1/G2 schematic to a verified editorial 3D optical-table render. + +| Stage | Artifact | +|---|---| +| 2D input | [fig_s17_componentlibrary_g1g2.png](input/fig_s17_componentlibrary_g1g2.png) | +| 3D hero | [v18_nature_hero_graphite_final_4k_preview.jpg](output/v18_nature_hero_graphite_final_4k_preview.jpg) | +| Annotated top view | [v18_nature_complete_top_annotated_final_4k_preview.jpg](output/v18_nature_complete_top_annotated_final_4k_preview.jpg) | +| Acceptance | [v18_nature_final_acceptance.json](evidence/v18_nature_final_acceptance.json) | + +The example proves workflow output and evidence packaging. It does not ship or license the source laboratory Blend or manufacturer CAD, and it does not certify real-world mechanical fit or spectral performance. diff --git a/examples/g1g2/evidence/v18_nature_final_acceptance.json b/examples/g1g2/evidence/v18_nature_final_acceptance.json new file mode 100644 index 0000000..9f3f966 --- /dev/null +++ b/examples/g1g2/evidence/v18_nature_final_acceptance.json @@ -0,0 +1,26 @@ +{ + "schema": "g1g2_v18_public_example_acceptance_v1", + "status": "PASS_V18_NATURE_FINAL_VERIFIED", + "geometry_revision": "v18 fixed STEP leaf-solid mesh; geometry frozen during Nature rendering", + "render": { + "engine": "Cycles", + "samples": 96, + "master_resolution": [4096, 2304], + "annotated_resolution": [4096, 3072], + "public_artifacts": "compressed preview copies" + }, + "gates": { + "render_geometry_signature_unchanged": true, + "opencv_image_qa": "PASS_V18_NATURE_IMAGE_QA", + "saved_blend_reopen": "PASS_V18_NATURE_FINAL_REOPEN", + "independent_publication_review": "PASS_3_OF_3_NATURE_REVIEWERS", + "p0_count": 0, + "p1_count": 0 + }, + "public_release_limits": { + "vendor_cad_included": false, + "laboratory_blend_included": false, + "mechanical_or_spectral_certification": false + }, + "blockers": [] +} diff --git a/examples/g1g2/input/fig_s17_componentlibrary_g1g2.png b/examples/g1g2/input/fig_s17_componentlibrary_g1g2.png new file mode 100644 index 0000000..2a317f5 Binary files /dev/null and b/examples/g1g2/input/fig_s17_componentlibrary_g1g2.png differ diff --git a/examples/g1g2/output/v18_nature_complete_top_annotated_final_4k_preview.jpg b/examples/g1g2/output/v18_nature_complete_top_annotated_final_4k_preview.jpg new file mode 100644 index 0000000..4f0ad7d Binary files /dev/null and b/examples/g1g2/output/v18_nature_complete_top_annotated_final_4k_preview.jpg differ diff --git a/examples/g1g2/output/v18_nature_hero_graphite_final_4k_preview.jpg b/examples/g1g2/output/v18_nature_hero_graphite_final_4k_preview.jpg new file mode 100644 index 0000000..e82a54d Binary files /dev/null and b/examples/g1g2/output/v18_nature_hero_graphite_final_4k_preview.jpg differ diff --git a/i18n/ja/SKILL.md b/i18n/ja/SKILL.md new file mode 100644 index 0000000..0a6ecce --- /dev/null +++ b/i18n/ja/SKILL.md @@ -0,0 +1,33 @@ +--- +name: thorlabs-blender-optical-path-ja +description: 2D 光学回路図とメーカー CAD から、物理的に妥当な Blender 光学テーブルを構築・監査・改訂します。Thorlabs 互換ミラーマウント、レンズマウント、ビームスプリッター、ポスト、ファイバー結合、開口、検出器、光学トポロジー、fail-closed 証拠、Nature スタイル描画に使用します。 +--- + +# Thorlabs Blender Optical Path + +2D 回路図を、説明可能で独立監査可能な Blender 光学テーブルへ変換します。 + +英語版を技術的な正本とします。形状作業の前に `../../skills/thorlabs-blender-optical-path/references/physical-gates.md`、合否判定の前に `evidence-contract.md`、既存シーンの改訂では `history-derived-rules.md`、実例では `project-case-study.md` を読みます。 + +## 権限と改訂 + +1. システム制約、最新のユーザー指示・注釈画像、active なプロジェクト規則、本 Skill、旧成果物・旧 PASS の順に優先します。 +2. 合格済み成果物を凍結し、修正ごとに新しい revision を作ります。 +3. 共有 Blender generator は single-writer とし、補助 agent は既定で read-only です。 +4. 画像指摘を object family、world-space geometry、数値ゲート、必要証拠へ変換します。 +5. 実形状で証明できない場合は `UNVERIFIED` または `BLOCKED` とします。CAD の存在、process success、AABB 接触、自己申告は証拠ではありません。 + +## コア手順 + +1. `schematic node -> experimental role -> real asset -> optical/fiber/electrical ports -> support path` を作成します。 +2. 全 branch、部品、光線高さ、開口、検出端点を列挙します。 +3. 公式 CAD の型番、URL、SHA-256、scale、bbox、local axis/normal、aperture、provenance を記録します。 +4. 光学中心、鏡面、分割面、反射、branch continuity を先に解きます。 +5. 実テーブル穴から fastener、clamp、holder、post、mount、device を post-first で組みます。 +6. 共通の配置原因を修正し、代表 1 台を証明してから展開し、保存後に全コピーを再監査します。 +7. beauty render より先に明るい mechanical/axial/cutaway 監査画像を作ります。 +8. reopen、ray/BVH、OpenCV、GLB reimport、report、manifest、hash、active-rule matrix を完了します。 + +自由空間光、ガイドファイバー、電気ケーブルは別 family とします。開口は実際に開いていなければなりません。物理 PASS 後にのみ Nature スタイルの材質、照明、カメラ、注釈を変更できます。 + +`PASS` は全適用ゲートの新しい証拠、`PARTIAL/SCOPED` は限定範囲、`UNVERIFIED` は証拠不足、`BLOCKED` は既知の失敗を表します。 diff --git a/i18n/zh-CN/SKILL.md b/i18n/zh-CN/SKILL.md new file mode 100644 index 0000000..be6b898 --- /dev/null +++ b/i18n/zh-CN/SKILL.md @@ -0,0 +1,33 @@ +--- +name: thorlabs-blender-optical-path-zh +description: 从二维光路示意图与厂家 CAD 构建、审核和修订具有物理可信度的 Blender 光学平台。适用于 Thorlabs 兼容镜架、透镜架、分束器、支柱、光纤耦合、孔径、探测器、完整光路拓扑、fail-closed 证据和 Nature 风格光子学渲染。 +--- + +# Thorlabs Blender 光路 + +把二维示意图转换成可解释、可独立审计的 Blender 光学平台。 + +英文版是技术权威源。涉及几何时读取 `../../skills/thorlabs-blender-optical-path/references/physical-gates.md`;验收前读取 `evidence-contract.md`;修订旧场景时读取 `history-derived-rules.md`;完整案例见 `project-case-study.md`。 + +## 权威与版本 + +1. 系统约束优先;随后是用户最新文字或标注截图、项目 active rules、本 skill,最后才是旧产物和旧 PASS。 +2. 冻结已验收版本;每次纠正新建 revision,不覆盖旧证据。 +3. 共享 Blender 生成器保持单写入,副 agent 默认只读。 +4. 把每个截图问题转换为对象族、世界坐标几何、数值门槛和必需证据。 +5. 无法证明时使用 `UNVERIFIED` 或 `BLOCKED`。文件存在、CAD 导入、进程成功、AABB 接触和自报文本都不是证据。 + +## 核心流程 + +1. 建立 `schematic node -> 实验角色 -> 真实资产 -> 光/光纤/电端口 -> 支撑路径`。 +2. 列出全部分支、器件、光束高度、孔径和探测终点。 +3. 记录官方 CAD 的型号、来源、SHA-256、尺度、bbox、局部光轴、法向、孔径和 provenance;替代件必须明示。 +4. 先解光心、镜面、分束面、反射和分支连续性。 +5. 再从真实桌孔向上按 post-first 构建紧固件、夹具、holder、post、mount 和器件。 +6. 修共享根因,先验一个代表件,再传播;保存后重开并逐件复核。 +7. 先做明亮的机械/轴向/剖切审计图,再做 beauty render。 +8. 完成重开、ray/BVH、OpenCV、GLB 回导、报告、manifest、hash 和全 active-rule 合规矩阵。 + +光束、柔性光纤和电缆必须是不同对象族。孔径必须真实开放。删除重复 surrogate 和无角色 placeholder。Nature 风格只能在物理门槛通过后修改材质、灯光、相机和排版,不能替代装配证据。 + +状态:`PASS` 表示所有适用规则有新鲜证据;`PARTIAL/SCOPED` 只代表局部;`UNVERIFIED` 表示证据不足;`BLOCKED` 表示已知失败。禁止把局部通过写成整机最终通过。 diff --git a/rules/OPTICAL_PATH_PROJECT_MEMORY_TEMPLATE.md b/rules/OPTICAL_PATH_PROJECT_MEMORY_TEMPLATE.md new file mode 100644 index 0000000..c5626fa --- /dev/null +++ b/rules/OPTICAL_PATH_PROJECT_MEMORY_TEMPLATE.md @@ -0,0 +1,46 @@ +# Optical Path Project Memory + +## Metadata + +- Ruleset: `PROJECT-YYYY.MM.DD-r1` +- Updated: `YYYY-MM-DD timezone` +- Current revision: `revision-id` +- Frozen baseline: `revision-id or none` +- Current state: `BLOCKED | UNVERIFIED | PARTIAL_SCOPED | PASS` +- Governing skill: `thorlabs-blender-optical-path` + +This file is the project-local source of truth. Register new user corrections here before or together with the next revision. + +## Authority + +1. System/developer constraints. +2. Newest explicit user wording or annotated screenshot. +3. Active project rules in this file. +4. General optical-path skill. +5. Older artifacts, audits, or PASS labels. + +Preserve replaced rules as `superseded`; never silently delete history. + +## Active rules + +| Rule ID | Severity | Scope | Rule | Required evidence | Status | +|---|---|---|---|---|---| +| EXAMPLE-001 | P0 | all | Replace this row with one atomic rule. | JSON field and view path | active | + +## Latest overrides + +### YYYY-MM-DD / revision + +- Add the newest user correction here. +- State which older rule or acceptance claim it supersedes. +- Keep one writer for shared geometry and freeze the old package. + +## Required rule-compliance matrix + +Every final audit records `ruleset_version`, `ruleset_sha256`, `latest_user_command_at`, `audit_scope`, `rule_compliance[]`, and `unresolved_conflicts[]`. + +Whole-system PASS requires `FULL_ACTIVE_RULE_REGRESSION`. A delta-only audit is `PARTIAL_SCOPED`. + +## Changelog + +- `YYYY-MM-DD r1`: initialized project memory. diff --git a/scripts/validate_repository.py b/scripts/validate_repository.py new file mode 100644 index 0000000..cab1fe6 --- /dev/null +++ b/scripts/validate_repository.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Validate the public skill repository with the Python standard library.""" + +from __future__ import annotations + +import json +import re +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +SKILLS = { + ROOT / "skills/thorlabs-blender-optical-path/SKILL.md": "thorlabs-blender-optical-path", + ROOT / "i18n/zh-CN/SKILL.md": "thorlabs-blender-optical-path-zh", + ROOT / "i18n/ja/SKILL.md": "thorlabs-blender-optical-path-ja", +} +REQUIRED = [ + ROOT / "LICENSE", + ROOT / "README.md", + ROOT / "README.zh-CN.md", + ROOT / "README.ja.md", + ROOT / "rules/OPTICAL_PATH_PROJECT_MEMORY_TEMPLATE.md", + ROOT / "examples/g1g2/input/fig_s17_componentlibrary_g1g2.png", + ROOT / "examples/g1g2/output/v18_nature_hero_graphite_final_4k_preview.jpg", + ROOT / "examples/g1g2/output/v18_nature_complete_top_annotated_final_4k_preview.jpg", + ROOT / "examples/g1g2/evidence/v18_nature_final_acceptance.json", +] +FORBIDDEN_SUFFIXES = {".blend", ".blend1", ".blend2", ".step", ".stp"} +MAX_FILE_BYTES = 10 * 1024 * 1024 + + +def check_frontmatter(path: Path, expected_name: str) -> None: + text = path.read_text(encoding="utf-8") + match = re.match(r"\A---\s*\n(.*?)\n---\s*\n", text, re.S) + assert match, f"missing YAML frontmatter: {path}" + block = match.group(1) + name = re.search(r"(?m)^name:\s*(.+?)\s*$", block) + description = re.search(r"(?m)^description:\s*(.+?)\s*$", block) + assert name and name.group(1).strip('"') == expected_name, f"wrong name: {path}" + assert description and len(description.group(1).strip()) >= 40, f"short description: {path}" + + +def check_markdown_links(path: Path) -> None: + text = path.read_text(encoding="utf-8") + for target in re.findall(r"!?\[[^\]]*\]\(([^)]+)\)", text): + target = target.strip().strip("<>").split("#", 1)[0] + if not target or re.match(r"^(https?://|mailto:)", target): + continue + resolved = (path.parent / target).resolve() + assert resolved.exists(), f"broken link in {path}: {target}" + + +def main() -> None: + for path in REQUIRED: + assert path.exists(), f"missing required file: {path.relative_to(ROOT)}" + + for path, expected_name in SKILLS.items(): + check_frontmatter(path, expected_name) + + files = [path for path in ROOT.rglob("*") if path.is_file() and ".git" not in path.parts] + for path in files: + assert path.suffix.lower() not in FORBIDDEN_SUFFIXES, f"forbidden binary asset: {path}" + assert path.stat().st_size <= MAX_FILE_BYTES, f"file exceeds 10 MiB: {path}" + if path.suffix.lower() in {".md", ".yml", ".yaml", ".json", ".cff"}: + text = path.read_text(encoding="utf-8") + assert not re.search(r"[A-Za-z]:[\\/]Users[\\/]", text), f"private Windows path: {path}" + if path.suffix.lower() == ".md": + check_markdown_links(path) + + acceptance = json.loads((ROOT / "examples/g1g2/evidence/v18_nature_final_acceptance.json").read_text(encoding="utf-8")) + assert acceptance["status"] == "PASS_V18_NATURE_FINAL_VERIFIED" + assert acceptance["gates"]["p0_count"] == 0 + assert acceptance["gates"]["p1_count"] == 0 + print(f"PASS: {len(files)} files, {len(SKILLS)} skill editions, public example verified") + + +if __name__ == "__main__": + main() diff --git a/skills/thorlabs-blender-optical-path/SKILL.md b/skills/thorlabs-blender-optical-path/SKILL.md new file mode 100644 index 0000000..93853bb --- /dev/null +++ b/skills/thorlabs-blender-optical-path/SKILL.md @@ -0,0 +1,54 @@ +--- +name: thorlabs-blender-optical-path +description: Build, audit, and revise physically plausible Blender optical-table figures from 2D schematics and manufacturer CAD. Use for Thorlabs-compatible mirrors, lens mounts, beamsplitters, posts, fiber launches, apertures, detectors, optical topology, fail-closed evidence, or Nature-style photonics renders. +--- + +# Thorlabs Blender Optical Path + +Convert a 2D optical schematic into a physically explainable, independently auditable Blender scene. + +## Load the relevant references + +- Read [physical-gates.md](references/physical-gates.md) before geometry, CAD placement, or mechanical review. +- Read [evidence-contract.md](references/evidence-contract.md) before declaring any PASS or preparing a release. +- Read [history-derived-rules.md](references/history-derived-rules.md) when revising an existing scene or when old fixes may have regressed. +- Read [project-case-study.md](references/project-case-study.md) for the complete G1/G2 2D-to-3D example. + +## Authority and revision rules + +1. Apply system constraints first, then the newest explicit user wording or annotated screenshot, then active project rules, then this general skill, and only then older artifacts or PASS labels. +2. Freeze an accepted package. Start a new revision for every correction; never overwrite the prior evidence package. +3. Keep one writer for the shared Blender generator. Use helpers as read-only optical, mechanical, CAD, evidence, and visual reviewers unless an isolated write scope is explicit. +4. Translate every correction into object families, world-space geometry, a measurable gate, and required evidence before editing. +5. Use `BLOCKED` or `UNVERIFIED` when real geometry or evidence is missing. File existence, imported CAD, process success, labels, AABB contact, and self-reported text are not proof. + +## Core workflow + +1. Build a machine-readable map: `schematic node -> experimental role -> real asset -> optical/fiber/electrical ports -> support path`. +2. Inventory every branch, component, beam segment, beam height, aperture, connector, and required detector endpoint. +3. Acquire official CAD when licensing permits. Record part number, source URL, SHA-256, unit scale, bbox, local optical axis, surface normal, aperture, and provenance. Mark modeled or surrogate parts explicitly. +4. Solve optical constraints first: centers, surface normals, reflection, splitting planes, branch endpoints, and zero-radius clearance. +5. Solve mechanics post-first from verified table holes through real fasteners, clamps, holders, posts, mount faces, and device interfaces. +6. Fix the shared placement or transform root cause. Prove one representative repeated assembly before propagation, then reopen and recheck every copy. +7. Render bright audit views before beauty views. Use cutaways or transparency only to expose hidden, already-measured interfaces. +8. Complete the saved-scene, visual, export, document, hash, and rule-compliance gates in the evidence contract. + +## Required semantic separation + +- Treat free-space optical rays, guided fiber, and electrical/coaxial cables as different object families, materials, ports, and audit records. +- Terminate free-space light at the physical coupling surface; continue only the guided fiber from the ferrule/FC interface. +- Use open geometry for apertures and slits. A centered ray through an opaque disk is a collision, not a PASS. +- Remove duplicate surrogates and unexplained placeholders after the real or declared modeled assembly exists. + +## Publication rendering + +After physical gates pass, produce a clean editorial scene with restrained metals, readable black-anodized edges, physically modest glass, thin emissive beam cores, soft halos, and uncluttered labels. Preserve topology and geometry while changing camera, lighting, materials, or presentation. Nature-style appearance never replaces mechanical evidence. + +## Completion language + +- `PASS`: every applicable active gate has fresh evidence. +- `PARTIAL/SCOPED`: only a declared subset was audited. +- `UNVERIFIED`: required evidence is missing or cannot distinguish the claim. +- `BLOCKED`: a known requirement fails. + +Never promote `PARTIAL/SCOPED` to whole-system PASS. diff --git a/skills/thorlabs-blender-optical-path/agents/openai.yaml b/skills/thorlabs-blender-optical-path/agents/openai.yaml new file mode 100644 index 0000000..ae3d06c --- /dev/null +++ b/skills/thorlabs-blender-optical-path/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "OpticalModeler" + short_description: "Build and audit physical Blender optical tables" + default_prompt: "Use $thorlabs-blender-optical-path to reconstruct this optical schematic as a physically auditable Blender scene." diff --git a/skills/thorlabs-blender-optical-path/references/evidence-contract.md b/skills/thorlabs-blender-optical-path/references/evidence-contract.md new file mode 100644 index 0000000..a5e6094 --- /dev/null +++ b/skills/thorlabs-blender-optical-path/references/evidence-contract.md @@ -0,0 +1,71 @@ +# Evidence contract + +## Contents + +1. Scope and lineage +2. Representative-to-global loop +3. Required evidence +4. Rule-compliance record +5. Fail-closed decisions + +## Scope and lineage + +- Freeze accepted revisions and build new corrections in a new directory. +- Any geometry, scene, export, report, or evidence write invalidates all dependent downstream checks. +- Record the user-command source, ruleset version/hash, generator hash, scene hash, and audit scope. +- Use `FULL_ACTIVE_RULE_REGRESSION` for whole-system PASS. Use `PARTIAL_SCOPED` for a delta-only audit. + +## Representative-to-global loop + +1. Fix the shared placement/transform root cause. +2. Validate one representative repeated assembly with real mesh, section, ray, and BVH evidence. +3. Inspect a side/oblique load-path view plus a bright axial/cutaway view. +4. Propagate only the verified transform. +5. Reopen the saved scene and recheck every copy plus global neighbor collisions. + +## Required evidence + +- machine-readable topology and role inventory; +- official/modeled/surrogate provenance with hashes and unit scale; +- saved-Blend reopen and world-space transform/mesh readback; +- zero-radius optical-axis and first-opaque-hit checks; +- narrow-phase BVH with allowed contact envelopes separated from illegal collision; +- close-up mechanical views and complete table views; +- role-specific OpenCV or equivalent visual checks; +- empty-scene GLB reimport when GLB is delivered; +- readable PDF/README, manifest, and independently checked hashes; +- status agreement across all artifacts. + +Do not substitute generator-time self-report, AABB-only overlap, process success, or a beauty render for these gates. + +## Rule-compliance record + +```json +{ + "ruleset_version": "project ruleset id", + "ruleset_sha256": "sha256", + "latest_user_command_at": "timestamp or source turn", + "audit_scope": "FULL_ACTIVE_RULE_REGRESSION", + "rule_compliance": [ + { + "rule_id": "MECH-POST-FIRST", + "applicable": true, + "verdict": "PASS", + "evidence": ["relative/path/to/audit.json#field"], + "notes": "measured result" + } + ], + "unresolved_conflicts": [] +} +``` + +The manifest repeats the ruleset, scope, rule-gate status, conflicts, and artifact hashes. + +## Fail-closed decisions + +- `PASS`: every applicable active rule has fresh, independent evidence. +- `PARTIAL/SCOPED`: the declared subset passes; no whole-system claim is allowed. +- `UNVERIFIED`: evidence cannot establish the claim. +- `BLOCKED`: a known rule fails. + +Any stale hash, unresolved conflict, inconsistent status, missing P0 evidence, or unverified physical interface blocks a final release. diff --git a/skills/thorlabs-blender-optical-path/references/history-derived-rules.md b/skills/thorlabs-blender-optical-path/references/history-derived-rules.md new file mode 100644 index 0000000..14d9c6b --- /dev/null +++ b/skills/thorlabs-blender-optical-path/references/history-derived-rules.md @@ -0,0 +1,63 @@ +# History-derived rules + +## Contents + +1. Source and privacy boundary +2. Revision timeline +3. Recurring failures +4. Durable management rules +5. Publication-render lessons + +## Source and privacy boundary + +The originating G1/G2 build session contained 162 user-role records and 513 assistant-role records across repeated correction, audit, and rendering cycles. This document preserves durable decisions and failure patterns. It intentionally excludes raw private conversation, local absolute paths, credentials, and one-off coordinates. + +## Revision timeline + +| Revision phase | Durable result | +|---|---| +| Initial layout | Reconstruct the declared 2D topology before beautification; do not treat a table-only export as a completed optical system. | +| v1-v4 | Manufacturer CAD orientation and optical axes must be measured. Switch from mount-first placement to post-first physical assembly. | +| v5 | Prove the MBT/RMS objective, FC/ferrule/boot chain, and one representative launch before copying four assemblies. | +| v6 | Separate free-space beams, guided fiber, and electrical cables. Audit fiber bend radius and strain relief. | +| v7-v10 | Repair disconnected branches, semantic asset mismatches, closed apertures, impossible splitter geometry, and hidden collisions. | +| v11-v12 | Preserve accepted table mesh/material structure; prove clamp fasteners in real holes; add reopen, OpenCV, GLB-reimport, PDF, and manifest gates. | +| v13 | Convert screenshot complaints into object-family/BVH diagnoses; remove duplicate spectrometer proxies, blue placeholders, and floating cryostage support. | +| v14 | Add real objective-seat/thread evidence, internal coupling segments, measured slit blades, detector continuation, and real clamp/post-chain assets. | +| v15 | Move fiber families directly to the main table, enforce latest objective semantics, attach cable endpoints to real ports, preserve table material indices, and reopen clamp collisions. | +| v16 | Audit every adapter material and clamp neighbor globally; side-mount CCD2 to the spectrometer and prove the internal redirecting optic. | +| v17 | Freeze verified geometry and create separate Nature-style and mentor-explanation render packages. | +| v18 | Diagnose STEP leaf-solid/material artifacts at their source, retain frozen transforms/topology, then pass 4K image QA, saved-Blend reopen, and three independent publication reviewers. | + +## Recurring failures + +| Failure pattern | Why it recurred | Permanent gate | +|---|---|---| +| Local delta reported as final | Only the newest screenshot was checked | Run all applicable active P0 rules; label delta audits `PARTIAL/SCOPED`. | +| Official CAD mistaken for assembly proof | Presence and bbox looked plausible | Require real port, seat, thread, hole, contact, ray, and load-path evidence. | +| Representative PASS copied blindly | Neighbor collisions appeared after propagation | Reopen and recheck every instance plus global neighbor BVH. | +| Fiber route regressed after platform moves | Only the curve or decorative coil moved | Move and audit the complete mechanical/optical/fiber family. | +| Aperture looked centered but was opaque | Thick beam mesh or label hid the blade/body | Use zero-radius axis and first-opaque-hit truth. | +| Placeholders survived a final package | Role inventory covered only changed objects | Scan the full scene for duplicate roles, placeholder names, and materials. | +| Evidence became stale | Scene/export changed after audit | Treat every upstream write as invalidating downstream evidence. | +| Nature styling hid science | Darkness, bloom, or perspective masked geometry | Freeze geometry, keep bright audit views, and use separate editorial renders. | + +## Durable management rules + +1. Newest explicit user wording and annotated screenshots override prior PASS labels and older rules. +2. Register a changed rule before or together with the next revision; preserve the superseded rule and reason. +3. Freeze accepted artifacts and keep the shared Blender generator single-writer. +4. Keep helpers read-only unless they receive an isolated asset scope. +5. Resolve repeated errors in the shared placement/transform root cause, not by unrelated manual moves. +6. Convert screenshots into world-space objects, numeric gates, and required proof. +7. Keep statuses fail-closed and identical across audits, reports, manifests, and user-facing summaries. +8. Do not interrupt an active long render merely because no file has appeared; use process, log, resource, and timestamp evidence. + +## Publication-render lessons + +- Keep the full physical topology visible; use a small number of close-ups that add unique evidence. +- Preserve neutral metals, readable black anodization, restrained glass, and declared beam colors. +- Distinguish non-emissive fiber jackets and dark electrical cables from emissive free-space beams. +- Treat faceting, wrinkled normals, duplicate surfaces, and incorrect STEP solid materials as root-cause defects. Do not hide them with blur, darkness, or blanket smoothing. +- Use an unannotated hero for editorial impact and a separate annotated top view/cutaway for scientific explanation. +- Gate final rendering through actual high-resolution files, image QA, saved-scene reopen, and independent scientific/visual review. diff --git a/skills/thorlabs-blender-optical-path/references/physical-gates.md b/skills/thorlabs-blender-optical-path/references/physical-gates.md new file mode 100644 index 0000000..60284d1 --- /dev/null +++ b/skills/thorlabs-blender-optical-path/references/physical-gates.md @@ -0,0 +1,98 @@ +# Physical gates + +## Contents + +1. Optical topology and ports +2. Post-first mechanics +3. Hardware-family rules +4. Fiber, cable, and instruments +5. Platforms and rendering +6. Numeric defaults + +## Optical topology and ports + +- Make every visible object serve a declared experimental role. Empty posts, unknown boxes, duplicate optics, and co-located surrogates fail unless explicitly future/optional. +- Pass beams through the measured center or open aperture of every lens, filter, waveplate, pinhole, fiber coupler, objective, beamsplitter, window, and detector. +- Solve a mirror normal from incident and outgoing directions. Then roll the real mount around that normal so its mounting interface meets the support and its adjusters avoid the beam half-space. +- Solve a beamsplitter with both transmitted-axis and splitting-plane constraints. Include endpoint rays; one plane cannot create arbitrary orthogonal outputs. +- Treat every declared branch as end-to-end topology. A visually plausible main beam does not excuse a disconnected return, detector, g(1), g(2), or spectrometer branch. +- Trace a zero-radius axis for physical clearance. A thick visible beam is presentation geometry and must be classified separately. + +## Post-first mechanics + +Use a continuous load path: + +`verified table hole -> screw/shank/washer -> clamp -> base adapter -> post holder -> post -> real mount face/hole -> device` + +- Choose the post height from the optical center and clearance before placing the mount. +- Center the post in the holder bore. Do not use a nearby cylinder as a support. +- Make the flat post top contact the mount's real bearing face. Hide the stud in the real hole; never use an exposed stud as a spacer. +- Make a fork clamp capture its own adapter. Put the washer on the slot bearing surface and the shank through the slot into a verified open table hole. +- Classify thread/hole engagement separately from illegal opaque-body collision. +- Prove raised boards and large instruments with a complete table-to-device load path and side/cutaway views. + +## Hardware-family rules + +### KM100-style mirror mount + +- Seat the mirror disk inside the real frame. +- Coincide mirror center, mount optical center, and solved beam intersection. +- Engage the real bottom or side mounting hole. +- Roll adjuster knobs away from the incident/outgoing beam region. + +### LMR1-style transmissive mount + +- Keep the mount vertical and the optic centered in the real bore. +- Seat the foot on the post top and keep the stud out of the glass. +- Do not add decorative external retaining rings. + +### CCM1-style mounted beamsplitter + +- Use physical face-port centers, not cube edges or opaque cage walls. +- Engage the bottom mount interface and preserve both transmitted and reflected branches. + +### MBT/RMS objective and FC chain + +- Identify the official mesh's thread segment, shoulder, seat, objective entrance, and FC center before moving it. +- Keep the large objective barrel outside the retaining seat while the declared threaded segment engages the real bore with full-circumference retention. +- Audit free-space beam -> objective entrance -> internal focusing envelope -> thin internal segment -> FC/ferrule center. +- Label a cone or waist as a schematic envelope unless the optical prescription supports a calculated Gaussian focus. +- Continue sleeve, ferrule, boot, jacket, and fiber without endpoint gaps. + +### Aperture, slit, and spectrometer + +- Use an annular opening, iris, pinhole ring, or two real slit blades—not a solid disk. +- Measure slit center and width from blade meshes. +- Continue the zero-radius axis through the slit and any internal redirecting optic to a detector center read from scene geometry. +- Remove duplicate entrance and sensor-window proxies. Mark a CAD-missing enclosure as modeled, not official. + +## Fiber, cable, and instruments + +- Give every fiber or cable named endpoint ports, tangent continuity, strain relief, and a physically plausible bend radius. +- Recheck the whole family after moving a device or platform; do not move only the decorative curve. +- A projected crossing is acceptable only when measured 3D clearance is positive. +- Keep optical beams, fiber, and electrical cables in separate materials and audit families. +- Give cameras, detectors, cryostages, and spectrometers visible feet, brackets, fasteners, and continuous load paths. + +## Platforms and rendering + +- Extend an accepted table by cropping/tiling the accepted or official matching mesh. Never non-uniformly scale hole geometry. +- Preserve material slots and per-polygon material indices across extensions. +- Replace layout placeholders with explainable multi-part enclosures before final acceptance. +- Use bright side/oblique, axial, and cutaway audit views. Beauty lighting cannot hide contact, aperture, collision, or support evidence. +- Keep labels near bases, away from optical centers and beam crossings. Avoid arrows and leader lines unless requested. + +## Numeric defaults + +Use the real manufacturer specification when it is stricter. Otherwise use these evidence defaults: + +| Gate | Default | +|---|---:| +| Optical/mechanical center error | `<= 0.1 mm` | +| Axis alignment | `abs(dot) >= 0.9999` | +| Bearing/contact gap | `<= 0.1 mm` | +| Table-hole penetration | `>= 4 mm` | +| Representative annular support fraction | `>= 0.25` | +| Fiber/cable bend radius | `>= 30 mm` | +| Fiber/cable endpoint or join error | `<= 0.1 mm` | +| Undeclared opaque collision pairs | `0` | diff --git a/skills/thorlabs-blender-optical-path/references/project-case-study.md b/skills/thorlabs-blender-optical-path/references/project-case-study.md new file mode 100644 index 0000000..0676d6a --- /dev/null +++ b/skills/thorlabs-blender-optical-path/references/project-case-study.md @@ -0,0 +1,55 @@ +# G1/G2 2D-to-3D case study + +## Contents + +1. Goal +2. Input topology +3. Reconstruction decisions +4. Evidence outcome +5. Limits + +## Goal + +Reconstruct a pump-probe, spectrometer, single-mode-fiber, g(1), and g(2) schematic as one physically continuous Blender optical table, then produce an editorial Nature-style render without changing verified geometry. + +Public example files: + +- 2D input: `examples/g1g2/input/fig_s17_componentlibrary_g1g2.png` +- 3D hero: `examples/g1g2/output/v18_nature_hero_graphite_final_4k_preview.jpg` +- annotated top view: `examples/g1g2/output/v18_nature_complete_top_annotated_final_4k_preview.jpg` +- sanitized acceptance: `examples/g1g2/evidence/v18_nature_final_acceptance.json` + +## Input topology + +- Probe: `Galvo -> L1 -> L2 -> BS_MAIN -> L3 -> BS_PICK -> DMLP -> OBJ100 -> Sample` +- Pump: `LA-ND -> SH -> CM2 -> CM1 -> AP -> CM3 -> M1 -> M2 -> DMLP -> OBJ100 -> Sample` +- Spectrometer: `collection plane -> PH -> BS_SPEC -> FELH -> slit -> internal redirect -> CCD2` +- Reflection/SMF: declared sample-return pickoff -> launch -> continuous SMF -> launch -> downstream optics +- g(1)/g(2): declared beamsplitter chain -> two SPAD optical endpoints -> two separate electrical/coaxial links to TCSPC + +## Reconstruction decisions + +1. Map every schematic node to a physical asset, port, optical anchor, and support chain. +2. Use real open apertures and measured face-port centers. +3. Build post-mounted hardware from verified table holes upward. +4. Model each MBT objective and FC/fiber chain as one continuous optical/mechanical family. +5. Distinguish optical rays, fiber jackets, and electrical cables in geometry and color. +6. Prove slit-to-internal-mirror-to-CCD2 continuity with a dedicated cutaway. +7. Freeze verified transforms and topology before editorial lighting, materials, camera, and annotation work. + +## Evidence outcome + +The sanitized final record reports: + +- status `PASS_V18_NATURE_FINAL_VERIFIED`; +- Cycles, 96 samples; +- 4096×2304 16-bit master renders and 4096×3072 annotated output; +- unchanged render geometry signature; +- image QA PASS; +- saved-Blend reopen PASS; +- three of three independent publication reviewers PASS; +- zero P0 and P1 blockers. + +## Limits + +The repository does not ship the laboratory Blend or manufacturer CAD. The image pair demonstrates the workflow and evidence contract; it does not independently reproduce the scene, certify commercial hardware interfaces, or establish spectral performance.