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 @@ +
+
+
|
|
+
+匿名化済みの [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
+
+
+
|
|
+
+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 @@
+
+
+
|
|
+
+脱敏的 [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.