FR-089 交接現況(STATE)

這份是 living 檔:每棒就地 Edit,只描述「此刻」。歷史脈絡看同資料夾的 FR-089-LOG.md。 本 arc 是協調者級:涵蓋 FR-089(套件結構統一)母案底下三段——jedi-asset 定形(Done)/FR-090 主專案側收斂(進行中)/FR-091 18 支套用(第一批派出)。

項目
最後更新 2026-09-13 晚(首腦第 3 棒中繼交接:FR-091 25 卡全 Done 已 push;1736 PM 文件卡待驗;下一棒=驗 1736 → 開 arc-review → 收口裁決)
branch BE feature/FR-075;jedi monorepo feature/FR-075;FE feature/FR-075(1741 一顆);test 不動
母案卡 CM-1688 FR-089 https://app.notion.com/p/FR-089-jedi-asset-18-jedi-3d9346da4cd0812ca708cca57d3123b3
子母卡 CM-1682 FR-090 https://app.notion.com/p/FR-090-app-port-wrapper-3d9346da4cd081bb803bc6448ec3b3d0 / CM-1690 FR-091 https://app.notion.com/p/FR-091-18-jedi-jedi-asset-5-3-A-F-logger-runtime-3d9346da4cd0815280cbeb3d644cb2b8
在跑的卡 無。發版 (a) 進行中:21 支已推 Nexus(1.0.0/oscal-v2 2.3.0,jedi 2837fea)、BE pin 還原+pyproject 整理(e0496645)+lock;本機 DEV 已裝 Nexus wheel 起服務,決策者驗中。剩 version-bump(BE 1.20.0/FE 對齊/release note/spec 快照)。CM-1737 Done(首腦驗收,commit 0422c5d6)、CM-1736 Done(決策者看過)。其餘 25 卡 Done。兩 repo feature/FR-075 已 push(BE 至 9fff7772、jedi 至 c26a313;之後文件 commit 已全推,第 4 棒查兩 repo 無領先)
Notion 回寫規範 docs/claude/notion-issue-tracker.md
接手前必讀 §0 讀序

🧭 原始需求 / WHY

這節寫一次,之後各棒不動

  • 決策者原話(2026-09-12):「然後有超多 dataclass 直接寫在 plugin 裡面,這不能另外整理嗎?那隻一堆東西都沒有整理過很難閱讀」→「都做吧,這個作為範例」→「我想要全部做法都統一」→「我不想要在一堆地方設定,這樣接手的人很難上手」。
  • 要解決什麼:FR-069/FR-080 把功能抽成 21 支 jedi-* 套件後,每支長得不一樣(plugin.py 塞 400 行、守門函式各叫各的、logger 五種名、註解塞滿棒號);主專案側接一支套件要翻四五處且每支翻的地方不同。接手者無從上手。
  • 目標模型
    • 套件側:plugin/ 五檔(init/contract/runtime/assembly/migrations);api/guards.pyruntime()+三個 lazy decorator)與 routing.py;logger 掛 common.jedi_<pkg>;entity 一律 dataclass;註解只留「為什麼」與「陷阱」;API 有吐 created_user_name 的才開 identity port。範例=jedi-asset。
    • 主專案側:接一支套件三步——pyproject 一行、新建 core/plugins/<pkg>.py(adapter+填表+註冊三段同檔)、PLUGINS 清單加一列。只有主專案其他模組要直接用套件 domain service 才多第四步(DI)。
  • 三段結構:① jedi-asset 定形(FR-089 自身,Done)→ ② 主專案側收斂(FR-090)→ ③ 18 支套用(FR-091)。DI container 瘦身排 ③ 之後(FR-090 第 6 棒)。
  • 與 FR-080 的關係:FR-080 收口中,其「發版推 Nexus/pin 還原/SPEC/release note」四項 2026-09-12 移入本案,等 18 支整理完一次做(CM-1619 末段已記)。不掛回 FR-080。
  • 說明文件docs/features/FR-089-2609-package-shape-unification/plugin-anatomy.md(袋子比喻、port/adapter、DI 與 runtime、設計模式對照、harness)——工程師第一次接觸先讀這份。

§0 接手讀序

0.1 🔒 先懂需求 gate

  1. 本檔 🧭 WHY 節
  2. docs/features/FR-089-2609-package-shape-unification/plugin-anatomy.md §「這次整理做了什麼」「新手教程」「port 與 adapter」三節(全讀
  3. docs/features/FR-069-2608-jedi-module-extraction/extraction-sop.md §4.3(plugin 分檔規格)與 §5(主專案側)

0.2 現況與待辦

  1. 本檔 §1、§3
  2. FR-089-LOG.md 最後 1 個 block
  3. 待驗的卡 python3 scripts/notion_case.py get <id> > /tmp/x.txt(直接 pipe 會截):CM-1736 3da346da4cd081a8af86d2a3bf50985c。母卡 CM-1690 3d9346da4cd0815280cbeb3d644cb2b8

0.3 需要細節才開

  • jedi-asset 整支(範例);core/asset_wiring.pyinfra/asset/(主專案側現況,第 5 棒會搬)
  • FR-090 README docs/features/FR-090-2609-host-side-residue-cleanup/README.md;FR-091 README

0.4 ✅ 冷接自檢

  1. 為什麼 adapter 最終放 core/plugins/<pkg>.py 不放 infra/?(答:一檔看完優先於分層純度,決策者裁;CM-1684 先搬 infra 再被 CM-1689 改判)
  2. 哪些套件要開 identity port、哪些不要?判準是什麼?
  3. 為什麼 ctx() 改叫 runtime()
  4. FR-080 剩哪些收口項、哪些移來了?
  5. 能力點(capability)現在「誰宣告、誰判定、誰 seed」三件事各在哪?(答:套件 plugin/contract.pyCAPABILITIES 宣告;主專案 core/plugins/_host.pycommon.authz.require_capability 判定,實體 jedi_iam.authz;seed 仍在主專案 04-seed-core.sql,主專案五條守衛比對)
  6. 為什麼驗收要在該卡 commit 的 worktree 跑而不是 HEAD?(答:並行 runner 的後續 commit 會把前一張的綠跑成紅,HEAD 顏色不代表單卡成果;1733/1732 實例)

§1 當前狀態

1.1/1.6 由首腦第 3 棒 2026-09-13 晚更新;1.2 commit 清單停在 09-12(之後 200+commit 見 git log --grep="CM-17",不再逐條列);1.3 卡表為最新;1.4/1.5 未重跑。

1.1 兩 repo git 現況

這是兩個 repo 的 branch/領先/HEAD/working tree 狀況(git status -sb + git log),2026-09-12 18:42 查。未 commit 的檔多半是並行 runner 正在做的,照實列不判斷。

repo branch 領先 origin HEAD working tree
BE compliance-manager-be feature/FR-075 已 push 至 9fff7772,之後文件 commit 數個未推 c2f90adf docs anatomy 重寫(CM-1736) 未 commit:poetry.lockpyproject.toml20 支 path dependency,刻意不 commit;別台機器 clone 跑不起來,發版 pin 還原前留意)
jedi monorepo jedi-python-package feature/FR-075 已 push 至 c26a313,無領先 c26a313 refactor(common) CM-1735 乾淨

1.2 FR-089/090/091 相關 commit 清單

這是兩 repo 用 --grep="CM-16[7-9][0-9]|FR-089|FR-090|FR-091" 撈到的 commit(BE 前 40、jedi 前 30),2026-09-12 18:42 查。含少數同號段內的鄰近 arc(CM-1668~1675 FR-088、CM-1679/1681 註解收斂/修測)一併列出。

BE(新→舊)

hash 卡號 一句話
0ebc6c4f FR-080 收口——design/README/登記表改「已落地」、LOG 第 4 棒
7fad430c CM-1690~1695 docs(FR-091) 登記 18 支套用標準形狀——母卡+第一批五張
3149e48f CM-1686 ⑤⑥ refactor(iam) 兩支 wrapper 瘦成純守門,補暱稱回套件
12b16e68 CM-1686 ④ refactor(iam) 兩支登入薄殼併進 core/iam_wiring.py
f6f47385 CM-1686 ③ refactor(iam) 刪兩支轉發殼,port 實作歸位 infra/iam/
629ed2c2 CM-1687 ④ docs+test 補暱稱唯一路徑焊死+主專案統一形狀進 SOP
c4129183 FR-089 docs 插件解剖說明頁 plugin-anatomy.md 13 節 13 張 mermaid
d9f88a1b CM-1687 ② refactor(common) 補暱稱 helper 改走 D8 IdentityContext
a3f1b626 CM-1687 ① refactor(di) 身分名冊收成單一 IdentityContext
ceb455df FR-089/090 docs 補母卡登記與資料夾——族譜歸位
5a009656 CM-1684 refactor(layout) FR-090 第 2 棒——五處 jedi port 實作歸位 infra//
580ae2df CM-1683 chore(cleanup) FR-090 第 1 棒——刪套件上移後留的空殼
412809a5 CM-1678 docs(spec) 資訊系統盤點頁——enum 值域統一與租戶隔離
18a0a572 CM-1668 註解收斂 BE 51 行「棒號當主詞」
aa90006b 註解收斂 main.py 補一處遺漏
adcae4e1 註解收斂 scripts/
f959c312 註解收斂 domain/、infra/
000acb2b 註解收斂 di_containers/
7f4cc9bf CM-1677 ⑤ docs(SOP) §4.3 定名 runtime() 不叫 ctx()
42a86c1e 註解收斂 api/、app/、common/、core/upload_file_wiring.py
d5c914a3 註解收斂 api/、setup/ 四層
fe8f6883 註解收斂 config/config_util.py、config_loader.py、app_modules.py
bbbb547f 註解收斂 config/config.py
4cec216d 註解收斂 core/scheduler.py
a13676e0 註解收斂 core/app_factory.py
b190584d 註解收斂 main.py
32ac9e40 CM-1677 ② fix(asset) 引用計數改查表分派,未知型別留 warning
306ef445 CM-1670 docs(FR-088) 驗收 H2——三條「只驗身分不驗歸屬」屬實
e9507d29 FR-088.1 docs H2 任務/留言/證明資安掃描報告
f66e52a5 CM-1676 SOP §3.4 補 logger 名要 common.jedi_
71040f4e CM-1676 SOP 把 jedi-asset 整理出的形狀寫進 extraction-sop
ad78cb49 CM-1676 spec 更正資訊系統頁 to_oscal_dict 錯述
d9d057e2 CM-1669~1675 docs(FR-088) jedi-flow-engine 資安掃描 arc 開卡

jedi monorepo(新→舊)

hash 卡號 一句話
dba46e0 CM-1686 ② refactor(iam) 拔 User 審計暱稱 association_proxy,只留 identity port
1668abb CM-1686 ① feat(iam) 開 identity port 讓補審計暱稱回套件
4cee35b CM-1681 test(system-core) 修回 FR-080 後變紅的 5 條
634763e CM-1681 test(bulletin) 修回 FR-080 第 5 棒後變紅
3d9772f CM-1678 補充三 fix(asset) system_status enum 值域統一小寫
02ec7bd CM-1679 註解收斂 四支 harness/dev_app.py
0b9dace CM-1678 feat(asset) information_systems 補 RLS 四條 policy+FORCE,devices.tenant_id NOT NULL
f9f6faf CM-1677 ⑤ refactor(jedi-asset) ctx() 定名 runtime()
c7659b0 CM-1679 註解收斂 detection/compliance-audit/flow-engine/evidence-classification/iam
08ea021 CM-1679 註解收斂 jedi-common
bc526f8 CM-1679 註解收斂 jedi-ai-dashboard
528603e CM-1679 註解收斂 jedi-survey
57d4833 CM-1679 註解收斂 jedi-issue
65b07ef CM-1679 註解收斂 jedi-remote-agent
0733454 CM-1677 ④ docs(jedi-asset) README 已知落差表補「啟用狀態的表達」
4b18e61 CM-1679 註解收斂 jedi-system-core
c9afe6f CM-1677 ③ test(jedi-asset) 補 service 行為整合測試——真 postgres 18 支
d1f4d52 CM-1679 註解收斂 jedi-log api_log/forwarding
7620b02 CM-1679 註解收斂 jedi-log plugin.py
39bfd5b CM-1679 註解收斂 jedi-task-platform task/project
bd9fc73 CM-1679 註解收斂 jedi-task-platform participant
319131d CM-1679 註解收斂 jedi-bulletin domain/infra/plugin
546d289 CM-1679 註解收斂 jedi-bulletin api/dto/service/error_code
73aa9f0 CM-1677 ① refactor(jedi-asset) 刪 InformationSystemService.upsert_by_name
731c4d7 CM-1676 jedi-asset logger 改掛 common.jedi_asset
72926b9 CM-1676 E jedi-asset 刪零呼叫者 OSCAL 序列化模組+error_code 搬出 enum 目錄
e27ae44 CM-1676 D jedi-asset 六個 entity 改 dataclass+修四個小問題
60b2ada CM-1676 C jedi-asset 統一設備/資訊系統兩套內部寫法
f0ab1f2 CM-1676 B jedi-asset plugin.py 拆四檔、api/init.py 拆兩檔
da091c2 CM-1676 A jedi-asset 清施工日誌型註解

1.3 Notion 卡狀態

這是 17 張卡用 scripts/notion_case.py get <id> --props-only 逐張查到的狀態,2026-09-12 18:45 查。

卡號 所屬 標題(截 40 字) 狀態
CM-1688 FR-089 母卡 FR-089 套件結構統一——用 jedi-asset 定一種標準形狀,先收主專案側殘留 Not started
CM-1676 FR-089 FR-089 jedi-asset 結構整理——當作 19 支套件的範例:清施工日誌註解 Done
CM-1677 FR-089 FR-089 jedi-asset 收尾修正——刪零呼叫者的 upsert_by_name、引用計數改明 Done
CM-1678 FR-089 FR-089 資訊系統表補 RLS+設備表 tenant_id 收緊——jedi-asset 002 migra Done
CM-1682 FR-090 母卡 FR-090 主專案側殘留收斂——套件上移後留在 app/ 的空殼、放錯層的 port Not started
CM-1683 FR-090 FR-090 第 1 棒 空殼清理——套件上移後留在 app/ 與 api/ 的 8 個空目錄 Done
CM-1684 FR-090 FR-090 第 2 棒 port 實作歸位——app/ 下五處實作 jedi 套件 port 的 adap Done
CM-1686 FR-090 FR-090 第 3 棒 iam 宿主側收斂——app/auth/ 六檔與 user_auth_provider Done
CM-1687 FR-090 FR-090 第 4 棒 補審計暱稱統一走 D8——common/util/audit_nickname.py Done
CM-1689 FR-090 FR-090 第 5 棒 接線收成一支一檔——core/plugins/.py 固定三段 Done
CM-1696 FR-090 FR-090 第 6 棒 主專案 DI container 瘦身——不再重複建套件 service Not started
CM-1690 FR-091 母卡 FR-091 18 支 jedi-* 套件套用 jedi-asset 定的標準形狀——三批各 5 支 Not started
CM-1691 FR-091 FR-091 第一批 jedi-ai-bot——照 jedi-asset 形狀整理:清註解、plugin.py Done
CM-1692 FR-091 FR-091 第一批 jedi-notification——照 jedi-asset 形狀整理:清註解 Done
CM-1693 FR-091 FR-091 第一批 jedi-integrity——照 jedi-asset 形狀整理:清註解 19 處 Done
CM-1694 FR-091 FR-091 第一批 jedi-remote-agent——照 jedi-asset 形狀整理:清註解 47 Done
CM-1695 FR-091 FR-091 第一批 jedi-ai-dashboard——照 jedi-asset 形狀整理:清註解 17 Done
CM-1697 FR-091 第二批 jedi-bulletin Done(第 2 棒驗收)
CM-1698 FR-091 第二批 jedi-file-upload Done(第 2 棒驗收;主專案 URL 守衛紅→1702)
CM-1699 FR-091 第二批 jedi-system-core Done(第 2 棒驗收)
CM-1700 FR-091 第二批 jedi-evidence-classification(含主專案側 G 組) Done(第 2 棒驗收)
CM-1701 FR-091 第二批 jedi-license-runtime(含主專案側 G 組) Done(第 2 棒驗收)
CM-1712 FR-091 第三批 jedi-issue Done(第 2 棒驗收)
CM-1713 FR-091 第三批 jedi-log Done(第 2 棒驗收)
CM-1714 FR-091 第三批 jedi-flow-engine Done(第 2 棒驗收)
CM-1715 FR-091 第三批 jedi-compliance-audit(identity port+G 組雙接線) Done(驗收棒 2026-09-13,十步全過;FR-048 403 路徑因 DEV 孤兒資料未複驗採信 runner)
CM-1725 FR-091 大卡 jedi-iam Done(第 3 棒驗收補三項:506 passed、404 AUTH_404005 實打)
CM-1726 FR-091 大卡 jedi-detection Done(第 3 棒驗收:105 passed 含 integration、三突變紅、拔掉 35→0 條)
CM-1727 FR-091 大卡 jedi-task-platform Done(第 3 棒驗收:139 passed、80 條 import、兩 harness smoke;task 接線與 compliance-audit 同形共用 blueprint)
CM-1716 FR-091 第三批 jedi-survey(暱稱收 D8+順收 evidence-classification 死引用) Done(第 2 棒驗收)
CM-1702 FR-091 收尾小卡:asset/bulletin PKG_ROOT、file-upload URL 守衛、三支 harness --smoke Done(第 2 棒驗收)
CM-1728 FR-091 能力點清單定形:jedi-asset contract.py 收 CAPABILITIES+jedi-common Capability 型別 Done(第 3 棒驗收)
CM-1729 FR-091 能力點回補四支+survey 守門走 port Done(第 3 棒驗收:comm 90/90 零回歸、403 GRC_403022 實打)
CM-1730 FR-091 主專案守衛:Plugin 帶 capabilities,五條測試對 seed Done(第 3 棒驗收:95 passed、四突變紅;127 筆四類零未歸類)
CM-1731 FR-091 jedi-integrity 版面歸位 Done(第 3 棒驗收:乾淨 worktree 109 passed、兩突變紅)
CM-1732 FR-091 file-upload/issue/notification 頂層 ports 併 domain、issue tests 搬根 Done(第 3 棒驗收)
CM-1733 FR-091 api/ 四件統一:license-runtime/remote-agent/log forwarding Done(第 3 棒驗收)
CM-1734 FR-091 能力點全套件普查與回補 Done(第 3 棒驗收:21 支 80 筆、對 seed 零缺、凍結集合雙向守)
CM-1735 FR-091 oscal-v2+common 收尾 Done(第 3 棒驗收:123/234 passed、兩突變紅)
CM-1736 FR-091 PM 白話說明頁+anatomy 補更新(純文件) Not started,可派

1.4 測試基線

這是三組測試在 BE .venv 下跑 pytest -q 的末行結果,2026-09-12 18:45 查。

測試 結果
jedi-asset tests/ 67 passed, 1 skipped, 12 warnings
jedi-iam tests/ 457 passed, 26 warnings
BE test/test_module_boundaries.py 90 passed(含帶 file-upload 工作樹;URL 守衛已改讀 FROZEN_URLS)
jedi-bulletin/file-upload/system-core tests/ 159/173/225 passed(各含 testcontainers 整合測試 18/14/21)

1.5 DEV DB 實況(唯讀)

這是 DEV guidant_ai_dev(188:25432,cmmgr)查 pg_class/pg_policies/pg_enum 的結果,2026-09-12 18:45 查。

RLS 開 FORCE policy 數
compliance.information_systems t t 4
public.devices t f 4
enum(schema compliance 值域
system_status_enum operational | under-development | disposition | under-major-modification | other
security_sensitivity_level_enum low | moderate | high

1.6 BE 服務

2026-09-13 晚:BE 以 python main.py 起在 8000,不需 PYTHONPATH(20 支 path dep 都指工作樹,只剩 oscal-v2 之外全 path)。/api/1.0/devices/menu 回 401 即活著。決策者正在 DEV 走一輪頁面測回歸(零行為變更的 arc,測「什麼都沒壞」)。

§2 已定裁示(不要重新討論)

裁示 何時
全部做法統一成 jedi-asset 形狀 2026-09-12
先做主專案側(FR-090)再做 18 支(FR-091) 2026-09-12
ctx() 改名 runtime(),19 支一起改 2026-09-12
identity port 只給 API 有吐 created_user_name 的套件(survey/detection/task-platform/compliance-audit/log;iam 已於 CM-1686 開)。第 2 棒實查修正:log 已有 IUserNameResolver port 不另開;survey 現有三條補名路徑收成 D8 一條(CM-1716) 2026-09-12/13
enum 值域統一小寫(A 案),已套 DEV(CM-1678) 2026-09-12
adapter 與填表同檔放 core/plugins/<pkg>.py,改判 CM-1684 的 infra/ 位置 2026-09-12
iam 兩支 wrapper 留原地瘦成純守門(A 案),不搬不改套件 route 2026-09-12
DI container 瘦身排 18 支之後(CM-1696),先問決策者定「主專案怎麼用套件」規則 2026-09-12
FR-080 發版/pin/SPEC/release note 移入 FR-089,等 18 支完一次做 2026-09-12
資安掃描不因結構整理重掃;報告行號以整理前 commit 為準 2026-09-12
能力點跟著套件走,21 支全列、形式一致(沒有的 CAPABILITIES = (),不只 route 有守門的):每支套件在 contract.py 列 CAPABILITIES(jedi-common Capability 型別,含 read 與 default_roles);survey/detection 寫死字串一律收成 config 形狀;config 不獨立成檔留 contract.py。守門判定仍由主專案 _host.pycommon.authz.require_capability,不動 2026-09-13
「init image 在 migrate 時讀套件清單自動補 capabilities row」是獨立大 arc,另開 FR,不在 FR-091(要處理 seed 檔 127 對寫死整數 role_capabilities、Administrator 初始持有集合、ui_routes)。FR-091 只做前置三卡 2026-09-13
SOP §4.3 api/ 四件:guards.py/routing.py/routes//serializers/,route 與 schema 不平鋪 api/ 頂層,子插件各自照長 2026-09-13
SOP §4.3 三條版面規則:頂層 jedi_<pkg>/ 只放 __init__.py+分層目錄;port 只放 domain/ports.py 不開頂層 ports/;tests 在套件根。驗收 SOP ③ 殘留掃描加這三項 2026-09-13
能力點歸屬四裁:report 不進套件清單;flow_template.* 歸主專案(判準=誰的 route 在守);主專案 39 筆要宣告但歸 FR-090 另開卡、1730 先豁免名單;疑廢 20 筆+DEV 殘留 7 筆照列不刪 2026-09-13
oscal-v2 做輕量版(ports 併 domain/logger 統一/entity 抽查),common 只清註解與 logger、不動結構;兩支不建 plugin。開 CM-1735 2026-09-13

§3 下一步

🔴 下一個動作(依序):

  1. 驗 CM-1736(決策者 2026-09-13 看過收 Done);CM-1737 已收。PM 頁 for-pm.md「三個零件裝法還是舊式」段要拿掉(純文件小改,首腦順手或併 arc-review 後的文件卡)。原 1 項:驗 CM-1736(PM 白話頁 for-pm.md+anatomy 重寫)。驗法:① 兩頁 grep CM-1|第 .* 棒|原本|收斂前|改判|後來|2026-09-12 出現即退回(決策者裁「文件只寫現況」);② PM 頁允許 plugin/主專案/接線/能力點/守衛測試五個詞且首次出現有括號白話,不得出現 adapter/port/DI/runtime/dataclass/contract/seed;③ 有「一支 plugin 裡面有什麼」五部分表;④ 數字對現況(21 支、25 卡、80 筆、core/plugins/ 17 檔);⑤ render_index.py 重 build 後 for-pm.html 側欄有、mermaid 沒壞。過了把 for-pm.md 全文貼給決策者轉 PM。
  2. arc review+修正卡 全收:CM-1738 報告(2C/6I/5M)+ 1739~1744 六張 Done。乾淨 worktree HEAD 守衛族 141 passed。未開卡留存:I-5 九處 import 改指+刪三支 ports/ 殼(1744 白名單標「I-5 收」,收完要拿掉白名單)、M-1~M-5、註解 58 條、四支既有紅測試(不掛 FR-089)、ProjectRoleGuardAdapter 兩份同名不同實作(infra/survey/adapters.py vs core/plugins/evidence_classification.py)。
  3. 決策者裁(拿 review 結果一起談):(a) FR-080 移來的發版推 Nexus/pin 還原/SPEC/release note——STG 測試的前提;(b) CM-1696 DI 瘦身規則「主專案哪些模組可直接用套件 domain service」;(c) FR-090 補卡:主專案自有 36 筆能力點申報處(三支接線那張已開 CM-1737,見 §4);(d) migrate FR:出貨 image 不撿套件 migration+能力點自動補 row+Administrator 初始權限(seed 檔 127 對寫死 role_capabilities 整數)。
  4. follow-up 要不要開卡:evidence-classification 3 條/ai-bot 1 條寫入 API 無 schema;issue tests/vcs_integration/ 21 紅(需外部服務);compliance-audit/task-platform 無 testcontainers 整合測試;FlowControlJobEntity 未 dataclass(參數名≠屬性名);report 能力點無點;task-setup/tree 500(raw SQL ap.uid 應為 uuid)。
  5. 順手:CLAUDE.md「DB 環境清單」DEV 列改 localhost(188 guidant_ai_dev 標退役快照)、docs/claude/sql-migration-conventions.md 與 3-way diff 腳本同步;「說明文件只寫現況」已進 CLAUDE.md 不用再補;驗收 SOP 措辭改「驗既有紅唯一方法=開 worktree 到開工前 commit」放最前(禁 stash 放尾巴擋不住,1727/1735 連兩張伸手)。
  6. FR-089/FR-091 母卡收 Done、SUMMARY——等決策者下令收尾。

驗收 SOP(第 3 棒定型,全程在該卡 commit 的 worktree 跑):⓪ git status 該卡目錄零 ??(1731 事故:commit -- 路徑 不納未追蹤新檔);① 讀回寫(重導到檔再讀);② git log 對卡;③ 殘留掃描(ctx()/施工日誌關鍵字/非 dataclass entity/logger 名/addopts/--smoke/PKG_ROOT/頂層平鋪/頂層 ports//套件內 tests//api 頂層只允許 init guards routing);④ 套件 pytest 全量在該卡 commit 的 worktree、PYTHONPATH 只指 worktree(HEAD 紅要歸因到後續哪張卡;runner 報「與 baseline 相同」必看 comm 輸出,沒貼就自己比);⑤ 版面守衛突變——突變前 git diff --stat 確認真的改到檔(BSD sed 0,/pat/s// 空替換、Nd 行號算錯都會假綠);⑥ harness --smoke;⑦ 主專案 boundaries+logger 守衛+fr048;⑧ AST 掃主專案 import 逐一 importlib;⑨ BE 重啟零新 Traceback、真實 URL 從套件 routing.py 抓、先看 GET/POST 與 FE payload;⑩ 有 G 組加拔掉測試。驗收是首腦本職,不外派(決策者 2026-09-13 裁)。

⚠️ 這節是建議清單,不是執行授權。接手方讀完盤點完即停,等 user 發令。

§4 待辦與風險

  • runner 側紀律缺口(本棒三張退回的共同根因):並行時 HEAD 不代表單卡成果;commit -- 路徑 漏未追蹤檔;「與 baseline 相同」靠記憶不靠 comm;驗既有紅伸手 git stash。派工 prompt 尾註要固定加:收工前全量在自己 commit 的 worktree 跑、git status??、對照用 comm 貼輸出、禁 stash 改 worktree。

  • 三 repo 領先 origin 未推:BE 自 56a15397 起(1737+review+六張修正+docs)、jedi 自 b077ed8 起(1741/1739/1742 三顆)、FE 6b7b0f2(1741 退路)。等令。

  • 發版前置:jedi-common 新 export fill_user_names,五支對 jedi-common 下限(asset≥0.0.34/iam≥0.0.23/survey≥0.0.33/compliance-audit≥0.0.33/bulletin≥0.0.34)發版時要提到含該函式那版,否則裝舊版直接 ImportError。

  • 守衛 test_converged_plugin_adapters_do_not_return_to_infra 會被 __pycache__ 假紅:它用 path.exists() 判舊目錄,舊樹上殘留的 pycache 目錄會讓它紅(首腦驗 1737 撞到)。改法:判目錄內有無 .py 檔,或 git ls-files。小卡候選。

  • 出貨 image 不撿套件 migration(CM-1678 runner 查證):scripts/init/ 與升級腳本只讀主專案 scripts/sql/ manifest,套件的 migrations/ 永遠套不到客戶端。enum bug 三環境+出貨基線都有。未開卡。

  • CM-1684 守衛盲點test_jedi_port_implementations_live_in_infra 只認繼承 jedi port ABC 的 class,duck typing 的 adapter 看不到。1689 改守衛時要一併擴。

  • 1687 幾處 _enrich_nicknames 之外的補暱稱app/flow_control/service/project_service.py:315(受評標的負責人)與 feedback_issue_dto.py 不是補審計暱稱,刻意不動,別誤收。

  • admin(tenant 1)建的資料在 blsadmin 視角暱稱回 None:RLS 範圍 /1/102/ 看不到 tenant 1,不是 bug。

  • 五支套件(asset/system-core/log/task-platform/bulletin)未發版:主專案走 path dependency(pyproject.toml:184 附近,不 commit),別台機器 clone 要先有 jedi 套件目錄。

  • 主專案 venv 四支(issue/file-upload/flow-engine/ai-bot)仍讀 Nexus wheel——首腦 2026-09-13 裁:派 CM-1730 前一律改 path dependency(不 commit),否則守衛在主專案讀不到清單會誤判。原文:多數套件是 Nexus wheel 不是工作樹(CM-1692 runner 抓到):pyproject.toml 只有 asset/iam 等少數走 path override,其餘是 pin。在主專案驗任何套件改動前先 python -c "import jedi_<pkg>;print(jedi_<pkg>.__file__)",指到 site-packages 就要 PYTHONPATH=<套件目錄> 重跑,否則假綠。已通知第一批其餘四張 runner。

  • 主專案 venv 的 site-packages 裝了 jedi-asset 的 tests/ 當頂層套件(path dependency 副作用):其他套件 from tests.xxx import 被遮蔽,預設模式 pytest collection error。用 pytest --import-mode=importlib,或下批卡要求各套件 pyproject.tomladdopts = "--import-mode=importlib"。整理前就存在。

  • 第一批三支 harness 沒有 --smoke(ai-bot/remote-agent/ai-dashboard 都是 app.run() 綁 port),首腦驗收時撞 port 撞了三次。第二批起卡上加「harness 補 --smoke(test client 不綁 port)」,並回頭給這三支開一張小卡補。

  • 三支接線(ai-bot/ai-dashboard/remote-agent)已收進 core/plugins/(CM-1737,0422c5d6):_CAPABILITY_PACKAGES_OUTSIDE_PLUGINS 清空、PLUGINS 20 支。留此行只為對照舊待辦。

  • 1689 範圍外仍有 infra/ adapterinfra/{license,remote_agent,survey,detection_tools,notification,upload_file}/ 各 1~4 檔沒搬,因為那些套件不在 PLUGINS 迴圈(走 REGISTERED_APPS 或另掛)。守衛 90 passed 表示它們不繼承 jedi ABC 或已白名單。FR-091 對應批次時順手收進 core/plugins/

  • core/plugins/ 是新目錄,Nuitka 打包白名單未驗(1689 runner 列出)。出包前必查 scripts/build/

  • 並行 runner 共用工作樹時裸 git commit 會吞別人 staged 的檔(首腦 ea34a17e 吞了 1689 的 22 檔;1692 也吞了 1693 的 14 檔)。首腦與 runner 一律 git commit -- <路徑>

  • 疆界守衛 PKG_ROOT 陷阱(CM-1699 runner 發現,第 2 棒實查)Path(<pkg>.plugin.__file__).parent 在 plugin 拆子套件後指到 plugin/,三支「不得 import 主專案」守衛只掃 5 檔仍全綠。asset/bulletin 已由 1702 修好(掃 58/42 檔,突變會紅);第三批起開卡固定寫「PKG_ROOT 從套件頂層模組取」

  • bulletin 整合測試只套 001 不套 002,RLS 未覆蓋(runner 當場講明,首腦收下)。system-core 那支有套 002 可當範本。

  • 第一批五支的 plugin.py 都能無痛拆五檔:已由 runner 回寫證實,推測撤銷。

§5 Pre-flight(必跑)

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git status -sb | head -3 && git log --oneline -5
cd ~/Projects/Jedicogy/module/jedi-python-package && git status -sb | head -3 && git log --oneline -5
# 待驗的卡
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
python3 scripts/notion_case.py get 3da346da4cd081a8af86d2a3bf50985c --props-only 2>&1 | grep -E "^Case No|^狀態"   # CM-1736
# 21 支全指工作樹+能力點可讀
source .venv/bin/activate && python -c "import importlib;print(sum(len(importlib.import_module(m).CAPABILITIES) for m in ['jedi_asset.plugin','jedi_iam.plugin','jedi_detection.plugin','jedi_survey.plugin']))"   # 42
# 守衛基線
python -m pytest test/test_module_boundaries.py test/test_jedi_package_logger_names.py -q 2>&1 | tail -1   # 100 passed
# BE 在不在
curl -s -o /dev/null -w "%{http_code}\n" localhost:8000/api/1.0/devices/menu   # 401 = 活著

憑證一律查 .env,不寫明文。

§6 環境座標

項目
BE repo ~/Projects/Billows/Audit-Manager/compliance-manager-be,branch feature/FR-075
jedi monorepo ~/Projects/Jedicogy/module/jedi-python-package,branch feature/FR-075;21 支套件各一目錄
範例套件 jedi-asset/(整支);harness DB 走 harness/docker-compose.yml port 5493
DEV DB 2026-09-13 起搬本機 localhost:5432 guidant_ai_dev(決策者裁,小弟 pg_dump 自 188 拉回;188:25432 那份退為快照不再是 DEV),帳號 cmmgr,密碼查 .env。接手先 psql -h localhost -p 5432 -U cmmgr -d guidant_ai_dev -c "select count(*) from schema_migrations" 確認搬完;沒搬完就仍是 188
BE 起法 kill -9 舊的再 python main.py(port 8000);log log/app.log
登入 POST /api/1.0/login body {"username":"blsadmin","password":<查 memory reference_dev_login>}欄位是 username 不是 login_name
Notion CLI python3 scripts/notion_case.py get/status/append;建卡 scripts/notion_create_case.py <spec.json>
STG/POC 本 arc 全程不碰(開發階段只動 DEV)

§7 行為規範提醒

  • 派工=開 Notion 卡,卡上帶母卡號;runner prompt 薄(母卡號+卡 URL+讀卡照做+branch+並行注意+commit 回寫不等令),並標建議 model。
  • 驗收不採信 runner 自報:自己跑測試、grep 殘留、重啟 BE 打端點。
  • 驗守門類功能前先查清楚定義(2026-09-12 首腦教訓:以為 blsadmin 是 root admin,實際受保護的是 tenant 1 的 admin,誤把測試帳號停用後手動復原)。
  • 檔案內註解只寫為什麼與陷阱;施工日誌進 commit message。
  • 不發版、不推 Nexus、不 push、不切 branch、不碰 STG/POC。
  • 中繼交接:STATE 就地 Edit、LOG append、在跑的子卡不動。
  • commit 一律 git commit -- <路徑>,共用工作樹有並行 runner 時裸 commit 會吞別人 staged 的檔(第 1 棒踩兩次)。
  • 驗收打端點前先看 route 是 GET 還是 POST:第 2 棒三條列表端點都是 POST 帶 RequestMetaSchema(pager/sort/filters),用 GET 打回 405 不是壞。上傳是 multipart 帶 json part。
  • 驗收要批次:三張卡的 pytest/突變/smoke/import 掃描一次跑完再看,不要一張一張。