Skip to content

修正 A1 選檔後可直接執行治理檢核 - #291

Merged
monkey1sai merged 4 commits into
mainfrom
fix/a1-direct-rule-run
Jul 3, 2026
Merged

monkey1sai merged 4 commits into
mainfrom
fix/a1-direct-rule-run

Conversation

@monkey1sai

@monkey1sai monkey1sai commented Jul 3, 2026 •

Copy link
Copy Markdown
Owner

摘要

  • 修正 A1「執行規則檢核」不再要求先選 review session;選定 IFC 後直接走 POST /api/governance/rule-runs。
  • review session 改回只作為 Review Room / 3D handoff / mapping enrichment 的 optional target。
  • 更新 A1 狀態機與測試,防止再回到 createRuleRunForSession gating。
  • 補上 a1Machine.test.ts,移除舊 PICK_SESSION for-session 契約,改驗證 A1 v2 必須以已選 IFC 作為 CPU rule-run 目標。
  • Formal spec evidence:docs/superpowers/specs/2026-07-03-a1-direct-ifc-rule-run.md。

驗證

  • npm test -- A1ViewerEmbed.test.tsx console.test.tsx
  • npm test -- a1Machine.test.ts
  • npm run build
  • npm run verify
  • git diff --cached --check
  • GitNexus impact(a1Reducer, upstream, includeTests=true):risk LOW
  • GitNexus detect_changes(scope=staged):第一次 implementation risk medium,第二次 test-only risk low,spec evidence docs-only risk low,無 HIGH/CRITICAL

Frontend Verification

項目 結果
Frontend route http://127.0.0.1:8004/ui/#a1(本 PR 未重啟測試部署區實機驗證)
Main button(s) tested a1-step-pick, a1-step-run via Vitest/jsdom
Fixture used mocked MinIO source IFC 松風庵/root/main/u1/model.ifc + sample IDS path
Visible success state 選定 IFC 後,不需 review session 即可啟用「執行規則檢核」,並呼叫 direct rule-run API;3D Review Room / highlight 仍維持 session-gated
E2E command 未跑 gstack/browser E2E;本輪跑 npm run verify 覆蓋 viewer build、Vitest、struct-log
Screenshot / trace 未產生新截圖;Vitest/jsdom 驗證 createRuleRun 呼叫與 createRuleRunForSession 不被呼叫
Known gaps 部署區畫面需重建/重啟後才會反映此 source 變更;完整瀏覽器與 Kit/WebRTC E2E 不在本 PR 驗證範圍

Copilot AI review requested due to automatic review settings July 3, 2026 09:53
@coderabbitai

coderabbitai Bot commented Jul 3, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR decouples governance rule-run execution from review session selection in the A1 workflow ("A1 v2"). The state machine removes the PICK_SESSION event and gates RUN on step progress plus a valid ifcPath. The workbench page calls createRuleRun directly against the selected IFC, with review sessions now optional for 3D Review Room handoff. UI copy and extensive test suites are updated accordingly.

Changes

A1 v2 run decoupling

Layer / File(s) Summary
State machine event and gating changes
web-viewer-sample/src/console/a1Machine.ts
Removes PICK_SESSION from A1Event, tightens the RUN reducer guard to require non-idle step and truthy ifcPath, and updates a UI step comment.
Workbench page run flow and UI copy
web-viewer-sample/src/console/pages.tsx
doRun gates on ifcPath and calls createRuleRun directly instead of a session-based API; button captions, step labels, and review-session panel text updated to reflect session as an optional 3D handoff target.
Test suite updates for createRuleRun and pickModel flow
web-viewer-sample/src/console/A1ViewerEmbed.test.tsx, web-viewer-sample/src/console/console.test.tsx
Adds a pickModel() helper, replaces createRuleRunForSession mocks with createRuleRun across workflow/polling/export tests, and updates SSR smoke assertions for new copy and gating.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant A1GovernanceWorkbenchPage
  participant a1Reducer
  participant governanceClient

  User->>A1GovernanceWorkbenchPage: pick IFC model
  A1GovernanceWorkbenchPage->>a1Reducer: dispatch PICK_FILE (ifcPath)
  User->>A1GovernanceWorkbenchPage: click run validation
  A1GovernanceWorkbenchPage->>a1Reducer: dispatch RUN
  a1Reducer-->>A1GovernanceWorkbenchPage: allow (step != idle, ifcPath truthy)
  A1GovernanceWorkbenchPage->>governanceClient: createRuleRun(ifc_source_path, ids_path)
  governanceClient-->>A1GovernanceWorkbenchPage: run result
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: A1 can run governance checks directly after selecting a file.
✨ 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 fix/a1-direct-rule-run

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.

@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: ba726537bc

ℹ️ 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".

Comment on lines +365 to +367
const { rule_run_id } = await governanceClient.createRuleRun({
ifc_source_path: state.ifcPath,
ids_path: idsPath || undefined,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Resolve MinIO keys before direct rule-runs

When the user follows the updated A1 flow, state.ifcPath is the selected MinIO object key from /api/minio/objects (for example 松風庵/root/main/u1/model.ifc), but POST /api/governance/rule-runs is a direct pass-through that requires a server-side filesystem path and governance-service rejects anything for which os.path.exists(ifc_source_path) is false. This makes the new “select IFC then run” path fail with ifc_source_path not found; the previous for-session route resolved the session to a host-local IFC path before forwarding.

Useful? React with 👍 / 👎.

@@ -637,14 +632,13 @@ export function A1GovernanceWorkbenchPage() {
const nextSession = e.target.value;
if (nextSession === selectedSession) return;
setSelectedSession(nextSession);

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 session-scoped results when switching sessions

If an operator runs validation while session A is selected, the success path can enrich state.failed with USD prim paths from A's expected_mapping_url; this handler then lets them switch to session B without clearing those results, so the Review Room handoff is built for B while still carrying A's usd_prim_path. In environments with multiple active sessions for different converted stages, that can highlight the wrong prim/stage; clear or re-enrich the stored results on session changes.

Useful? React with 👍 / 👎.

export type A1Event =
| { type: "PICK_FILE"; ifcPath: string }
| { type: "PICK_SESSION" }
| { type: "RUN" }

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 Remove or update stale PICK_SESSION tests

After this event union drops PICK_SESSION, src/console/a1Machine.test.ts still dispatches { type: "PICK_SESSION" } in two tests that expect the reducer to enter picked/running; running npm test -- a1Machine.test.ts now fails both tests, so the package-level npm run verify gate will fail even though the narrower tests listed in the commit message pass. Please update or remove those stale reducer tests as part of this behavior change.

Useful? React with 👍 / 👎.

Comment on lines +576 to +577
<Btn primary data-testid="a1-step-run" disabled={state.step === "idle" || !state.ifcPath || (state.step === "running" && !state.runError)}
caption={state.ifcPath ? "POST /api/governance/rule-runs" : t("先選定 IFC 模型;不需要 review session 即可檢核", "Select an IFC model first; review session is not required for validation")} onClick={doRun}>

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 Reset the locked IFC when the dropdown changes

After locking model A, changing the MinIO dropdown to model B leaves state.ifcPath set to A while the run button remains enabled because it only checks that state.ifcPath is non-empty; clicking “Run Rule Validation” then submits the stale locked model rather than the model currently shown in the selector. This mismatch matters now that the run path uses state.ifcPath directly, so the dropdown change should clear the locked file or the button should require selectedKey === state.ifcPath.

Useful? React with 👍 / 👎.

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 reworks the A1 governance workbench (web-viewer-sample) so operators can run rule validation immediately after selecting an IFC, rather than being gated on first creating/selecting a review session. The A1Event state machine drops the PICK_SESSION event, RUN gating switches from !selectedSession to !state.ifcPath, and doRun calls governanceClient.createRuleRun({ ifc_source_path, ids_path }) instead of createRuleRunForSession. Review sessions are demoted to an optional target for 3D Review Room handoff / mapping enrichment. UI captions, the first lifecycle step label ("上傳模型" → "選檔"), and the associated tests are updated accordingly.

Changes:

  • Decouple A1 rule-run from review sessions: gate on selected IFC and call the direct POST /api/governance/rule-runs endpoint.
  • Remove the PICK_SESSION event/reducer case and the auto-PICK_SESSION effect; stop resetting state when the session dropdown changes.
  • Update copy/labels and the console.test.tsx / A1ViewerEmbed.test.tsx suites (new pickModel helper, createRuleRun mocks).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

File Description
web-viewer-sample/src/console/a1Machine.ts Removes PICK_SESSION from the event union and reducer; RUN now guards on !state.ifcPath; comment updated for the new first step.
web-viewer-sample/src/console/pages.tsx doRun calls createRuleRun with ifc_source_path: state.ifcPath; run button/gating keyed off state.ifcPath; captions and session panel copy updated; session-change no longer dispatches RESET.
web-viewer-sample/src/console/console.test.tsx Swaps createRuleRunForSession mocks for createRuleRun, removes selectReviewSession helper, updates SSR assertions.
web-viewer-sample/src/console/A1ViewerEmbed.test.tsx Adds pickModel helper; asserts run enables via picked IFC and calls createRuleRun without a session.

Two blocking concerns were found: a1Machine.test.ts (not part of this PR) still references the removed PICK_SESSION event, breaking type-checking and the reducer tests; and the direct createRuleRun call forwards a MinIO object key as ifc_source_path, which governance-service rejects with HTTP 400 since it expects a resolvable local filesystem path. Both are detailed in inline comments.


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

Comment on lines 44 to +45
case "RUN":
// 守門改看 step(非 idle 才前進):picked 可能來自 PICK_FILE(ifcPath 有值)或 PICK_SESSION
// (ifcPath 為空),故不可再用 !state.ifcPath 當「未選檔」判斷,否則 session-pick 後 RUN 會被誤擋。
if (state.step === "idle") return state;
if (state.step === "idle" || !state.ifcPath) return state;
Comment on lines +365 to +368
const { rule_run_id } = await governanceClient.createRuleRun({
ifc_source_path: state.ifcPath,
ids_path: idsPath || undefined,
});

@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: 1c46989786

ℹ️ 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".

try {
const { rule_run_id } = await governanceClient.createRuleRunForSession(selectedSession, { ids_path: idsPath || undefined });
const { rule_run_id } = await governanceClient.createRuleRun({
ifc_source_path: state.ifcPath,

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 Bind the handoff session to the locked IFC

When a review session is selected but belongs to a different converted stage than the locked MinIO key, this new direct run targets state.ifcPath while the later success path still enriches results from selectedSession's expected_mapping_url; because the session dropdown is global and is not filtered or validated against the locked IFC, Review Room can receive USD prim paths from the wrong stage. Clear or validate selectedSession when the IFC is locked, or only enrich/handoff when the session is known to correspond to the same model.

Useful? React with 👍 / 👎.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Agent Summary

Field Value
Status blocked
Risk high
PR 291
Head fix/a1-direct-rule-run / 1c46989786df245e1c2b5c1b2477cb35e1bcedb0
Base main / 35d976f736a6c06f791f6fdd9af21252c5e6e5d6

Blockers

  • [high] Behavior, workflow, code, or repo-boundary changes require an OpenSpec change id or documented exception.

Warnings

  • None

Validation Commands

  • npm run verify

Checks

  • passed web-viewer-sample verify (web-viewer-sample)

Human Review Notes

  • Optional AI adapter is not required by policy and was skipped.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Agent Summary

Field Value
Status passed
Risk low
PR 291
Head fix/a1-direct-rule-run / ff79254d6819e836aa83b8f2fe408918d97a0808
Base main / 35d976f736a6c06f791f6fdd9af21252c5e6e5d6

Blockers

  • None

Warnings

  • None

Validation Commands

  • npm run verify

Checks

  • passed web-viewer-sample verify (web-viewer-sample)

Human Review Notes

  • OpenSpec archive or formal spec evidence detected; active change-id validation was skipped.
  • Optional AI adapter is not required by policy and was skipped.

@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: ff79254d68

ℹ️ 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".

Comment on lines +365 to +368
const { rule_run_id } = await governanceClient.createRuleRun({
ifc_source_path: state.ifcPath,
ids_path: idsPath || undefined,
});

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 Preserve model-version binding for direct runs

When the operator follows the conversion-ready flow, A1 auto-selects the review session for the converted model, but this new direct rule-run body only sends ifc_source_path/ids_path. The previous for-session proxy populated model_version_id from that session before forwarding, and issues_from_rule_run later copies run.model_version_id into every formal issue; with this call those issues (and downstream BCF/diff-impact filtering by model version) are created unbound even though the matching session is available. Include the selected session's model_version_id when it corresponds to the locked model, or keep a resolving endpoint that preserves that field.

Useful? React with 👍 / 👎.

Comment on lines +576 to +577
<Btn primary data-testid="a1-step-run" disabled={state.step === "idle" || !state.ifcPath || (state.step === "running" && !state.runError)}
caption={state.ifcPath ? "POST /api/governance/rule-runs" : t("先選定 IFC 模型;不需要 review session 即可檢核", "Select an IFC model first; review session is not required for validation")} onClick={doRun}>

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 Lock the IFC before conversion-first validation

In the no-active-session path, a1-trigger-convert is enabled by selectedKey, so an operator can select a MinIO object and queue conversion without clicking the separate “Select Model” button. After conversion becomes ready, the session is auto-selected, but the removed PICK_SESSION flow no longer moves the reducer out of idle, and this run button still requires state.ifcPath; the validation step stays disabled until the user goes back and locks the same file. Either lock the selected key when starting/finishing conversion, or require the conversion button to use an already locked IFC.

Useful? React with 👍 / 👎.

@monkey1sai
monkey1sai merged commit 72eee69 into main Jul 3, 2026
12 checks passed
@monkey1sai
monkey1sai deleted the fix/a1-direct-rule-run branch July 3, 2026 10:30
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