Repository navigation
feat(console): Edge Console P2–P4 前端建置(真實後端頁 + A4–A10 vision + Review Room v1) - #179
Conversation
P2-1 OverviewPage 補三 Panel: - BoundaryDiagram(web-plane→boundary→internal 三欄,視覺化「瀏覽器只打 :8004」) - DEPENDENCIES 授權風險表(LGPL/copyleft 照實標,禁「零授權風險」) - ENDPOINTS coordinator 已實作路由清單(逐一查證自 app.ts) - 可選接 coordinator /health 探活(未連線誠實標未取得,不假裝 healthy) P2-2 SemanticViewerPage(取代 semantic StubPage): - 載入真實 element_mapping.json;重用既有 isFakeMappingDocument 工具 - 嚴守 fake-vs-real 隔離:mock / allow_fake_mapping / fake_mapping_count>0 / mapping_method=fake_for_smoke_test 一律標 demo 並拒絕當正式 mapping - 點構件 3D 標示需 viewer DataChannel(console 無此鏈)→ 標 p1,不做假按鈕 P2-3 CoordinatorPage / IntakePage / RuntimePage(取代 B/C/F StubPage)+ 新建 coordinatorClient.ts: - 只打 coordinator :8004 的真實 coordinator-owned 端點(GET /api/runtime/status、 GET /api/external/ifc-ready、GET /api/review-sessions/:id/stream-config) - 永不直連 :49100/:49101/:49102;幻覺端點(/api/governance/uploads、 /api/governance/runtime/*)查證不存在 → 不使用、不 mock - GPU / 首幀 / conversion 秒數無遙測 → 標未取得(idle,非 fail),禁捏造 - callback-outbox 直查需 internal token(瀏覽器不可達)→ 改由 ifc_ready job 的 callback_outbox_id 觀察,不捏造投遞數 console.test.tsx 補 P2 靜態斷言:DEPENDENCIES 含 copyleft 且無「零授權風險」、 Semantic fake 隔離、coordinatorClient 只打 :8004 且無幻覺端點、GPU 標未取得。 驗證:npx tsc --noEmit(0)、npx vitest run(46 pass)、npx vite build(OK)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…olish P3-1 A4–A10 vision 詳頁: - 泛用 AppVisionPage 吃 data.ts 新增的 A1A10_DETAIL(轉述 RM_APPS: schema/api/ui/mvp/sprint steps/risks);AppsPage roadmap 卡可點 → app/<slug> - 整頁標願景:明確標「後端未建」;scenario 標「範例情境(願景敘事,非真實 run)」; api 標「願景 API 設計(非已實作 route)」;禁當真實實測、禁捏造數字 - Prov 型別加 p3/p4(A5=p3、其餘 p4,對齊 RM phase),同步 PROV_LABEL/PROV_CLASS + edge-console.css 的 .ec-p3/.ec-p4 P3-2 右欄 Agent:補 suggested prompts(disabled 示意)+ 寫入限制聲明 (AI 僅改 review/session layer)+ disabled 輸入框(A9 ROADMAP)。 P3-3 FlowBar(Intake→Convert→Meeting→Mark→Record,Mark 標 p15)+ Tweaks (操作員/技術用語切換、scenario clean/warn UI 偏好;真實頁一律以 live API 為準, 不改真實資料)移植到 EdgeConsole 殼層。 console.test.tsx 補 P3 斷言:每個 vision 頁含「後端未建」+「範例情境/非真實 run」+ 「非已實作 route」且無捏造數字;roadmap 卡可點且標 p3/p4;殼層含 Agent prompts + disabled 輸入 + FlowBar + Tweaks。 驗證:npx tsc --noEmit(0)、npx vitest run src/console(15 pass)、npx vite build(OK)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
P4 Review Room(G)v1(pages.tsx ReviewRoomPage,取代 review StubPage): - 維持殼層狀態 + 加「在既有 viewer 開啟」連結:coordinator /ui/open?session= (server-side redirect,查證自 app.ts)+ 本地 /?session=(main.tsx 解析 attach) - session id 格式 gating(lwv_ / review_session_)→ 不合則連結停用,非假連結 - 工具列誠實標 provenance(openStage/focusPrim/selectPrims/clearHighlight asbuilt; highlight 走 client 主動拉 / section / snapshot p15) - 不在 console 內嵌 3D;不動 App.tsx / Window.tsx(守 console 邊界) OpenSpec change edge-console-p2-p4-buildout: - proposal.md(含端點查證:真實 coordinator-owned 端點 vs 判定不存在的幻覺端點) - tasks.md(P2/P3/P4 逐項 + 8.8 標 browser E2E 由主對話補、本 change 不偽造截圖) - specs/edge-console-operator-frontend/spec.md(## ADDED Requirements 五項, P2-1/P2-2/P2-3/P3/P4 各含可驗收 scenario 與誠實條款) console.test.tsx 補 P4 斷言:Review Room 含「在既有 viewer 開啟」+ /ui/open + ?session= + 不動 App.tsx/Window.tsx + section/snapshot p15。 驗證:npx tsc --noEmit(0)、npx vitest run(50 pass)、npx vite build(OK)、 npx openspec validate edge-console-p2-p4-buildout --strict(valid)+ --all --strict (41 passed / 0 failed)。browser E2E / 截圖由主對話跑真實 IFC E2E 補(本 change 不做)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 7 minutes and 28 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
此 PR 依 OpenSpec change edge-console-p2-p4-buildout,在 不跨出 web-viewer-sample/src/console/ 邊界的前提下,將 Edge Console 的 P2–P4 前端頁面從殼頁補齊為可讀取 coordinator(:8004) 真實端點的 UI,並新增 A4–A10 的 vision 詳頁與 Review Room v1 的「開啟既有 viewer」導引。
Changes:
- P2:Overview 補 Boundary/Endpoints/Dependencies(含授權風險)、Semantic Viewer(fake mapping 嚴格隔離)、Coordinator/Intake/Runtime 真實頁與
coordinatorClient(只打 :8004)。 - P3:A4–A10 roadmap 卡可點進 vision 詳頁(整段標願景/後端未建),並在殼層加 FlowBar + Tweaks + disabled 的 Agent prompts。
- P4:Review Room v1 維持殼層,新增透過
/ui/open?session=與/?session=連到既有 viewer 的連結。
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| web-viewer-sample/src/console/pages.tsx | 新增/替換多個頁面(Overview/Coordinator/Intake/Runtime/Semantic/AppVision/ReviewRoom)並串接 coordinatorClient |
| web-viewer-sample/src/console/EdgeConsole.tsx | hash 路由 renderBody 擴充、加入 FlowBar/Tweaks、更新右欄 Agent(disabled) |
| web-viewer-sample/src/console/edge-console.css | 新增 p3/p4 樣式與 BoundaryDiagram、ENDPOINTS、risk、fake-banner、FlowBar/Tweaks 等 UI 樣式 |
| web-viewer-sample/src/console/data.ts | 擴充 Prov(p3/p4)、新增 SERVICES/ENDPOINTS/DEPENDENCIES/A1A10_DETAIL,並讓 A4–A10 roadmap 指向 vision route |
| web-viewer-sample/src/console/coordinatorClient.ts | 新增 coordinator-owned REST client(僅 :8004)與 runtime/ifc-ready/stream-config 型別 |
| web-viewer-sample/src/console/console.test.tsx | 新增 P2/P3/P4「誠實鐵律」相關的 renderToString smoke assertions |
| openspec/changes/edge-console-p2-p4-buildout/tasks.md | 記錄端點查證與實作/驗證任務清單 |
| openspec/changes/edge-console-p2-p4-buildout/specs/edge-console-operator-frontend/spec.md | 新增 P2–P4 前端需求(誠實條款、端點/授權/vision/review-room) |
| openspec/changes/edge-console-p2-p4-buildout/proposal.md | 變更動機與範圍/非目標、驗證方式整理 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <Field | ||
| k="COORD Coordinator :8004" | ||
| v={health === "ok" ? "control plane · /health ok" : health === "down" ? "未連線(/health 不可達)" : "control plane(探活中…)"} | ||
| prov={health === "down" ? "demo" : "asbuilt"} | ||
| /> |
| // 從 runtime/status 撈帶 expected_mapping_url 的真實 session,方便操作員選擇真實 artifact。 | ||
| const loadCandidates = useCallback(async () => { | ||
| setErr(null); | ||
| try { | ||
| const rt = await coordinatorClient.runtimeStatus(); | ||
| const withMap = rt.sessions.items.filter((s) => s.expected_stage_url); | ||
| // sessions.items 無 mapping_url,但 ifc_ready_jobs 可間接定位;這裡以 sessions 帶 stage 的為候選, | ||
| // 真正 mapping_url 由 session detail / expected_mapping_url 提供(操作員亦可直接貼 URL)。 | ||
| setCandidates([]); | ||
| if (withMap.length === 0) setErr("runtime/status 無帶 mapping 的 session(可直接貼 mapping URL 載入)"); | ||
| } catch (e) { | ||
| setErr(`未連線 coordinator /api/runtime/status:${String(e)}`); | ||
| } | ||
| }, []); |
| <a className={`ec-btn ${valid ? "primary" : ""}`} href={viewerOpenUrl} target="_blank" rel="noreferrer" | ||
| style={valid ? undefined : { pointerEvents: "none", opacity: 0.45 }} aria-disabled={!valid}> | ||
| coordinator /ui/open(redirect) |
| <a className="ec-btn" href={viewerLocalUrl} target="_blank" rel="noreferrer" | ||
| style={valid ? undefined : { pointerEvents: "none", opacity: 0.45 }} aria-disabled={!valid}> | ||
| 本地 viewer /?session= |
| <div style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}> | ||
| <input className="ec-btn" style={{ minWidth: 420 }} placeholder="element_mapping.json 的 URL(artifact 來源)" value={mapUrl} onChange={(e) => setMapUrl(e.target.value)} /> | ||
| <Btn primary disabled={busy || !mapUrl.trim()} caption="fetch mapping JSON" onClick={loadMapping}>{busy ? "載入中…" : "載入 mapping"}</Btn> | ||
| <Btn caption="GET /api/runtime/status(找帶 mapping 的 session)" onClick={loadCandidates}>列出真實 session</Btn> |
| {candidates.length > 0 && ( | ||
| <p className="ec-note">真實 session 候選:{candidates.map((c) => c.ifc_ready_job_id).join(" · ")}</p> | ||
| )} |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1619bf0787
ℹ️ 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".
| const withMap = rt.sessions.items.filter((s) => s.expected_stage_url); | ||
| // sessions.items 無 mapping_url,但 ifc_ready_jobs 可間接定位;這裡以 sessions 帶 stage 的為候選, | ||
| // 真正 mapping_url 由 session detail / expected_mapping_url 提供(操作員亦可直接貼 URL)。 | ||
| setCandidates([]); |
There was a problem hiding this comment.
Populate mapping candidates from runtime status
When coordinator returns sessions with mapping artifacts, this handler still discards them with setCandidates([]), so the "列出真實 session" button never shows any usable candidate and operators can only proceed by manually pasting a URL. I checked buildRuntimeStatus in bim-review-coordinator/src/app.ts, and sessions.items already includes expected_mapping_url; use that value (and type it on RuntimeSessionSummary) instead of dropping the fetched sessions.
Useful? React with 👍 / 👎.
| // as-built;highlight 走 client 主動拉(不復活 server-push);section/snapshot 待建。 | ||
| export function ReviewRoomPage() { | ||
| const [sessionId, setSessionId] = useState(""); | ||
| const valid = /^(lwv_|review_session_)[A-Za-z0-9_]+$/.test(sessionId.trim()); |
There was a problem hiding this comment.
Reject lwv IDs that the viewer cannot attach
When an operator enters an lwv_... id, this page enables both viewer links, but the viewer bootstrap treats the query value as a review session id and immediately calls /api/review-sessions/${id}; SessionStore only accepts review_session_..., so the opened viewer fails before stream-config is loaded. Unless the viewer gains a local-web-view lookup path, this UI should only accept the review_session_... ids that the existing attach flow can resolve.
Useful? React with 👍 / 👎.
PR Review Agent Summary
Blockers
Warnings
Validation Commands
Checks
Human Review Notes
|
全部在 web-viewer-sample/src/console/pages.tsx;不動 viewer App/Window,守 /console 殼層邊界。
1.(真 bug)SemanticViewer loadCandidates 算了 withMap 卻 setCandidates([]),列表永遠空白。
改走真實可達端點 GET /api/external/ifc-ready,填入帶轉換產出(expected_stage_url)的真實
ifc-ready job 作候選;佇列為空時誠實顯示為空(不留永遠空白的假功能)。coordinator 不持有
mapping_url 欄位,mapping URL 仍由操作員貼入——不發明幻覺端點。
2. Overview COORD /health 探活的 Field 在 down 時被誤標 demo;探到 down/未連線是真實觀測,
一律改標 asbuilt(真實探活結果),只是顯示狀態為未連線;demo 僅保留給無真實遙測來源的值。
3.(a11y)ReviewRoom viewer 連結在 invalid 時改不渲染 href、加 tabIndex={-1} + aria-disabled,
鍵盤/螢幕閱讀器無法啟用,移除原本仍可互動且 Enter 跳 # 的 href="#"。
4. SemanticViewer「列出」按鈕 caption 與實際呼叫一致:改為 GET /api/external/ifc-ready。
5. 候選標籤與資料實體(IfcReadyListItem)一致:改「真實 job 候選」並同時顯示 job_id /
review_session_id,不再寫概念混淆的「真實 session 候選」。
6. ReviewRoom lwv / review_session id 驗證對齊 viewer attach(main.tsx)與 coordinator
/ui/open(app.ts:1590)共用權威格式;不符者不產生會被後端 400 打回的壞連結,並誠實提示
「viewer 無法 attach、coordinator /ui/open 會回 400」——不發明 attach 預檢幻覺端點。
測試:console.test.tsx 補 finding 1/2/3/4/5/6 斷言(provenance demo→asbuilt、候選端點/標籤一致、
invalid 連結無 href=# 且 tabindex=-1 + aria-disabled)。
驗證:npx tsc --noEmit 0 errors;npx vitest run 53 passed(console 19);npx vite build OK;
git diff --cached --check 無 trailing whitespace。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6a5d3012a0
ℹ️ 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".
| setErr(null); | ||
| try { | ||
| const { items } = await coordinatorClient.listIfcReady(50); | ||
| const withStage = items.filter((j) => j.expected_stage_url); |
There was a problem hiding this comment.
Populate mapping URLs from ifc-ready candidates
Fresh evidence in the current change is that this handler now reads /api/external/ifc-ready, whose summarizeIfcReadyJob response includes expected_mapping_url, but it still filters only on expected_stage_url and renders job IDs without ever setting mapUrl. When a converted job has a mapping artifact, the “列出真實 job” path still cannot help the operator load it, so the Semantic Viewer remains manual-paste only despite the coordinator exposing the URL.
Useful? React with 👍 / 👎.
PR Review Agent Summary
Blockers
Warnings
Validation Commands
Checks
Human Review Notes
|
… mapping URL(回應 #179 codex :685) coordinator summarizeIfcReadyJob 已回 expected_mapping_url,但前端 IfcReadyListItem 型別漏接、候選僅文字顯示無法載入。 補型別 + loadCandidates 改篩 expected_mapping_url + 候選改為可點按鈕 onClick setMapUrl,讓帶 mapping 產出的 job 一鍵填入。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR Review Agent Summary
Blockers
Warnings
Validation Commands
Checks
Human Review Notes
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c5a2271e9b
ℹ️ 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".
| <td>{it.name ?? ""}</td> | ||
| <td>{it.ifc_guid ?? <span className="ec-warn-note">null</span>}</td> |
There was a problem hiding this comment.
Render real mapping class and name fields
When loading mapping artifacts produced by the real ifc2usdc_powershell_adapter, each row uses ifc_type and ifc_name (the adapter writes those keys into element_mapping.json), not ifc_class and name. As a result, the Semantic Viewer shows blank class/name columns for real converted jobs even though the data is present, which makes the new semantic inspection page lose the operator-facing metadata it is meant to expose; read both field aliases before falling back to empty strings.
Useful? React with 👍 / 👎.
| // 故拒絕產生連結(不產生會被後端打回的壞連結,不發明「attach 預檢」幻覺端點)。 | ||
| const valid = /^(lwv_|review_session_)[A-Za-z0-9_]+$/.test(sid); | ||
| // invalid 時連結為 undefined(不渲染成可互動 anchor),避免 href="#" 被鍵盤 / 螢幕閱讀器啟用後跳到 #。 | ||
| const viewerLocalUrl = valid ? `/?session=${encodeURIComponent(sid)}` : undefined; |
There was a problem hiding this comment.
Preserve viewer path prefixes in local links
In deployments where the viewer is served under a path prefix, e.g. the coordinator tests cover viewerPublicBaseUrl=https://review.example.test/bim-viewer, this absolute /?session=... link leaves the viewer prefix and opens the origin root instead of the existing viewer app. The coordinator /ui/open redirect preserves configured prefixes, but the new local viewer link bypasses that path, so use a URL relative to the viewer base/current app prefix rather than a root-relative / URL.
Useful? React with 👍 / 👎.
| try { | ||
| const res = await fetch(mapUrl.trim(), { headers: { Accept: "application/json" } }); | ||
| if (!res.ok) { setErr(`載入 mapping ${res.status} ${res.statusText}`); return; } | ||
| const json = (await res.json()) as ElementMappingDocument; |
There was a problem hiding this comment.
Validate mapping JSON before accepting it
If the operator pastes the wrong artifact URL, such as a manifest or metadata JSON, this cast still stores it as a mapping document and the page renders it as a loaded artifact with mapped=0 and fake mapping=0 instead of reporting an invalid shape. The existing viewer loader rejects payloads that lack mapping items or summary; the console path should apply the same shape check before calling setDoc so bad URLs do not look like valid empty mappings.
Useful? React with 👍 / 👎.
* docs(openspec): 批次歸檔 #178/#179/#180 + roadmap sync(archive-batch-2026-06-04) 歸檔三個已 merged change: - agent-ship-cycle-automation:ship-cycle 自動化(agent-operability-governance +1 req) - edge-console-p2-p4-buildout:P2-P4 前端補齊(edge-console-operator-frontend +5 req) - unified-governance-console:統一治理控制台北極星,純規格(新 capability unified-governance-console +5 req,openspec/specs/ 40→41) 補 unified-governance-console/spec.md Purpose(原 TBD)。 修正 3 個 spec.md EOF 空行(perl strip)。 roadmap update-log 加 2026-06-04 批次歸檔條目。 npx openspec validate --all --strict = 41 passed / 0 failed。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(openspec): PR #181 reviewer spec-correctness 四項修正(live-spec reconciliation) 1. unified-governance-console §highlightPrimsRequest:明確指 `web-viewer-sample/src/Window.tsx` React 元件 private method `_sendStreamMessage`,非 browser global Window。 2. unified-governance-console §前端禁令:限縮為「governance / 資料 API 禁直連 :49102」,明確 carve-out primary viewer ↔ Kit WebRTC 串流 + DataChannel(含 highlightPrimsRequest / focusPrimRequest)為既有合法 runtime 通道,對齊 AGENTS.md §3.5/§6 boundary。 3. unified-governance-console §operator 頁路由:改為 `/console#coordinator` / `#intake` / `#runtime` hash 路由,與既有 EdgeConsole.tsx 零依賴 hash 路由一致,不捏造後端 path router。 4. edge-console-operator-frontend §provenance 型別:補全權威集合為 `asbuilt | artifact | demo | p1 | p15 | p3 | p4`,與 data.ts Prov 型別及 A4–A10 roadmap 標示一致,消除 p3/p4 不一致。 validate: 41 passed, 0 failed Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(spec): 修正 PR #181 兩項 reviewer findings(unified-governance-console) **修正 1(provenance 集合補 p3/p4)** - Requirement「前端 SHALL 只經 coordinator…誠實 provenance」原窄化為 `asbuilt / artifact / demo / p1 / p15`,但同 commit 的 `edge-console-operator-frontend` spec 與 `web-viewer-sample/src/console/data.ts` 已含 `p3` / `p4` - 補成完整集合並加說明:p3/p4 為 RM phase 3/4 願景項, 與上述兩份 artifact 的 Prov 型別定義一致 **修正 2(A1–A10 新治理工作流編號明確註記)** - MVP 流程描述中的 A1–A10 非舊 roadmap-data.jsx RM_APPS 誤植, 而是 2026-06-04 使用者拍板的新治理工作流編號 - 加入 HTML comment 明確說明新舊編號的刻意差異, 並聲明本 capability spec 為新編號的權威對映 validate: 41 passed, 0 failed Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
摘要
以 OpenSpec change
edge-console-p2-p4-buildout(capability:edge-console-operator-frontend)實作 Edge Console P2–P4 前端建置,只動web-viewer-sample/src/console/(守 viewer repo 邊界)。誠實鐵律最高優先。coordinatorClient.ts(只打 :8004)。AppVisionPage(吃A1A10_DETAIL,整段標 vision、scenario 標範例情境);Prov加 p3/p4;右欄 Agent suggested prompts(disabled)+ disabled 輸入框;FlowBar + Tweaks(操作員/技術用語、scenario clean/warn)。/ui/open?session=+ 本地/?session=),不動App.tsx/Window.tsx。3 個 logical commit(P2 / P3 / P4)。不 merge——留給主對話跑真實 IFC E2E + buffered-merge。
端點查證(誠實鐵律核心)
逐一查證
bim-review-coordinator/src/app.ts:真實 coordinator-owned 端點(已接,只打 :8004):
GET /health、GET /api/runtime/status(sessions / kit bindings / ifc_ready jobs / observations)GET /api/external/ifc-ready[?limit]+/:jobIdGET /api/review-sessions/:id/stream-configGET /ui/open?session=(server-side redirect 至 browser-visible viewer)/api/governance/*,由既有 governanceClient 走)判定不存在(幻覺端點)→ 改誠實處理:
/api/governance/uploads、/api/governance/runtime/{sessions|health|metrics}→ app.ts 無對應 route → 不使用、不 mock;改用真實/api/runtime/status取等價 runtime summary。GET /api/internal/callback-outbox/:id存在但受 internal-token gate(瀏覽器不可達)→ 不在 coordinatorClient 提供;callback 改由 ifc_ready job 的callback_outbox_id觀察,不捏造投遞數。Frontend Verification
http://127.0.0.1:8004/ui→ 導向/console(Edge Console,hash 路由各頁)expected_mapping_url或操作員貼入scripts/deploy.ps1golden path 起 coordinator :8004 + viewer,瀏覽器開http://127.0.0.1:8004/ui→/console(待主對話跑真實 IFC E2E)驗證
npx tsc --noEmit→ 0 errorsnpx vitest run→ 50 passed / 0 fail(baseline 40 + 10 新誠實斷言)npx vite build→ 成功(chunk-size 警告為既有,非錯誤)npx openspec validate edge-console-p2-p4-buildout --strict→ validnpx openspec validate --all --strict→ 41 passed / 0 failedgit diff --cached --check→ 無 trailing whitespace / EOF blank邊界與依賴
:8004;永不直連:49100/:49101/:49102;不渲染 3D;不復活退役 server-push highlight;不動App.tsx/Window.tsx。src/types/mapping.tsfake 隔離工具(不重造)。🤖 Generated with Claude Code