Skip to content

docs(openspec): archive coordinator-auto-poll-streaming-conversion 並同步 specs + roadmap - #99

Merged
monkey1sai merged 1 commit into
mainfrom
codex/openspec/archive-coordinator-auto-poll-streaming-conversion
May 22, 2026
Merged

monkey1sai merged 1 commit into
mainfrom
codex/openspec/archive-coordinator-auto-poll-streaming-conversion

Conversation

@monkey1sai

Copy link
Copy Markdown
Owner

Summary

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 三項:CONVERSION_POLL_ENABLED / CONVERSION_POLL_INTERVAL_SECONDS / CONVERSION_POLL_MAX_ATTEMPTS)
    • 加 3 新 Scenario:Dispatch auto-schedules / Auto-poll de-duplicates with manual / Poll timeout failed-equivalent
    • 加 implementation status note(reference 本 change 與 PR coordinator auto-poll streaming conversion:dispatch 後自動 ingest viewer_url #98 + L4 zero-touch 驗證)
  • docs/plans/AI-BIM-governance-saas-roadmap-2026-05.md 加 archive 摘要

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

fast-mvp loop zero-touch automation 完成 ✨

階段 Item
OpenSpec changes archived remove-conflict-review-from-fast-mvp + fast-ifc-link-demo-loop + streaming-server-prefer-local-ifc-path + coordinator-auto-poll-streaming-conversion
Hotfix bundle PR #94 / #95 / #96 / #98
L4 真實驗證 2026-05-22 zero-touch end-to-end:dispatch → 40 秒內 viewer_url 自動出現,無任何 manual ingest trigger

整條 fast-mvp loop 從 spec 到 code 完整對齊並真實跑通。

🤖 Generated with Claude Code

…步 specs + roadmap

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>
Copilot AI review requested due to automatic review settings May 22, 2026 05:35
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@monkey1sai has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 44 minutes and 20 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2cad4c69-8ea3-40be-a3fe-31f8c580bc95

📥 Commits

Reviewing files that changed from the base of the PR and between 2103bf7 and d33345d.

📒 Files selected for processing (7)
  • docs/plans/AI-BIM-governance-saas-roadmap-2026-05.md
  • openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/acceptance.md
  • openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/design.md
  • openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/proposal.md
  • openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/specs/conversion-webhook-lifecycle/spec.md
  • openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/tasks.md
  • openspec/specs/conversion-webhook-lifecycle/spec.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/openspec/archive-coordinator-auto-poll-streaming-conversion

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 merged commit de4fbd9 into main May 22, 2026
2 checks passed
@monkey1sai
monkey1sai deleted the codex/openspec/archive-coordinator-auto-poll-streaming-conversion branch May 22, 2026 05:35

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

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

>
> **2026-05-19 更新(B 方案 intake smoke 現行證據)**:`scripts/smoke-bscheme-intake.ps1` 已從 contract-stub API-only smoke 擴成「contract checks + optional real `storage/*.ifc` → coordinator intake → streaming conversion polling → coordinator callback outbox」的最小整合驗證入口。本 8caa worktree 的 `storage/*.ifc` 目前為 **0 檔**,因此 `real_ifc_fixture=blocked`、`real_ifc_intake_conversion=blocked`;contract/API 層仍通過(repo-root pytest 7、coordinator verify 140、streaming conversion pytest 10、callback outbox passed)。GPU/Kit 層本次 `runtime_image_kit_launcher=deferred`,實際 blocker 為 **Docker engine not available**;single Kit render 為 `deferred`、multi-viewer 與 USD stage composition 為 `not_observed`。證據:`docs/verification/evidence/2026-05-18-bscheme-intake-smoke/bscheme-readiness.json` 與 `docs/verification/evidence/2026-05-18-t0-kit-launcher/kit-launcher-readiness.json`。
>
> **2026-05-22 更新(`coordinator-auto-poll-streaming-conversion` archive 對齊;fast-mvp loop zero-touch automation 完成)**:本 change(implementation PR #98,2026-05-22 merged,squash `2103bf7`)已完成 **OpenSpec sync/archive**(archive folder `openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/`;`openspec/specs/` 26 保持 **26**,本次為 `conversion-webhook-lifecycle` capability **MODIFIED** 1 個 requirement(`Coordinator ingests host-native conversion result into callback outbox` 加 SHALL auto-poll 子條款 + 3 新 Scenario + implementation status note);totals + 0 added / ~ 1 modified / - 0 removed)。`openspec validate --specs --strict` = **26 passed / 0 failed**。本 change 補實該 requirement 早已寫的「ingest through polling, an internal result loop, or an equivalent internal callback」但 polling / internal result loop **皆未實作**的 gap:`bim-review-coordinator/src/services/streamingConversionClient.ts` 加 module-level `isTerminalConversionResult` helper + class method `pollConversionResult(jobId, options): PollerHandle`(setTimeout chain 避免 setInterval overlap、cancel()、max attempts → poll_timeout fake failed result);`bim-review-coordinator/src/config.ts` 加 `conversionPollEnabled`(default true)/ `conversionPollIntervalSeconds`(default 5)/ `conversionPollMaxAttempts`(default 60 = 5 分鐘 ceiling)+ `parseBooleanEnv`;`bim-review-coordinator/src/app.ts` 加 `pollerRegistry: Map<conversion_job_id, PollerHandle>`、refactor 既有 manual ingest 邏輯抽成共用 helper `ingestStreamingConversionResult`、dispatch 成功後 `schedulePollerForConversion`、manual endpoint 開頭 cancel + delete registry(去重)、`CoordinatorApp` 加 `dispose()` shutdown hook。**Verification(本 change L1-L4)**:coordinator `npm run verify` = 12 files / **173 tests passed**(168 既有 + 5 新 `auto-poll-conversion.test.ts` cover happy path / failed / duplicate dispatch budget / manual cancel auto / disabled config);streaming-server `pytest tests -q` = **31 passed**(不動,regression OK);root pytest 9 passed;GitNexus pre-impact LOW for `fetchConversionResult` / `createCoordinatorApp`;**L4 真實 runtime end-to-end 第一次 zero-touch 跑通**:docker compose recreate coordinator(讀新 code,帶 absolute `RUNTIME_STORAGE_ROOT`)→ `POST /api/external/ifc-ready` → fixture trick 確保 IFC 落地 → **無任何 manual POST ingest** → 40 秒內 coordinator `GET /api/external/ifc-ready/<job>` 返回 `conversion_status: ready` + `viewer_url: http://127.0.0.1:8004/ui/open?session=review_session_<id>`(2026-05-22 timestamp)。**注意**:本 archive 不持久化 poller state(coordinator restart 後 in-memory timers lost,手動 endpoint 仍可救);不解雲端 callback outbox retry / dead-letter(另一條既有 requirement 不動);不引入 streaming-server push callback(本 change 走 coordinator pull)。**fast-mvp loop 從 spec 到 code 從 zero-touch 自動化的角度完整收尾(架構完整對齊 + 自動跑通)**:OpenSpec changes archived = `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。

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 Update roadmap HTML after syncing roadmap markdown

This archive-sync entry updates the roadmap markdown, but the paired HTML view was not regenerated in the same commit. Per AGENTS.md workflow rules, roadmap sync must also refresh docs/plans/AI-BIM-governance-saas-roadmap-2026-05.html; otherwise the human-facing HTML drifts from the markdown source of truth and can hide the new archive/evidence status from reviewers who read the HTML view.

Useful? React with 👍 / 👎.

### Requirement: Coordinator ingests host-native conversion result into callback outbox

Coordinator SHALL ingest the host-native conversion result through polling, an internal result loop, or an equivalent internal callback. A ready conversion result SHALL be transformed into the existing metadata-only `conversion_result_ready` callback outbox entry; a failed result SHALL become `conversion_failed`. Callback delivery state SHALL remain separate from conversion success.
Coordinator SHALL ingest the host-native conversion result through polling, an internal result loop, or an equivalent internal callback. **A successful dispatch to `bim-streaming-server` SHALL automatically schedule an in-process polling task that periodically fetches `GET /api/conversions/<conversion_job_id>/result` until the result reaches a terminal state(`status` ∈ {`succeeded`, `succeeded_with_warnings`, `failed`, `cancelled`} or `model_status` ∈ {`ready`, `failed`}),then runs the same ingestion path as the manual `POST /api/internal/conversions/<id>/ingest` endpoint(callback outbox enqueue + local review session handoff per existing requirements).** Polling cadence and max attempts SHALL be configurable via env(`CONVERSION_POLL_INTERVAL_SECONDS` default `5`,`CONVERSION_POLL_MAX_ATTEMPTS` default `60`= 5 分鐘 ceiling);env `CONVERSION_POLL_ENABLED=false` MAY disable auto-poll for test fixtures while keeping the manual endpoint functional. A ready conversion result SHALL be transformed into the existing metadata-only `conversion_result_ready` callback outbox entry; a failed result SHALL become `conversion_failed`. Callback delivery state SHALL remain separate from conversion success. The same conversion_job_id MUST NOT spawn duplicate concurrent pollers; the manual ingest endpoint MUST cancel any active poller for that conversion_job_id before running ingestion to prevent double-delivery.

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 Define failed callback mapping for cancelled terminal status

The updated requirement makes status="cancelled" a terminal poll outcome, but the same paragraph only specifies callback mapping for ready and failed results, leaving cancelled behavior implicit. This ambiguity can lead an implementation to stop polling on cancelled without enqueuing conversion_failed, causing inconsistent outbox behavior across implementations that follow this spec literally.

Useful? React with 👍 / 👎.

### Requirement: Coordinator ingests host-native conversion result into callback outbox

Coordinator SHALL ingest the host-native conversion result through polling, an internal result loop, or an equivalent internal callback. A ready conversion result SHALL be transformed into the existing metadata-only `conversion_result_ready` callback outbox entry; a failed result SHALL become `conversion_failed`. Callback delivery state SHALL remain separate from conversion success.
Coordinator SHALL ingest the host-native conversion result through polling, an internal result loop, or an equivalent internal callback. **A successful dispatch to `bim-streaming-server` SHALL automatically schedule an in-process polling task that periodically fetches `GET /api/conversions/<conversion_job_id>/result` until the result reaches a terminal state(`status` ∈ {`succeeded`, `succeeded_with_warnings`, `failed`, `cancelled`} or `model_status` ∈ {`ready`, `failed`}),then runs the same ingestion path as the manual `POST /api/internal/conversions/<id>/ingest` endpoint(callback outbox enqueue + local review session handoff per existing requirements).** Polling cadence and max attempts SHALL be configurable via env(`CONVERSION_POLL_INTERVAL_SECONDS` default `5`,`CONVERSION_POLL_MAX_ATTEMPTS` default `60`= 5 分鐘 ceiling);env `CONVERSION_POLL_ENABLED=false` MAY disable auto-poll for test fixtures while keeping the manual endpoint functional. A ready conversion result SHALL be transformed into the existing metadata-only `conversion_result_ready` callback outbox entry; a failed result SHALL become `conversion_failed`. Callback delivery state SHALL remain separate from conversion success. The same conversion_job_id MUST NOT spawn duplicate concurrent pollers; the manual ingest endpoint MUST cancel any active poller for that conversion_job_id before running ingestion to prevent double-delivery.

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 Use API terminal field name consistently in polling rule

The new terminal-state clause says polling should stop when model_status is terminal, but this same spec defines the upstream result payload using model.status (see the ready scenario). Because this sentence governs how callers interpret GET /api/conversions/<id>/result, using the internal flattened name here can cause implementers to watch a non-existent API field and poll until timeout even after upstream has reached terminal.

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

Archives the OpenSpec change for coordinator auto-poll streaming conversion ingestion and syncs the resulting requirement/scenario updates into the main conversion-webhook-lifecycle spec, plus a roadmap entry documenting the archive/verification.

Changes:

  • Synced conversion-webhook-lifecycle with an expanded “Coordinator ingests …” requirement, implementation-status note, and 3 new scenarios for auto-poll behavior.
  • Added the archived OpenSpec change bundle under openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/ (proposal/design/tasks/acceptance + spec delta).
  • Updated the May 2026 SaaS roadmap with an archive summary and verification notes.

Reviewed changes

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

Show a summary per file
File Description
openspec/specs/conversion-webhook-lifecycle/spec.md Syncs the main spec requirement + scenarios + implementation status note for coordinator auto-poll ingestion.
openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/tasks.md Archived tasks checklist/reference path for the change.
openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/specs/conversion-webhook-lifecycle/spec.md Archived spec delta capturing the requirement/scenario modifications.
openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/proposal.md Archived rationale and intended implementation outline for auto-poll.
openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/design.md Archived design notes describing poller behavior, idempotency, and failure modes.
openspec/changes/archive/2026-05-22-coordinator-auto-poll-streaming-conversion/acceptance.md Archived acceptance criteria and verification checklist.
docs/plans/AI-BIM-governance-saas-roadmap-2026-05.md Adds a roadmap archive summary entry with verification notes and references.

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

### Requirement: Coordinator ingests host-native conversion result into callback outbox

Coordinator SHALL ingest the host-native conversion result through polling, an internal result loop, or an equivalent internal callback. A ready conversion result SHALL be transformed into the existing metadata-only `conversion_result_ready` callback outbox entry; a failed result SHALL become `conversion_failed`. Callback delivery state SHALL remain separate from conversion success.
Coordinator SHALL ingest the host-native conversion result through polling, an internal result loop, or an equivalent internal callback. **A successful dispatch to `bim-streaming-server` SHALL automatically schedule an in-process polling task that periodically fetches `GET /api/conversions/<conversion_job_id>/result` until the result reaches a terminal state(`status` ∈ {`succeeded`, `succeeded_with_warnings`, `failed`, `cancelled`} or `model_status` ∈ {`ready`, `failed`}),then runs the same ingestion path as the manual `POST /api/internal/conversions/<id>/ingest` endpoint(callback outbox enqueue + local review session handoff per existing requirements).** Polling cadence and max attempts SHALL be configurable via env(`CONVERSION_POLL_INTERVAL_SECONDS` default `5`,`CONVERSION_POLL_MAX_ATTEMPTS` default `60`= 5 分鐘 ceiling);env `CONVERSION_POLL_ENABLED=false` MAY disable auto-poll for test fixtures while keeping the manual endpoint functional. A ready conversion result SHALL be transformed into the existing metadata-only `conversion_result_ready` callback outbox entry; a failed result SHALL become `conversion_failed`. Callback delivery state SHALL remain separate from conversion success. The same conversion_job_id MUST NOT spawn duplicate concurrent pollers; the manual ingest endpoint MUST cancel any active poller for that conversion_job_id before running ingestion to prevent double-delivery.

#### Scenario: Auto-poll de-duplicates with manual ingest endpoint

- **WHEN** a poller is active for `conversion_job_id` and the operator(or other internal caller)POSTs `/api/internal/conversions/<conversion_job_id>/ingest` with a valid internal token
monkey1sai added a commit that referenced this pull request May 22, 2026
…error 帶 log path (#100)

* streaming-server capture Kit conversion logs:async redirect + result.error 帶 log path(streaming-server-capture-kit-conversion-logs)

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

## Why

2026-05-22 user 用 341MB 真實 IFC 跑 fast-mvp loop,coordinator pipeline 全 work
(下載 / dispatch / sandbox / auto-poll / ingest),但 Kit subprocess `exit 0` 沒寫
model.usdc,error message 只有 ps1 line 316 throw 字串(`"output was not created"`)。

根因:`bim-streaming-server/scripts/convert-ifc-to-usdc.ps1` 用 `Process.Start` 沒設
`RedirectStandardOutput` / `RedirectStandardError`,Kit subprocess 所有 stdout/stderr
直接寫到 PowerShell host 主控台(被吞)沒進 conversion result。任何「Kit silently exit 0
但沒寫 output」debug 線索皆無。

## What changed(9 files / +575 / -15)

### ps1(+77 / -15)
- `convert-ifc-to-usdc.ps1::Invoke-KitConversion`:
  - 加 `$startInfo.RedirectStandardOutput = $true` / `RedirectStandardError = $true`
  - artifact dir 內開 `kit-stdout.log` / `kit-stderr.log`(AutoFlush UTF-8 StreamWriter)
  - async `Register-ObjectEvent` + `BeginOutputReadLine` / `BeginErrorReadLine` 避免
    sync ReadToEnd + WaitForExit 大量 output 經典 deadlock
  - finally:second WaitForExit(drain pending events)→ Unregister-Event → close writer
  - 失敗 throw 改 multi-line message,含:reason、kit_stdout_log 路徑、kit_stderr_log 路徑、
    stderr last 100 行 tail、stdout last 50 行 tail
  - 成功時 log file 仍保留(baseline 對比用)

### Python adapter(+15)
- `conversion_authority.ConversionAuthorityError`:加 optional `metadata: dict | None`
  attribute(backward compat:既有 raise 不影響)
- `ifc2usdc_powershell_adapter._run_powershell_conversion`:subprocess fail 時 regex 從
  combined stderr/stdout 抓 `kit_stdout_log:` / `kit_stderr_log:` 兩行 host absolute path,
  附到 ConversionAuthorityError.metadata
- `conversion_authority.StreamingConversionStore._fail_job`:加 optional `metadata` 參數,
  merge 進 `result.error` dict;catch ConversionAuthorityError 那條 path 傳入 exc.metadata

### Pytest(+58)
- `tests/test_host_native_conversion_service.py` 加 2 case:
  - failed conversion with metadata → result.error 含 kit_stdout_log / kit_stderr_log
  - regression:沒 metadata 不該硬塞 keys(`FakeFailedConverter` 既有 path 不破)

### OpenSpec(5 files / +398)
- proposal / design / tasks / acceptance / `streaming-ifc-usdc-conversion-authority`
  MODIFIED requirement(`Conversion failures expose actionable diagnostic`)+ 4 新 Scenario

## GitNexus blast radius = LOW

| symbol | risk | d=1 |
|---|---|---|
| `_run_powershell_conversion` | LOW | `convert`(同 class) |
| `Ifc2UsdcPowershellConverterAdapter` | LOW | `host_native_conversion_service.py` import |

## Verification

| Level | Result |
|---|---|
| L1 streaming-server `pytest tests -q` | **33 passed**(31 既有 + 2 新) |
| L1 coordinator `npm run verify` | **173 passed**(不動,regression OK) |
| L1 root pytest | **9 passed** |
| L2 `openspec validate streaming-server-capture-kit-conversion-logs --strict` | **valid** |
| L2 `openspec validate --specs --strict` | **26 passed / 0 failed** |
| L3 GitNexus pre-impact | LOW |
| L4 真實 runtime | **跳過** — 留 merge 後重啟 streaming-server 讀新 code + user 重 trigger 341MB IFC,看 GET /result error 含 kit_stdout_log / kit_stderr_log 並 tail 看 Kit 真實錯誤訊息 |

## Backward compatibility

- 既有 ConversionAuthorityError 不帶 metadata raise 點(>10 處)全部不變(metadata 預設 None)
- result.error 加 keys 是純 additive(`code` / `message` 仍在)
- callback outbox payload 不變(metadata-only,log paths 屬 host-local diagnostic,
  不轉發雲端,per `conversion-webhook-lifecycle` 原則)
- 既有 11+168+9 tests 全綠

## Predecessor / Scope

✓ Predecessor:`coordinator-auto-poll-streaming-conversion`(archive PR #99,2026-05-22)
本 change 只加觀察性,**不嘗試 fix Kit 自己為什麼 silent exit 0 沒寫 USDC**(那是 Kit /
HOOPS 本身的問題);下一個 change 可以拿本 change 收集的 Kit log 做 root cause analysis。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(streaming-server): code review:message 顯式 prepend log paths + 加 regex unit test

Review feedback on PR #100 from senior code reviewer:

- **Important #1**:`_run_powershell_conversion` 內 `[-800:]` tail truncation 可能
  把 spec scenario 1 required substring `"---- stderr tail (last 100 lines) ----"`
  砍掉。改成 message 開頭顯式 prepend `kit_stdout_log: ` + `kit_stderr_log: ` 兩行
  +tail(額度提到 3000 chars,容納 header 與 tail 內容),保證 spec 要的 substring 仍在。
- **Important #2**:加 `test_run_powershell_conversion_regex_extracts_log_paths_from_ps1_throw`
  unit test,monkeypatch `subprocess.run` 返回真實 ps1 throw heredoc shape(含 Windows
  path 的 `C:\` drive-letter colon 與 backslash),assert regex 抓兩個 path 對 +
  ConversionAuthorityError.message 含 spec substring。鎖定 ps1 throw shape ↔ Python
  regex 契約,L1 直接 cover。
- **Minor #3**:`import re` 移到 module top(consistent with other stdlib imports),
  移除 inline `import re as _re`。

Verification:
- streaming-server pytest:**34 passed**(33 + 1 新 regex test)
- 既有 33 case 不破

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

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