| 項目 | 內容 |
|---|---|
| 日期 | 2026-06-08 |
| 性質 | Feasibility 評估(非 bug、無 live bug) |
| 結論 | 採方案 c:文件化現狀,不做合併。目前無第二個稽核產品,合併收益收不到、成本高 |
| 來源 | 套件重刻漂移收斂案例2;詳細 method 對照見 docs/analysis/2026-06-07-flow-engine-package-vs-be-divergence.md |
BE app/flow_engine/service/workflow_execution_service.py(1615 行)把 WorkflowExecutionService 重寫成產品專屬超集,與 jedi-flow-engine 套件版(598 行)各自演化。要不要把兩份收斂成一份?
結構:BE 是嚴格超集 —— 13 個同名 method + 17 個 BE 獨有 + 套件獨有 0。
complete_job / revert_job / start_workflow_execution):核心 BPMN 邏輯相同,但 BE 把產品副作用「織」進控制流。以 complete_job 為例(套件 112 行 → BE 171 行),同一骨架插了 9 個產品副作用點:權限守門(C16)、GrcErrorCode、AP-task 通知、專案狀態、I7 CANCEL-aware 判定、AP-task 狀態、job_execution_uid 注入(巢狀子流程)、survey 關聯、todo 通知。revert_job 更甚(86 → 221 行)。assert_project_participant / complete_main_workflow_job / notify_* / process_survey_property / update_assessment_plan_task_job_link / build_task_combinations 等,全依賴 BE 專屬 domain(AP / Project / Participant / Notification / Survey / Drive),無法進通用套件。現況其實已經分兩層:
| 層 | 在哪 | 重用性 |
|---|---|---|
| 通用 BPMN 引擎 | jedi-flow-engine 套件(598 行) | 已可重用——不同領域的產品今天就能拿去用 |
| GRC/稽核編排(17 method + 9 織入副作用) | BE 主專案 | 綁主專案;只有「另一個稽核產品」會想共用 |
「很多是這個產品的核心、寫在主專案」本身是對的(DDD:產品專屬編排該在產品端,不是技術債)。
未來若出現第二個產品:
jedi-audit-workflow(疊在 flow-engine 之上、裝稽核編排,產品專屬部分 adapter 注入,mirror FR-032 jedi_information_system 抽法)——不是把東西塞進通用的 jedi-flow-engine(會污染通用層)。兩條路(hook 化 / 抽 audit 層)都得先把副作用從控制流裡 un-weave,這才是真成本,且只有在真有第二個稽核產品時才划算。
| 方案 | 內容 | 評估 |
|---|---|---|
| a 對齊現況 | 套件版 5 項修正已是 BE 行為的可攜等價物 | 已完成,無動作 |
| b 完整合併 | BE 拆薄層 + 套件補 lifecycle hook + 巢狀 sub-process | 不採:去重收益僅 ~250~300 行共用骨架;17 個 BE method + 9 織入副作用合併後仍留 BE;要動稽核引擎核心 + 全回歸;無 live bug、無第二 consumer |
| c 文件化現狀 ✅ | 承認刻意雙實作,文件化邊界 | 採用:低風險;本文件即現狀紀錄 |
| 若有第二個稽核產品才做 | defer,trigger 見 §6 |
對 BE WorkflowExecutionService 查 DDD 分層 / transaction / error handling:
| 檢查項 | 結果 |
|---|---|
app 層碰 infra session / ORM(get_session / session.query / self.session) |
✅ 無 |
| 直接 import infra ORM model / method 內 new RepoImpl | ✅ 無(走注入的 domain service) |
裸 raise ValueError/Exception(應用 ErrorCode) |
✅ 無(用 GrcErrorCode) |
public method @transaction |
✅ 齊全(2 個例外為 false positive:build_task_combinations 純運算不需、assert_project_participant 僅在 @transaction method 內被呼叫的 re-entrant guard) |
| 權限檢查在 service 層 | ✅ assert_project_participant(C16) |
結論:BE 版完全合規,且比套件版乾淨(套件版在 method 內 WorkflowExecutionDomainService(WorkflowExecutionRepoImpl()) 直接實例化 repo;BE 版走 DI 注入的 domain service)。唯一小建議:assert_project_participant 命名無底線但實為內部 guard,可加底線或 docstring 標「caller 須在 @transaction scope」——cosmetic,不影響運作。
jedi-audit-workflow 套件層」(非合併進 flow-engine),屆時才做副作用 un-weave。承上架構討論:把 GRC 編排整進套件永遠是錯的(依賴倒置 + 污染 bounded context)。但有一類例外 —— BE 自己刻了、但本質上屬於通用 BPMN 引擎的能力,理論上該下沉到 jedi-flow-engine(讓引擎原生支援),而非留在 BE fork。候選:
| 候選能力 | 目前在 BE | 下沉條件(動手前必先 verify) |
|---|---|---|
| 巢狀 sub-process 遞迴實體化 | _instantiate_sub_workflow、_create_leaf_jobs |
確認遞迴邏輯不含 GRC 假設(純 BPMN call-activity 展開)才可下沉 |
job_execution_uid 注入 XML |
_patch_template_xml_job_uids、_inject_job_execution_uid |
確認是通用「實體化時把 execution uid 寫回模板 XML」機制、非 GRC 專屬 |
注意事項:
本 arc 以方案 c 結案,不開實作。FR-034 狀態標「feasibility done — 方案 c」。