Skip to content

fix(coordinator): storageRoot host-native fallback 修同步下載 502 - #94

Merged
monkey1sai merged 1 commit into
mainfrom
codex/hotfix/coordinator-storage-root-host-native-fallback
May 22, 2026
Merged

monkey1sai merged 1 commit into
mainfrom
codex/hotfix/coordinator-storage-root-host-native-fallback

Conversation

@monkey1sai

@monkey1sai monkey1sai commented May 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

Hotfix:bim-review-coordinator/src/config.ts loadConfig 對 storageRoot 的 default 寫死 /workspace/storage(docker container mount point)。Host-native(Windows / Linux)跑時沒設 STORAGE_ROOT env,node 把字串當 host 絕對路徑,Windows 上 fs.mkdir 拋 ENOTDIR: not a directory, mkdir 'C:\workspace',導致 POST /api/external/ifc-ready 的 ifcDownloader.downloadIfcToSharedVolume 全數 502 write_failed,fast-ifc-link-demo-loop (PR #92, archived 2026-05-21) happy path 走不通。

旁邊 storageHostRoot 已有 path.join(cwd, "storage") fallback,只有 storageRoot 漏接。本 PR 把 default 對齊,host-native 直接落在 <cwd>/storage(等同 bim-review-coordinator/storage/)。

重現

2026-05-22 用 Postman collection docs/postman/fast-ifc-link-demo.postman_collection.json 預設值對 host-native coordinator(:8004)送 POST /api/external/ifc-ready,coordinator 回:

HTTP 502
{
  \"detail\": \"IFC download failed\",
  \"ifc_ready_job_id\": \"ifcready_1779417827815_446a7c76\",
  \"error\": \"cannot create /workspace/storage/ifc-cache/ifcready_xxx: ENOTDIR: not a directory, mkdir '/workspace/storage'\",
  \"download_status\": \"failed\"
}

改動(3 files / +25 / -3)

File 變動
bim-review-coordinator/src/config.ts storageRoot default /workspace/storage → path.join(cwd, \"storage\");欄位註解同步更新
bim-review-coordinator/src/services/ifcDownloader.ts JSDoc 註解說明 docker compose / host-native 兩種來源
bim-review-coordinator/tests/config.test.ts 加 loadConfig storageRoot fallback describe,2 個 test(default → cwd / 顯式 env 保留)

Spec / Capability impact = NONE

fast-ifc-link-demo-loop (PR #92) implementation drift fix。local-coordinator-ifc-ready-intake-boundary SHALL 行為(同步下載 + 502 on failure)語意完全不變,只修 host-native default 不可用 → 因此不開新 OpenSpec change、不動 openspec/specs/。

Docker compose 行為驗證

compose.runtime-manager.yml:53,94 明確設 STORAGE_ROOT: /workspace/storage(env override 拿到 default 之前),改 default 不影響 container 路徑。

GitNexus impact

mcp__gitnexus__impact({target:\"loadConfig\", direction:\"upstream\"}) = LOW(direct = 0,只在 startup 被 import,不改 signature / 欄位語意,只動 default value)。

Verification

Level Result
L1 coordinator npm run verify 11 files / 168 tests passed(從 166 → +2 storageRoot fallback tests)
L2 spec validate skip(沒動 spec)
L3 GitNexus impact (pre-change) loadConfig LOW
L4 真實 runtime 重跑 Postman happy path 跳過 — 會中斷現有 host-native coordinator(:8004),建議 merge 後手動重啟並重跑同份 Postman collection 確認 502 → 200 + viewer_url
L5 真實 UI 跳過(同 L4)

Test plan

  • L1 全綠
  • CI green
  • Reviewer approve
  • merge
  • (post-merge)pull main + 重啟 coordinator + 重跑 Postman 確認 happy path 通

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Configuration Improvements

    • Storage path configuration is now environment-aware, automatically adapting to support both containerized and host-native deployments without requiring manual adjustments.
  • Documentation

    • Clarified storage configuration semantics and default behavior across deployment scenarios.

Review Change Stack

`bim-review-coordinator/src/config.ts` `loadConfig` 對 `storageRoot` 的 default
寫死 `/workspace/storage`(docker container mount point)。host-native(Windows /
Linux)跑時若沒設 `STORAGE_ROOT` env,node 把字串當 host 絕對路徑,Windows 上
`fs.mkdir` 拋 `ENOTDIR: not a directory, mkdir 'C:\workspace'`,導致
`POST /api/external/ifc-ready` 的 `ifcDownloader.downloadIfcToSharedVolume` 全數
502 `write_failed`,fast-ifc-link-demo-loop happy path 走不通。

旁邊 `storageHostRoot` 已有 `path.join(cwd, "storage")` fallback,只有 `storageRoot`
漏接。本 commit 把 default 對齊,host-native 直接落在 `<cwd>/storage`(等同
`bim-review-coordinator/storage/`)。

- `src/config.ts:206` storageRoot default 從 `/workspace/storage` 改成
  `path.join(cwd, "storage")`;欄位註解同步更新
- `src/services/ifcDownloader.ts:15` JSDoc 註解說明 docker compose / host-native
  兩種來源
- `tests/config.test.ts` 加 `loadConfig storageRoot fallback` describe block,
  2 個 test(default 走 cwd / 顯式 STORAGE_ROOT 保留)

不改 spec / capability:`fast-ifc-link-demo-loop` (PR #92, archived 2026-05-21)
implementation drift fix。`local-coordinator-ifc-ready-intake-boundary` SHALL
行為(同步下載 + 502 on failure)語意不變,只修 host-native default 不可用。

docker compose 行為驗證:`compose.runtime-manager.yml:53,94` 顯式設
`STORAGE_ROOT: /workspace/storage`,env override 不受 default 改動影響。

驗證(L1):
- `cd bim-review-coordinator && npm run verify`:11 files / 168 tests passed
  (+2 new storageRoot fallback tests)

L4 真實 runtime 重跑 Postman happy path 跳過:會中斷既有 host-native coordinator
service(:8004),建議 merge 後手動重啟並重跑。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 22, 2026 02:54
@coderabbitai

coderabbitai Bot commented May 22, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4a7bb79-a7a2-41d2-9094-f83e67c781bf

📥 Commits

Reviewing files that changed from the base of the PR and between 460d0b5 and f31ca2f.

📒 Files selected for processing (3)
  • bim-review-coordinator/src/config.ts
  • bim-review-coordinator/src/services/ifcDownloader.ts
  • bim-review-coordinator/tests/config.test.ts

📝 Walkthrough

Walkthrough

This PR makes storage root configuration path-relative instead of container-absolute by defaulting to path.join(cwd, "storage") instead of the hardcoded "/workspace/storage", while preserving override capability through the STORAGE_ROOT environment variable. Configuration contracts, tests, and related documentation are updated accordingly.

Changes

Storage root configuration and fallback behavior

Layer / File(s) Summary
Storage root configuration contract and implementation
bim-review-coordinator/src/config.ts
CoordinatorConfig.storageRoot field comment clarified for write-path semantics; loadConfig() default changed from hardcoded "/workspace/storage" to dynamic path.join(cwd, "storage") when STORAGE_ROOT is unset.
Test isolation and storage root fallback validation
bim-review-coordinator/tests/config.test.ts
Environment variable capture and restoration extended to include STORAGE_ROOT; new test suite validates storageRoot defaults to <cwd>/storage when unset and respects explicit STORAGE_ROOT override.
IFC downloader options documentation
bim-review-coordinator/src/services/ifcDownloader.ts
IfcDownloadOptions.storageRoot comment updated to reflect coordinator write destination and new host-relative default.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A storage path so neat and bright,
From container walls to home-like light,
No more hardcoded /workspace/ lines,
Just cwd + storage by design,
Tests ensure the fallback shines! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title mixes English and Chinese, making it unclear. The English portion describes the main fix (storageRoot host-native fallback), but the Chinese segment (修同步下載 502) is cryptic and the overall title is confusing to English-speaking reviewers. Revise the title to be clear and monolingual, e.g., 'fix(coordinator): storageRoot host-native fallback to resolve 502 error' or add a clarifying comment explaining the Chinese portion.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/hotfix/coordinator-storage-root-host-native-fallback

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.

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 hotfixes the bim-review-coordinator host-native default for storageRoot so synchronous IFC downloads write into a valid local directory when STORAGE_ROOT is not provided, preventing POST /api/external/ifc-ready from failing with 502 due to invalid path creation on Windows/Linux host-native runs.

Changes:

  • Change loadConfig() storageRoot default from hard-coded /workspace/storage to path.join(process.cwd(), 'storage') (aligning with the existing storageHostRoot fallback).
  • Clarify IfcDownloadOptions.storageRoot JSDoc to document docker-compose vs host-native behavior.
  • Add unit tests verifying storageRoot fallback behavior and that explicit STORAGE_ROOT is respected.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
bim-review-coordinator/src/config.ts Adjusts storageRoot default to <cwd>/storage to work on host-native environments while still allowing docker-compose override via env.
bim-review-coordinator/src/services/ifcDownloader.ts Updates JSDoc to reflect the intended source of storageRoot under docker-compose vs host-native usage.
bim-review-coordinator/tests/config.test.ts Adds coverage for the new storageRoot fallback and env override behavior.

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

@monkey1sai
monkey1sai merged commit 95e4a14 into main May 22, 2026
5 checks passed
@monkey1sai
monkey1sai deleted the codex/hotfix/coordinator-storage-root-host-native-fallback branch May 22, 2026 03:07
monkey1sai added a commit that referenced this pull request May 22, 2026
…OOT,IFC 落對 shared volume

`compose.runtime-manager.yml` `coordinator` service environment 漏設 `STORAGE_ROOT`
與 `STORAGE_HOST_ROOT`(對比 `streaming-server` line 94 / `kit-manager-api` line 53
都顯式設 `STORAGE_ROOT: /workspace/storage`)。PR #94 補了 host-native node 的 default
fallback,但在 docker container 內 coordinator cwd 是 `/workspace/bim-review-coordinator`,
fallback 解到 container-local path `/workspace/bim-review-coordinator/storage/`,**避開**
docker shared volume mount point `/workspace/storage`,IFC bytes 寫進 container local fs,
host 與 host-native streaming-server 都拿不到。

## Diagnostic(2026-05-22,with PR #94 deployed,container rebuild 後)

- ① POST /api/external/ifc-ready → 202 dispatched,`download_status: downloaded` ✓
- 但 `local_path` 寫成 `/workspace/bim-review-coordinator/storage/ifc-cache/<job>/source.ifc`
- container 內 `/workspace/storage/ifc-cache/` 為空(mount destination 沒被寫到)
- streaming-server(host-native :49101)從 host `<repo>\storage\ifc-cache\` 拿不到檔案
- conversion_status 卡 `queued` 不前進

## Fix

- coordinator service env 加 `STORAGE_ROOT: /workspace/storage`(對齊 mount destination)
- coordinator service env 加 `STORAGE_HOST_ROOT: ${RUNTIME_STORAGE_ROOT:-./storage}`,
  與 mount source 同 expansion;預設 `./storage`(相對 docker compose cwd)
- inline 註解標明:user 為 host-native streaming-server 場景應在 `.env` 設
  `RUNTIME_STORAGE_ROOT=<host absolute path>`(例:
  `C:\Repos\active\iot\AI-BIM-governance\storage`),否則 streaming-server 收到的
  `host_local_path` 是 relative 字串,host fs 解析依賴 streaming-server 啟動 cwd。

## Note(超出本 fix 範圍)

`bim-streaming-server/source/.../conversion_authority.py` `_ifc_artifact` 目前**未接**
dispatch payload 內的 `host_local_path` / `local_path` 欄位,僅讀 `ifc_artifact.url`
(HTTP URL fetch)。本 fix 只負責 coordinator 寫對位置 + dispatch payload schema 正確,
streaming-server 端的 `host_local_path` 消費邏輯應由另一個 change 補。

## Verification

- `docker compose -p hotfix-validate -f compose.runtime-manager.yml -f compose.host-kit.yml --env-file .env.web-plane.host-kit.example config`:
  STORAGE_ROOT / STORAGE_HOST_ROOT 正確 expansion(`./storage` fallback,因 .env 未設
  RUNTIME_STORAGE_ROOT)
- `cd bim-review-coordinator && npm run verify`:11 files / 168 tests passed
  (不動 TS code,無 regression)

不改 `.env.web-plane.host-kit.example`(權限限制無法讀寫),用 compose inline 註解
導引 user 設置。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
monkey1sai added a commit that referenced this pull request May 22, 2026
… shared volume (streaming-server-prefer-local-ifc-path)

完整 OpenSpec change(scaffold + apply 同 commit;模仿 fast-ifc-link-demo-loop PR #92 pattern)。

## Why

fast-ifc-link-demo-loop(PR #92,archived 2026-05-21)宣告 coordinator → streaming-server
dispatch payload 加 `local_path` / `host_local_path`,並寫進 spec delta:**streaming-server
SHALL prefer host_local_path when present...**。但 streaming-server 端**完全沒實作**這個
consumer 行為(`conversion_authority._ifc_artifact` 只認 url,`ifc2usdc_powershell_adapter._url_to_local_path`
HTTP scheme 直接 fail)。

PR #94/#95 修好 coordinator 端(host-native default + compose env);2026-05-22 重跑 Postman
證實 IFC 已正確落到 shared volume,但 `conversion_status` 卡 queued、`viewer_url: null`。
本 change 補完 streaming-server consumer drift,讓 fast-mvp happy path 真實跑通。

## What changed

### Streaming-server source(2 files / +54 lines)

- `conversion_authority._ifc_artifact`:return dict propagate `local_path` / `host_local_path`
  (lineage / debug visibility)
- `ifc2usdc_powershell_adapter.Ifc2UsdcPowershellConverterAdapter`:
  - `__init__` 加 `storage_root: Path | None`,resolve env `STORAGE_ROOT` 或 cwd
  - `_resolve_local_ifc` 新解析順序:`host_local_path` → `local_path` → 既有 url 解析
  - 新 helper `_try_local_path`:storage_root sandbox(path traversal hard-fail)+ 不存在 soft fallback

### Streaming-server tests(2 files / +167 lines)

- `test_host_native_conversion_service.py`:加 5 個 adapter `_resolve_local_ifc` test
  - host_local_path 在 storage_root 內 + 存在 → 直接用,跳過 url
  - local_path 為 fallback(host_local_path 不在時)
  - 兩者 path 在 storage_root 內但檔案不存在 → soft fallback url(edge-local://)
  - host_local_path 在 storage_root 外 → raise `invalid_ifc_input`
  - regression:既有 edge-local:// url-only payload 仍能解析
- `test_conversion_authority_api.py`:加 2 個 `_ifc_artifact` propagation test
  - local_path / host_local_path 存在時 propagate 進 return dict
  - 不存在時 default None

### OpenSpec change(5 files / +372 lines)

`openspec/changes/streaming-server-prefer-local-ifc-path/`:
- `proposal.md`:why / what / non-goals / capability impact
- `design.md`:resolution order / sandboxing / backward compat / failure semantics
- `tasks.md`:12 phase tasks(0 setup → 11 archive)
- `acceptance.md`:L1-L5 acceptance
- `specs/conversion-webhook-lifecycle/spec.md`:`## ADDED Requirements`
  `Streaming-server consumes shared-volume local IFC path before url fetch` + 3 Scenarios

## Blast radius

GitNexus pre-impact:`_ifc_artifact` / `_resolve_local_ifc` / `_url_to_local_path` 全 **LOW**
(direct d=1 callers 在同 module/class,affected processes = `create_conversion` + `convert`,
都是預期內)

## Verification(L1-L3)

| Level | Result |
|---|---|
| L1 `cd bim-streaming-server && pytest tests -q` | **31 passed**(原 23 + 新 8 cases) |
| L1 `cd bim-review-coordinator && npm run verify` | 11 files / **168 tests passed**(regression OK,coordinator side 不動) |
| L1 root `pytest tests -p no:cacheprovider` | **9 passed**(contracts / fakes regression OK) |
| L2 `openspec validate streaming-server-prefer-local-ifc-path --strict` | **valid** |
| L2 `openspec validate --specs --strict` | 26 passed / 0 failed |
| L3 GitNexus impact (pre-change) | LOW for `_ifc_artifact` / `_resolve_local_ifc` / `_url_to_local_path` |
| L4 真實 runtime end-to-end | **跳過** — 需重啟既有 host-native streaming-server(:49101),建議 merge 後重啟並重跑 Postman 驗證 conversion_status → ready + viewer_url 出現 |

## Predecessor / Follow-up

✓ Predecessor:`fast-ifc-link-demo-loop`(PR #92, archived PR #93) + hotfix PR #94(coordinator host-native fallback)+ PR #95(compose env)
✗ 仍 open follow-up(本 change 不做):
- streaming-server docker deployment 的 dual-fs 議題(scope = host-native fast MVP only)
- `main spec body` 缺少 fast-ifc-link-demo-loop 的 `Coordinator dispatch payload carries local path references` requirement entry(archive PR #93 只加了 implementation status note;archive 本 change 時可順手補)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
monkey1sai added a commit that referenced this pull request May 22, 2026
…ecs + roadmap (#97)

PR #96(implementation,squash `3c7dbd5`)merged 後的 OpenSpec sync/archive cleanup。

- `git mv openspec/changes/streaming-server-prefer-local-ifc-path/` → `openspec/changes/archive/2026-05-22-streaming-server-prefer-local-ifc-path/`
- `openspec/specs/conversion-webhook-lifecycle/spec.md` 加 2 個 ADD requirement:
  1. `Coordinator dispatch payload carries local path references`(backfill `fast-ifc-link-demo-loop` archive PR #93 缺漏的 requirement body,3 Scenarios)
  2. `Streaming-server consumes shared-volume local IFC path before url fetch`(本 change 新 ADD,3 Scenarios)
  + 對應的 implementation status note(2026-05-21 與 2026-05-22 兩段)
- `docs/plans/AI-BIM-governance-saas-roadmap-2026-05.md` 加 archive 摘要(2026-05-22 fast-mvp loop final landing,含 hotfix bundle PR #94 / #95 / #96)

`openspec validate --specs --strict` = **26 passed / 0 failed**

## fast-mvp loop 收尾完成

兩段 OpenSpec change archive(`remove-conflict-review-from-fast-mvp` + `fast-ifc-link-demo-loop`)+ 三段 hotfix(PR #94 coordinator default、PR #95 compose env、PR #96 streaming-server consumer),把外部 IFC Worker → coordinator → streaming-server → viewer 連結這條 happy path 從 spec 到 code 完整對齊。

L4 真實 happy path 需 user 設 `.env` `RUNTIME_STORAGE_ROOT=<host absolute path>`、recreate coordinator container、重啟 host-native streaming-server 帶 `STORAGE_ROOT=<host absolute path>`,本 archive 不包含此環境設定步驟(留給 user runbook)。

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
monkey1sai added a commit that referenced this pull request May 22, 2026
…_url(coordinator-auto-poll-streaming-conversion) (#98)

完整 OpenSpec change(scaffold + apply 同 commit)。

## Why

fast-mvp loop 三段 archive 收尾後驗證,`POST /api/external/ifc-ready` → coordinator dispatch → streaming-server 真實轉檔 succeeded(40s)— **但 coordinator 端 `conversion_status` 永遠停在 `queued`**:既有 spec `Coordinator ingests host-native conversion result into callback outbox` 已寫「SHALL ingest through polling, an internal result loop, or an equivalent internal callback」,但 polling / internal result loop 都未實作。`fetchConversionResult` 只在 manual `POST /api/internal/conversions/<id>/ingest` 端點被呼叫;沒有自動 caller,viewer_url 永不出現。

## What changed(10 files / +968 / -50)

### Coordinator src(3 files)
- `services/streamingConversionClient.ts`:加 module-level `isTerminalConversionResult` helper(terminal 判定抽出來避免雙處硬編)+ class method `pollConversionResult(jobId, options): PollerHandle`:setTimeout chain(避免 setInterval overlap)、cancel()、max attempts → poll_timeout 走 fake failed result 餵 onTerminal
- `config.ts`:加 `conversionPollEnabled` / `conversionPollIntervalSeconds`(default 5)/ `conversionPollMaxAttempts`(default 60 = 5 min)+ `parseBooleanEnv` helper
- `app.ts`:
  - `CoordinatorApp` interface 加 `dispose: () => void`
  - 加 module-scope `pollerRegistry: Map<conversion_job_id, PollerHandle>`
  - refactor 既有 manual ingest handler 內邏輯抽成共用 helper `ingestStreamingConversionResult(jobId, { result?, source })`(manual + auto-poll 共用)
  - 加 `schedulePollerForConversion(jobId)`:closure wrapper for `streamingConversionClient.pollConversionResult` + onTerminal=ingest helper + registry cleanup
  - dispatch path:`markDispatched` 之後若 `config.conversionPollEnabled && !pollerRegistry.has(id)` → `schedulePollerForConversion(id)`
  - manual ingest handler 開頭 cancel + delete registry(避免雙 ingest)
  - return 加 `dispose`:遍歷 registry cancel 所有 timer

### Coordinator tests(2 files)
- `unit_kitpool.test.ts`:fixture 加 3 個新 config field(default `false` 避免 unit test 啟 timer)
- `auto-poll-conversion.test.ts`(新):5 case
  - dispatch → poller queued/queued/ready 序列 → 自動 ingest 出 viewer_url
  - dispatch → poller queued/failed → 自動 ingest 為 failed,viewer_url 不出現
  - 重複 idempotent dispatch 不雙起 poller(stub /result 呼叫次數有 budget)
  - manual ingest 觸發 cancel auto poller(stub /result 只被打 1 次)
  - `conversionPollEnabled: false` fixture 不啟 poller

### OpenSpec change(5 files)
- proposal / design / tasks / acceptance / `conversion-webhook-lifecycle` MODIFIED requirement + 3 新 Scenario

## GitNexus blast radius = LOW

| symbol | risk | d=1 |
|---|---|---|
| `fetchConversionResult` | LOW | `createCoordinatorApp`(同 module) |
| `createCoordinatorApp` | LOW | 無 upstream(main entry) |
| `loadConfig` | LOW | (PR #94 同樣 path,LOW) |

## Verification

| Level | Result |
|---|---|
| L1 coordinator `npm run verify` | 12 files / **173 tests passed**(168 既有 + 5 新 auto-poll) |
| L1 streaming-server `pytest tests -q` | **31 passed**(不動,regression OK) |
| L1 root `pytest tests` | **9 passed** |
| L2 `openspec validate coordinator-auto-poll-streaming-conversion --strict` | **valid** |
| L2 `openspec validate --specs --strict` | **26 passed / 0 failed** |
| L3 GitNexus pre-impact | LOW for `fetchConversionResult` / `createCoordinatorApp` |
| **L4 真實 runtime** | **跳過** — 留 merge 後 docker compose recreate coordinator(讀新 code)+ 跑 Postman ① + 等(不手動 POST ingest)→ ② Poll 預期 5-90 秒內 `viewer_url` 自動出現 |

## Predecessor / Follow-up

✓ Predecessor:`streaming-server-prefer-local-ifc-path`(PR #96 / archive PR #97)+ PR #94 / PR #95 hotfix bundle
本 change 是 fast-mvp loop 自動化的最後一片拼圖,merge 後外部 caller 不再需要任何手動 trigger 就能拿到 viewer_url。

不解 / 排除:
- 不持久化 poller state(coordinator restart in-memory timers lost;手動 endpoint 仍可救)
- 不解 cloud callback outbox retry / dead-letter(另一條既有 capability,本 change 不動)
- 不引入 streaming-server push callback(本 change 走 coordinator pull)
- 不引入第三方 scheduler library

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
monkey1sai added a commit that referenced this pull request May 22, 2026
…步 specs + roadmap (#99)

PR #98(implementation,squash `2103bf7`)merged 後的 OpenSpec sync/archive cleanup。

- `git mv openspec/changes/coordinator-auto-poll-streaming-conversion/` → `openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/`
- `openspec/specs/conversion-webhook-lifecycle/spec.md` MODIFIED `Coordinator ingests host-native conversion result into callback outbox` requirement:加 SHALL auto-poll 子條款(env config 三項可調)+ 3 新 Scenario(dispatch auto-schedules / manual de-dup / poll timeout failed-equivalent)+ implementation status note
- `docs/plans/AI-BIM-governance-saas-roadmap-2026-05.md` 加 archive 摘要(2026-05-22 fast-mvp loop zero-touch automation 完成)

`openspec validate --specs --strict` = **26 passed / 0 failed**

## fast-mvp loop zero-touch 收尾完成

4 段 OpenSpec change archive(`remove-conflict-review-from-fast-mvp` + `fast-ifc-link-demo-loop` + `streaming-server-prefer-local-ifc-path` + `coordinator-auto-poll-streaming-conversion`)+ 4 段 hotfix bundle(PR #94 / #95 / #96 / #98)整體把外部 IFC Worker → coordinator → streaming-server → viewer 連結這條 happy path 從 spec 到 code、從 manual 到 zero-touch 完整對齊並驗證。

L4 真實 runtime 第一次 zero-touch end-to-end 跑通(2026-05-22):dispatch → 40 秒內 viewer_url 自動出現,無 manual ingest trigger。

Co-authored-by: Claude Opus 4.7 <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