Skip to content

feat(worker): 實作 IFC 轉 USDC 真實轉檔品質閘 - #24

Merged
monkey1sai merged 5 commits into
mainfrom
codex/openspec/worker-real-conversion-quality-bd7d
May 11, 2026
Merged

monkey1sai merged 5 commits into
mainfrom
codex/openspec/worker-real-conversion-quality-bd7d

Conversation

@monkey1sai

@monkey1sai monkey1sai commented May 11, 2026 •

Copy link
Copy Markdown
Owner

變更摘要

實作 _worker 的 IFC -> USDC 真實轉檔品質閘,讓 worker 產出的 model.usdc、index 與 element_mapping.json 來自實際 IFC 幾何資料,而不是 placeholder 產物。同步補齊 OpenSpec task、API contract、驗證紀錄與 single Kit/browser 截圖證據。

修改原因

目前 worker conversion flow 需要可審查的真實 USDC artifact,並且必須在 artifact group ready 前證明輸出可由 USD stage 開啟、mapping/coverage 可量測、失敗或缺少 converter prerequisite 時不會發布 ready artifact。此變更把轉檔品質閘落在 _worker 邊界,避免 downstream coordinator/viewer/Kit 把 placeholder artifact 當成正式模型。

主要變更

  • 新增 _worker/app/converters.py,以 IfcOpenShell + OpenUSD (usd-core) 建立 IFC -> USDC adapter boundary。
  • 更新 _worker/app/store.py、_worker/app/main.py,在 conversion result 中回傳 converter、quality_metrics、real artifact URLs,並在失敗或 non-openable USDC 時阻止 artifact group ready。
  • 更新 _worker/tests/test_worker_store.py、_worker/tests/test_worker_api.py,覆蓋 converter success、prerequisite missing、invalid output、placeholder rejection、one-to-many mapping shape 與 opt-in real smoke skip。
  • 更新 docs/contracts/worker-api.md、docs/verification/2026-05-11-worker-real-conversion-quality.md、OpenSpec specs/tasks,記錄品質閘、coverage measure-first policy 與驗證證據。
  • 新增 single Kit/browser 證據:docs/verification/evidence/2026-05-11-worker-real-conversion-quality/,包含 full-page screenshot、viewport screenshot 與 runtime summary JSON。

驗證方式

  • cd _worker && python -m pytest tests\test_worker_store.py -q --basetemp .pytest_tmp:45 passed。
  • cd _worker && $env:PYTHONPATH=(Resolve-Path .test-deps).Path; python -m pytest tests\test_worker_api.py -q --basetemp .pytest_tmp:32 passed, 1 skipped。skipped 項目是 WORKER_RUN_REAL_USDC_SMOKE=1 opt-in real converter smoke。
  • openspec validate worker-real-conversion-quality --strict:通過。
  • openspec instructions apply --change worker-real-conversion-quality --json:32/32 tasks complete。
  • gitnexus detect_changes(scope=all):risk level low,affected processes 0。
  • scripts/smoke-worker-review-request.ps1 -TimeoutSeconds 900:通過,real IFC fixture 89394282 bytes,coverage_ratio=0.950556913882097,conversion_job_id=conv_20260511034506_f88ee0fd,session_id=review_session_001a59d345ce。
  • Single Kit/browser CDP capture:readyState=4、videoWidth=1920、videoHeight=1080、srcObject=true、bodyHasDataChannelReply=true、pixelStats.nonBlack=14385,截圖位於 docs/verification/evidence/2026-05-11-worker-real-conversion-quality/single-kit-review_session_001a59d345ce-real-conversion.png。

風險與影響

  • _worker conversion 行為由 placeholder 改成真實 adapter;缺少 ifcopenshell 或 usd-core 時 conversion job 會失敗且不發布 ready artifact group。
  • 觀察到的套件 license:ifcopenshell 0.8.5 package classifier 為 LGPLv3+;usd-core 26.5 package metadata 為 LicenseRef-TOST-1.0。正式部署前需確認授權與散佈政策。
  • P0 coverage 採 measure-first:本次記錄 coverage ratio 與 mapping 指標,但尚未設定會 fail CI 的最低 coverage baseline。
  • Runtime evidence 依賴本機 NVIDIA GPU、既有 Kit build、viewer/coordinator node_modules 與 ignored 89 MB IFC fixture;CI 環境未必能重跑 single Kit/browser 截圖。
  • 此變更沒有修改 API 路徑、環境變數名稱、migration、排程或 webhook;conversion result payload 有 additive 欄位 converter / quality_metrics。

回滾方式

若需撤回,revert 本 PR 的 commits,重點是還原 _worker/app/converters.py、_worker/app/store.py、_worker/app/main.py、測試與對應 docs/OpenSpec/evidence。回滾後 worker 會回到原本 placeholder conversion 行為。

後續建議

  • 將 ifcopenshell / usd-core 的安裝方式與 license review 結果落到正式部署文件。
  • 累積多個實案 fixture 後再鎖定 coverage baseline,讓低 coverage 轉成 blocking quality gate。
  • 後續可把 single Kit/browser CDP capture 收斂成正式可重跑 script,而不是僅作本次 OpenSpec evidence。

Summary by CodeRabbit

Release Notes

  • New Features

    • Enabled real IFC-to-USDC conversion with IfcOpenShell and OpenUSD, replacing placeholder outputs
    • Added quality metrics reporting including coverage ratio, element counts, and openability validation
    • Added element mapping generation with one-to-many USD prim path support
  • Documentation

    • Updated API contracts with conversion quality metrics and error handling expectations
    • Enhanced prerequisites documentation and validation guidance
  • Tests

    • Added converter unit and integration tests for real conversion quality validation

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 11, 2026 •

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 132d3f84-ab26-4304-a372-c2b67796982d

📥 Commits

Reviewing files that changed from the base of the PR and between 0649444 and e6a99e6.

⛔ Files ignored due to path filters (2)
  • docs/verification/evidence/2026-05-11-worker-real-conversion-quality/single-kit-review_session_001a59d345ce-real-conversion-viewport.png is excluded by !**/*.png
  • docs/verification/evidence/2026-05-11-worker-real-conversion-quality/single-kit-review_session_001a59d345ce-real-conversion.png is excluded by !**/*.png
📒 Files selected for processing (21)
  • README.md
  • _worker/README.md
  • _worker/app/converters.py
  • _worker/app/main.py
  • _worker/app/store.py
  • _worker/tests/test_worker_api.py
  • _worker/tests/test_worker_converters.py
  • _worker/tests/test_worker_store.py
  • docs/contracts/local-dev-runbook.md
  • docs/contracts/streaming-datachannel-events.md
  • docs/contracts/worker-api.md
  • docs/verification/2026-05-11-worker-real-conversion-quality.md
  • docs/verification/evidence/2026-05-11-worker-real-conversion-quality/single-kit-runtime-summary.json
  • openspec/changes/worker-real-conversion-quality/.openspec.yaml
  • openspec/changes/worker-real-conversion-quality/README.md
  • openspec/changes/worker-real-conversion-quality/design.md
  • openspec/changes/worker-real-conversion-quality/proposal.md
  • openspec/changes/worker-real-conversion-quality/specs/runtime-verification-evidence/spec.md
  • openspec/changes/worker-real-conversion-quality/specs/worker-artifact-pipeline/spec.md
  • openspec/changes/worker-real-conversion-quality/tasks.md
  • scripts/smoke-worker-review-request.ps1

📝 Walkthrough

Walkthrough

This PR upgrades the _worker service from placeholder IFC-to-USDC conversion to real conversion using IfcOpenShell and OpenUSD. It introduces a pluggable converter adapter, implements IfcOpenShellUsdConverter, integrates the converter into the worker store, adds comprehensive testing infrastructure with fake converters, updates the smoke test script, and provides complete OpenSpec documentation with runtime verification evidence.

Changes

Real Conversion Implementation and Testing

Layer / File(s) Summary
Conversion Adapter Contract
_worker/app/converters.py
Defines ConversionAdapterResult, ConversionAdapter protocol, and error types (ConversionAdapterError, ConversionAdapterUnavailable) for pluggable converters.
Converter Utilities
_worker/app/converters.py
Adds prim name sanitization, atomic JSON writing, and package version lookup helpers.
IfcOpenShellUsdConverter Implementation
_worker/app/converters.py
Implements real IFC-to-USD conversion: validates prerequisites, extracts IFC products, builds USD stage with /World prims, tracks GUID-based coverage, computes geometry metrics, reopens USDC for verification, and generates index/mapping JSON with quality metrics.
Application Initialization
_worker/app/main.py
create_app() accepts optional converter dependency; _run_conversion_and_callback() guards against processing incomplete conversions.
Store Integration
_worker/app/store.py
WorkerStore accepts optional converter (defaults to IfcOpenShellUsdConverter); validates IFC-to-USDC format compatibility; delegates to converter; validates outputs; enforces quality gates (USDC openability); detects and rejects placeholders; enriches result payload with converter, quality_metrics, warnings.
Store Validation Helpers
_worker/app/store.py
_assert_adapter_result() validates output paths and boundaries; _looks_like_placeholder() detects fake USDC content; _fail_conversion_job() constructs consistent failure results.
API Test Fakes
_worker/tests/test_worker_api.py
FakeSuccessfulConverter writes deterministic outputs; FakeUnavailableConverter raises ConversionAdapterUnavailable; make_client() accepts optional converter.
Real IFC Smoke Test
_worker/tests/test_worker_api.py
Tests real IFC-to-USDC conversion using IfcOpenShellUsdConverter() directly; validates USDC openability, prim counts, coverage ratio, and element_mapping.json correctness; asserts artifact group readiness.
Conversion Failure Test
_worker/tests/test_worker_api.py
Tests that unavailable converter causes job failure with ready: false, unset usdc_url, and artifact-group readiness returns missing_derived`.
Converter Unit Tests
_worker/tests/test_worker_converters.py
Mocks ifcopenshell and pxr modules; validates mapping behavior for missing/unknown GUIDs and quality metrics (coverage_ratio, mapped_ifc_guids, unmapped_ifc_guids).
Store Test Infrastructure
_worker/tests/test_worker_store.py
Fake converters for store tests; make_store() accepts optional converter; tests quality metrics, one-to-many prim mappings, and failure scenarios (unavailable converter, placeholders, openability gates).
Smoke Script Update
scripts/smoke-worker-review-request.ps1
Adds DevSourceId parameter; queries worker for dev IFC sources; validates USDC openability hard gate; derives artifact_group_ids from conversion result.

Contract and OpenSpec Documentation

Layer / File(s) Summary
Worker README
_worker/README.md
Documents POST /api/conversions behavior with real adapter, prerequisites (ifcopenshell, usd-core), failure conditions, element_mapping.json schema, coverage metrics, and real IFC smoke test setup.
Root README
README.md
Clarifies that worker smoke test requires real IFC files and converter prerequisites.
API Contract Specification
docs/contracts/worker-api.md
Specifies ifcopenshell-openusd adapter, succeeded/failed result JSON examples with converter and quality_metrics, and multi-prim mapping structure.
Dev and Event Docs
docs/contracts/local-dev-runbook.md, docs/contracts/streaming-datachannel-events.md
Updates prerequisites, mapping validation guidance, and usd_prim_path alias documentation.
OpenSpec Design
openspec/changes/worker-real-conversion-quality/design.md
Documents goals, adapter contract priority, coverage measure-first policy, one-to-many mapping schema, evidence boundaries, and migration plan.
OpenSpec Proposal
openspec/changes/worker-real-conversion-quality/proposal.md
Proposes upgrade from placeholder to real conversion with evidence, coverage reporting, and scoped component impact.
OpenSpec Specifications
openspec/changes/worker-real-conversion-quality/specs/
Defines worker artifact pipeline (real USDC, indices, mapping, quality gates) and runtime verification evidence (traceability, metrics recording, placeholder detection, Kit evidence).
OpenSpec Tasks
openspec/changes/worker-real-conversion-quality/tasks.md
Documents preparation, spike, specification, implementation, test, and final pass validation checkpoints.
Verification Evidence
docs/verification/2026-05-11-worker-real-conversion-quality.md, docs/verification/evidence/.../single-kit-runtime-summary.json
Records fixture inventory, converter selection rationale, spike measurements, test results, root smoke validation, Kit runtime capture, and limitations.

🎯 4 (Complex) | ⏱️ ~60 minutes

🐰 The worker hops with glee,
Real USDC files now to see!
No placeholders fake, just geometry true,
Quality metrics and mapping—breakthrough!
IfcOpenShell converts with might,
Evidence shines, conversion done right. ✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/openspec/worker-real-conversion-quality-bd7d

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@monkey1sai
monkey1sai marked this pull request as ready for review May 11, 2026 09:04
Copilot AI review requested due to automatic review settings May 11, 2026 09:04
@monkey1sai
monkey1sai merged commit 3e97a54 into main May 11, 2026
1 of 2 checks passed
@monkey1sai
monkey1sai deleted the codex/openspec/worker-real-conversion-quality-bd7d branch May 11, 2026 09:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades _worker’s IFC→USDC conversion path from placeholder outputs to a real conversion adapter with hard quality gates (notably USDC openability), and propagates converter identity + quality metrics through the worker result payload, tests, and documentation/spec evidence so downstream components don’t treat placeholder artifacts as review-ready.

Changes:

  • Add an IFC→USDC converter adapter boundary (ifcopenshell + usd-core) that emits real model.usdc, indices, mapping, and quality metrics.
  • Enforce “real artifact” readiness by failing conversions that are non-openable, placeholder-like, mock mapping, or missing required outputs (and keep artifact groups non-ready on failure).
  • Update smoke script, tests, OpenSpec artifacts, and contract/verification docs to reflect the new quality gate and evidence requirements.

Reviewed changes

Copilot reviewed 21 out of 23 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/smoke-worker-review-request.ps1 Switch smoke flow to dev IFC sources and assert USDC openability quality gate before creating a review session.
README.md Clarify worker smoke prerequisites (real IFC in storage/, real converter prerequisites).
openspec/changes/worker-real-conversion-quality/tasks.md Add completed OpenSpec task checklist for the change.
openspec/changes/worker-real-conversion-quality/specs/worker-artifact-pipeline/spec.md Define requirements for real conversion artifacts, mapping schema, and quality gates.
openspec/changes/worker-real-conversion-quality/specs/runtime-verification-evidence/spec.md Define evidence requirements distinguishing API success vs real geometry success.
openspec/changes/worker-real-conversion-quality/README.md Introduce the OpenSpec change scope.
openspec/changes/worker-real-conversion-quality/proposal.md Record motivation, scope, and non-goals for the real conversion quality gate.
openspec/changes/worker-real-conversion-quality/design.md Document design decisions (adapter boundary, readiness semantics, measure-first coverage, one-to-many mapping).
openspec/changes/worker-real-conversion-quality/.openspec.yaml Register the OpenSpec change metadata.
docs/verification/evidence/2026-05-11-worker-real-conversion-quality/single-kit-runtime-summary.json Store single Kit/browser runtime capture summary for the verification evidence set.
docs/verification/2026-05-11-worker-real-conversion-quality.md Add detailed verification record for the real conversion quality gate and runtime evidence.
docs/contracts/worker-api.md Extend worker API contract with converter + quality metrics fields and failure semantics.
docs/contracts/streaming-datachannel-events.md Update mapping/prim-path guidance to reflect one-to-many mapping and alias field behavior.
docs/contracts/local-dev-runbook.md Update runbook to reflect new smoke prerequisites and placeholder rejection.
_worker/tests/test_worker_store.py Add store-level tests for quality metrics, converter unavailability, placeholder rejection, and openability gate handling.
_worker/tests/test_worker_converters.py Add unit tests for converter mapping rules (don’t count missing/unknown GUIDs as real coverage).
_worker/tests/test_worker_api.py Update API tests for new payload fields, failure behavior, and opt-in real converter smoke.
_worker/README.md Update worker README to describe real converter prerequisites, gates, and mapping schema.
_worker/app/store.py Replace placeholder conversion with converter adapter execution + result validation + readiness gating and new payload fields.
_worker/app/main.py Allow injecting a converter into the app; avoid posting callbacks for failed conversions.
_worker/app/converters.py Implement the IfcOpenShellUsdConverter adapter producing USDC + indices + mapping + quality metrics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread _worker/app/store.py
raise ConversionAdapterError("Generated element_mapping.json contains fake mapping entries.")

def _looks_like_placeholder(self, path: Path) -> bool:
content = path.read_bytes()[:4096].lower()

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6a99e6475

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

[string] $ModelVersionId = "version_demo_001",
[string] $UserId = "dev_user_001",
[string] $DevSourceId = "",
[int] $TimeoutSeconds = 30

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Increase the real-conversion smoke timeout

Now that this script selects a real dev IFC source and runs the IfcOpenShell/OpenUSD converter, the 30s default is too short for the documented validation path: the evidence added in docs/verification/2026-05-11-worker-real-conversion-quality.md records duration_seconds: 189.15. Running scripts/smoke-worker-review-request.ps1 without overriding -TimeoutSeconds will therefore fail while the conversion is still legitimately running, making the advertised smoke check unreliable for real IFC inputs; please raise the default or derive it from source size.

Useful? React with 👍 / 👎.

Comment thread _worker/app/main.py
Comment on lines +203 to +204
if job.get("status") != "succeeded" or not job.get("result"):
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate failed conversions to _bim-control

When the new real converter fails under the default auto_complete background path (for example missing ifcopenshell/usd-core or an invalid IFC), this early return prevents posting the failed result to _bim-control. _bim-control already maps non-succeeded conversion results to blocked_conversion, so skipping the callback leaves the data authority with no conversion-result/artifact-group state and review-session requests cannot surface the failure; post failed results as well, or add an explicit failure callback.

Useful? React with 👍 / 👎.

Comment thread _worker/app/store.py
Comment on lines +190 to +192
adapter_result = self.converter.convert(
source_path=Path(self.settings.objects_root) / source["object_key"],
output_dir=root_path,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Dereference upload references before converting

For artifacts created with source_url or signed_upload_url, _content_bytes stores only a JSON upload_reference object, but this new converter path always passes the persisted object as the IFC source file. In deployments that use signed upload references instead of content_base64, the real converter will try to parse that JSON stub as IFC and the job can never succeed; materialize the referenced bytes before this call or reject reference-only artifacts before queuing conversion.

Useful? React with 👍 / 👎.

Comment thread _worker/app/store.py
}
warnings = list(job.get("warnings") or [])
warnings.append(f"{code}: {message}")
return self._update_job(job["conversion_job_id"], status="failed", stage=stage, result=result, warnings=warnings)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear stale ready groups on conversion failure

If a conversion is rerun for a source whose artifact group is already ready, and the new real converter fails (for example after prerequisites are removed or the source is reprocessed with bad input), this failure path only updates the job record and leaves the existing artifact-group index untouched. The group therefore continues to advertise the previous derived model.usdc as ready even though the latest conversion result is ready=false, which violates the new failure semantics and can route review sessions to stale artifacts; update the group to a failed/blocked or missing-derived state here.

Useful? React with 👍 / 👎.

monkey1sai added a commit that referenced this pull request Jun 2, 2026
CH-3 收 stage host 設定化 + 死碼清理 + 文件對齊 3 風險(#12 stage allowed-hosts 設定化+warn / #24 移除三處退役 8005 死碼 / #14 SYSTEM_DESIGN 改 as-built)。spec delta: one-click-deploy-hybrid ADD 1(stage allowed-hosts 設定化+空值告警+預設不含退役 port);#14/README/fixture tasks-only。openspec validate --strict 通過。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
monkey1sai added a commit that referenced this pull request Jun 2, 2026
…_DESIGN as-built (#12 #24 #14)

CH-3 apply:
- #12 stage allowed-hosts 設定化+空值 warn: stage_loading.py 空值加 carb.log_warn; start-streaming-server.ps1 加 -AllowedStageHosts param + 三分支(param→env→Write-Warning+default),去除靜默 fallback
- #24 移除三處退役 _worker :8005 死碼: stage_loading.py 內建預設 / start-streaming-server.ps1 / deploy.ps1 Resolve-AllowedStageHosts / README,只留 49101(explore 確認 100% 可安全移除)
- #14 SYSTEM_DESIGN.md 改寫 as-built: 新增 As-built 段 + §5-13 前瞻逐段標 DEFERRED + 補實際描述(對 codebase 核實); §3/§9 target sizing 保留加註(roadmap 引用)

驗證: pytest stage_loading 3 passed(+2); root pytest 65; test-deploy-dryrun ALL PASSED(含 #24 Test 10); stage-loading-contract passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants