For agentic workers: REQUIRED SUB-SKILL: 使用
superpowers:subagent-driven-development(推薦)或superpowers:executing-plans逐 task 執行。步驟用 checkbox (- [ ]) 追蹤。
Goal: 完成 Spec 3 Phase 6 review 揭露的 Tier 1 follow-up(PR1-4)+ M8 跨 repo 測試補強,作為 Spec 3 task arc 的真正收尾,全部完成後一次性 push + 部署 stg。
Architecture: 在 feature/project-flow-engine-integrate branch 上以 milestone-style commit 逐項 land;每個 Task = 1 commit(含 changelog)= 對應 follow-up tracker 的 1 個 PR。BE service 異動後必重啟。
Tech Stack: Python 3.11 / Flask-RESTful / SQLAlchemy / pytest(BE);Vue 3 + TS + PrimeVue(FE);Cucumber.js + Playwright(compliance-manager-test)
範圍對齊(user 已決策):
feature/project-flow-engine-integratedocs/features/FR-026-2605-project-flow-engine-integrate/03-ap-binding/phase6-followup-plan.mddocs/issues/pending/2026-05-13-spec3-phase-6-followups.mdCommit 規則:
git add <files>,禁用 -am / -A / .(memory rule feedback_subagent_explicit_git_add)Changelog 規則:
docs/changelog/2026-05-14-tweak-spec3-followup-prN-*.mdtype: tweak(refactor / test 補強 / housekeeping,都不算讓使用者能做新事情)modules: [project, grc] 或 [frontend]issue: docs/issues/pending/2026-05-13-spec3-phase-6-followups.mdcommit: <hash>測試規則:
PYTHONPATH=. pytest test/<file>.py -vfeedback_be_restart_after_service_change):
pkill -9 -f main_socketio.py && python main_socketio.py > /dev/null 2>&1 &Issue tracker 同步:
docs/issues/pending/2026-05-13-spec3-phase-6-followups.md 第四節「處理狀態追蹤」表格填入 commit hashgit mv pending/...md resolved/...md,並在 issue 開頭加 ## ⓪ Resolution 段驗證 follow-up tracker 跟現況一致,避免 plan-vs-reality drift。
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git status # 預期:clean,HEAD = b6f4eec
git log --oneline -3grep -n "def activate_project\|def confirm_audit\|def terminal_close_ap\|def launch_audit" \
app/project/service/oscal_audit_service.py預期:
activate_project:line 77launch_audit:line 169confirm_audit:line 329terminal_close_ap:line 425python -c "from jedi_project.common.code.status_code import ProjectStatus; print([s.name for s in ProjectStatus])"預期至少含:PENDING / IN_PROGRESS / COMPLETED / SUSPENDED / ARCHIVED
sed -n '149,163p' app/grc/service/oscal_stage_handlers.py預期:execute(self, ap_uid, project_uid, user_id, curr_user, ctx) 已有 user_id,但 call terminal_close_ap 沒傳 — PR1 只需把它接上即可。
sed -n '216,275p' app/project/service/oscal_audit_service.py預期:line 222 為 raise PreconditionFailedError(...),之後到 # ── 首次稽核模式 ──(約 line 273-274)為 dead code(含 return 在 line 270)。實際刪除範圍以 sed 結果為準,不照 tracker 寫的 "218-271"。
sed -n '745,760p' infra/grc/repository/grc_project_repo_impl.py預期:line 755-758 有 if ap_status_str == "closed": completion_rate = 100.0 else: ...。tracker 寫的 app/grc/repo/grc_project_repo_impl.py 是錯的,實際在 infra/。
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
git status # 預期:clean,HEAD = 695baad
git log --oneline -3sed -n '103,140p' src/views/project/ProjectApListView.vuecd ~/Projects/Billows/Audit-Manager/compliance-manager-test
git status; git log --oneline -3npm run test:regression 或對應指令(看 package.json scripts)_sync_project_status helper + terminal_close_ap 加權限檢查Priority: High(一次清掉 Pattern 1 + Pattern 2 + Silent #1/#3/#6)
Files:
app/project/service/oscal_audit_service.py
_sync_project_status(project_uid, target_status, curr_user, allowed_from)(約插入 line 75 上方)user_id: int 參數self._check_participant_role(project_uid, user_id, ["manager", "auditor"])app/grc/service/oscal_stage_handlers.py
terminal_close_ap 加 user_id=user_id(line ~158)test/test_oscal_audit_service.py(若不存在則新建)test/test_oscal_stage_handlers.py 更新既有 TerminalCloseHandler test新增 test/test_oscal_audit_service.py(若已存在則 append):
# test/test_oscal_audit_service.py
import pytest
from unittest.mock import MagicMock
from app.project.service.oscal_audit_service import OscalAuditService
from jedi_project.common.code.status_code import ProjectStatus
class TestSyncProjectStatus:
def _make_service(self, project_status):
service = OscalAuditService.__new__(OscalAuditService)
project = MagicMock(status=project_status, updated_user=None)
service._project_domain_service = MagicMock()
service._project_domain_service.get_one.return_value = project
service._project_domain_service.update = MagicMock()
return service, project
def test_allowed_transition_writes_target(self):
svc, project = self._make_service(ProjectStatus.PENDING)
svc._sync_project_status("uid", ProjectStatus.IN_PROGRESS, "u", {ProjectStatus.PENDING})
assert project.status == ProjectStatus.IN_PROGRESS
assert project.updated_user == "u"
svc._project_domain_service.update.assert_called_once()
def test_not_in_allowed_from_skips(self):
svc, project = self._make_service(ProjectStatus.SUSPENDED)
svc._sync_project_status("uid", ProjectStatus.COMPLETED, "u",
{ProjectStatus.PENDING, ProjectStatus.IN_PROGRESS})
assert project.status == ProjectStatus.SUSPENDED # 不變
svc._project_domain_service.update.assert_not_called()
def test_archived_project_protected(self):
svc, project = self._make_service(ProjectStatus.ARCHIVED)
svc._sync_project_status("uid", ProjectStatus.COMPLETED, "u",
{ProjectStatus.PENDING, ProjectStatus.IN_PROGRESS})
assert project.status == ProjectStatus.ARCHIVED
svc._project_domain_service.update.assert_not_called()
def test_project_not_found_returns_silently(self):
svc = OscalAuditService.__new__(OscalAuditService)
svc._project_domain_service = MagicMock()
svc._project_domain_service.get_one.return_value = None
svc._sync_project_status("uid", ProjectStatus.COMPLETED, "u",
{ProjectStatus.IN_PROGRESS})
svc._project_domain_service.update.assert_not_called()PYTHONPATH=. pytest test/test_oscal_audit_service.py::TestSyncProjectStatus -v預期:4 個全 FAIL(AttributeError: '_sync_project_status' not defined 或類似)
插入位置:app/project/service/oscal_audit_service.py 約 line 75(activate_project 之前):
def _sync_project_status(
self,
project_uid: str,
target_status, # ProjectStatus enum
curr_user: str,
allowed_from: set, # set[ProjectStatus]
) -> None:
"""Idempotent project.status transition.
只在 project.status ∈ allowed_from 時推進;否則 skip + warning log。
Caller 必須給 allowed_from 白名單 — 防止 SUSPENDED / ARCHIVED 被誤推到 COMPLETED
破壞 archive 語意(Phase 6 review Pattern 1)。
"""
from jedi_project.domain.entity.project.project_query_entity import ProjectQueryEntity
project = self._project_domain_service.get_one(ProjectQueryEntity(uid=project_uid))
if not project:
return
if project.status not in allowed_from:
logger.warning(
f"[sync_project_status] project={project_uid} status={project.status} "
f"not in allowed_from={allowed_from}, skip"
)
return
project.status = target_status
project.updated_user = curr_user
self._project_domain_service.update(project)注意:ProjectQueryEntity import path 用實際路徑(pre-flight 可先 grep 確認);logger 用模組頂部既有 logger。
PYTHONPATH=. pytest test/test_oscal_audit_service.py::TestSyncProjectStatus -v預期:4 個全 PASS。
# 原:
if project and project.status == ProjectStatus.PENDING:
project.status = ProjectStatus.IN_PROGRESS
self._project_domain_service.update(project)
# 改:
self._sync_project_status(
project_uid, ProjectStatus.IN_PROGRESS, curr_user,
allowed_from={ProjectStatus.PENDING},
)# 原:
if project and project.status == ProjectStatus.IN_PROGRESS:
project.status = ProjectStatus.COMPLETED
self._project_domain_service.update(project)
# 改:
self._sync_project_status(
project_uid, ProjectStatus.COMPLETED, curr_user,
allowed_from={ProjectStatus.IN_PROGRESS},
)# 原(黑名單,會誤推 SUSPENDED / ARCHIVED):
if project and project.status != ProjectStatus.COMPLETED:
project.status = ProjectStatus.COMPLETED
self._project_domain_service.update(project)
# 改(白名單):
self._sync_project_status(
project_uid, ProjectStatus.COMPLETED, curr_user,
allowed_from={ProjectStatus.PENDING, ProjectStatus.IN_PROGRESS},
)註:替換時,原 block 內可能含其他邏輯(如 fetch project entity 的 line),看 sed 結果決定要不要保留。若 project = self._project_domain_service.get_one(...) 只為了 state sync 用途,可一併刪除(helper 內部會自己 fetch)。
# line 425 簽章改:
def terminal_close_ap(
self,
project_uid: str,
ap_uid: str,
user_id: int, # ← 新增
curr_user: str,
) -> dict:
self._check_participant_role(project_uid, user_id, ["manager", "auditor"]) # ← 新增
# ...既有邏輯# app/grc/service/oscal_stage_handlers.py:158
return self._oscal_audit_service.terminal_close_ap(
project_uid=project_uid,
ap_uid=ap_uid,
user_id=user_id, # ← 新增
curr_user=curr_user,
)搜尋 TestTerminalCloseHandler,更新 terminal_close_ap mock assertion 加 user_id 參數,加一個 assert 確認 service 收到的 user_id 是來自 ctx 的值。
grep -n "TestTerminalCloseHandler\|terminal_close_ap.assert" test/test_oscal_stage_handlers.pyPYTHONPATH=. pytest test/test_oscal_audit_service.py test/test_oscal_stage_handlers.py -v預期:全部 PASS。
pkill -9 -f main_socketio.py && python main_socketio.py > /dev/null 2>&1 &
sleep 2 && tail -20 log/app.log預期:log 末段顯示 server started,無 traceback。
docs/changelog/2026-05-14-tweak-spec3-followup-pr1-sync-project-status-helper.md:
---
type: tweak
modules: [project, grc]
issue: docs/issues/pending/2026-05-13-spec3-phase-6-followups.md
---
# PR1:抽 `_sync_project_status` helper + terminal_close_ap 加權限檢查
## 為什麼
Spec 3 Phase 6 review 揭露 Pattern 1(state sync 3 處不一致:activate 白名單 / confirm 白名單 / terminal_close 黑名單)+ Pattern 2(terminal_close_ap 缺角色檢查)。黑名單會強推 SUSPENDED/ARCHIVED → COMPLETED 破壞 archive 語意。
## 變更範圍
- `app/project/service/oscal_audit_service.py`:新增 `_sync_project_status` helper + 替換 3 處 call site + terminal_close_ap 加 `user_id` 參數 + `_check_participant_role`
- `app/grc/service/oscal_stage_handlers.py`:TerminalCloseHandler.execute 傳 user_id 給 service
- `test/test_oscal_audit_service.py`(新增):4 個 helper test
- `test/test_oscal_stage_handlers.py`:更新既有 TerminalCloseHandler test
## 行為差異
- SUSPENDED / ARCHIVED project:terminal_close_ap 不再強推 COMPLETED,改 skip + warning log
- terminal_close_ap:外部 caller 必須帶 user_id + 是 manager / auditor 才能呼叫(API 路由 / handler 已配對)
## 測試結果
`pytest test/test_oscal_audit_service.py test/test_oscal_stage_handlers.py -v` 全 PASS。
## 參考
- Phase 6 review master:`docs/review/2026-05-13-spec3-review.md` Pattern 1 + 2
- Silent failure:`docs/review/2026-05-13-spec3-review-silent-failures.md` #1 / #3 / #6git add app/project/service/oscal_audit_service.py \
app/grc/service/oscal_stage_handlers.py \
test/test_oscal_audit_service.py \
test/test_oscal_stage_handlers.py \
docs/changelog/2026-05-14-tweak-spec3-followup-pr1-sync-project-status-helper.md
git commit -m "$(cat <<'EOF'
tweak(spec3 followup PR1): _sync_project_status helper + terminal_close_ap 加權限檢查
- 抽 _sync_project_status(project_uid, target_status, curr_user, allowed_from) 統一 3 處 state sync
- terminal_close_ap 從黑名單 (!= COMPLETED) 改白名單 ({PENDING, IN_PROGRESS}) — 修 Pattern 1
- terminal_close_ap 加 user_id 參數 + _check_participant_role — 修 Pattern 2 + Silent #6
- TerminalCloseHandler.execute 把 ctx.user_id 傳給 service
Refs: docs/review/2026-05-13-spec3-review.md (Pattern 1+2, Silent #1/#3/#6)
EOF
)"在 docs/issues/pending/2026-05-13-spec3-phase-6-followups.md 第四節「處理狀態追蹤」PR1 row 填入 commit hash。
git log -1 --format=%h
# 把 hash 填進 tracker,再 commit tracker 變更注意:tracker 更新可以累積,最後一個 Task 完成時一起 commit;不需要每個 PR 都 commit tracker。
Priority: Medium(housekeeping)
Files:
app/project/service/oscal_audit_service.py(刪 line 222 之後到 line ~273 之前的 unreachable block)grep -n "raise PreconditionFailedError(GrcErrorCode.GRC_AP_REVIEW_VIA_CLOSE_ROUND)\|# ── 首次稽核模式 ──" \
app/project/service/oscal_audit_service.py記下 raise 行(保留)跟 # ── 首次稽核模式 ── 行(保留)。中間都刪。
原 block 約 50 行(從 # ── 以下覆核模式邏輯已停用(保留 reference)... 開始,到 return {"warning": False, "ap_uid": ap_uid, "status": "auditing", "run_no": new_run_no} 結束,共 ~50 行)。
保留 raise PreconditionFailedError(...) 那行 + 改其上方 comment 為:
if is_review_mode:
# Spec 2(2026-05-13 review fix H1 + Spec 3 Phase 6 PR2 cleanup):
# 「發起覆核」副作用已搬到 close_round handler(Banner「完成改善」推進路徑)。
# 此分支保留純粹防 dup — 外部 curl / legacy code 若在 remediation 狀態
# 觸發 launch_audit 會建出第二份 run_no=N+1 ar_data,所以直接 raise 防 data corruption。
# 對應覆核流程實作見 `oscal_audit_service.close_round()` (line ~427)。
raise PreconditionFailedError(GrcErrorCode.GRC_AP_REVIEW_VIA_CLOSE_ROUND)PYTHONPATH=. pytest test/ -v -k "launch_audit or LaunchAudit"pkill -9 -f main_socketio.py && python main_socketio.py > /dev/null 2>&1 &docs/changelog/2026-05-14-tweak-spec3-followup-pr2-launch-audit-dead-code.md
git add app/project/service/oscal_audit_service.py \
docs/changelog/2026-05-14-tweak-spec3-followup-pr2-launch-audit-dead-code.md
git commit -m "$(cat <<'EOF'
tweak(spec3 followup PR2): 刪 launch_audit is_review_mode unreachable block
Line 222 的 raise 之後是 dead code (Spec 2 H1 fix 後 close_round handler 接手覆核)。
保留 raise 防 legacy curl / external caller dup,但 unreachable 邏輯刪 ~50 行。
Refs: docs/review/2026-05-13-spec3-review-be-code.md #2
EOF
)"Priority: Medium(hotfix b979a71 暴露 import smoke 不夠)
Strategy:tracker 寫 4 個 case 都是 Python if ap_status_str == "closed" 那段,邏輯非常單純(3 行)— 採「extract pure helper + unit test」比 mock session.query 乾淨太多。
Files:
infra/grc/repository/grc_project_repo_impl.py(line 755-758 區域,抽出 _compute_completion_rate static method)test/test_grc_project_repo.py(新建,純 Python unit test)# test/test_grc_project_repo.py
import pytest
from infra.grc.repository.grc_project_repo_impl import GrcProjectRepoImpl
class TestComputeCompletionRate:
@pytest.mark.parametrize("ap_status, completed, total, expected", [
("closed", 0, 0, 100.0),
("closed", 2, 2, 100.0),
("closed", 0, 10, 100.0),
("open", 0, 0, 0.0),
("open", 1, 2, 50.0),
("open", 3, 10, 30.0),
("open", None, 5, 0.0), # defensive:completed_tasks 為 None
(None, 1, 2, 50.0), # ap_status_str 為 None
])
def test_compute(self, ap_status, completed, total, expected):
result = GrcProjectRepoImpl._compute_completion_rate(ap_status, completed, total)
assert result == expectedPYTHONPATH=. pytest test/test_grc_project_repo.py -v預期:FAIL(_compute_completion_rate 不存在)
@staticmethod
def _compute_completion_rate(ap_status_str, completed_tasks, total_tasks) -> float:
"""AP 已 closed 視為 100% 完成;否則回 completed/total 比例 (四捨五入 1 位)。
total_tasks=0 且未 closed 回 0.0(不除以零)。"""
if ap_status_str == "closed":
return 100.0
if not total_tasks:
return 0.0
return round((completed_tasks or 0) * 100 / total_tasks, 1)# 原:
if ap_status_str == "closed":
completion_rate = 100.0
else:
completion_rate = round(completed_tasks * 100 / total_tasks, 1) if total_tasks > 0 else 0.0
# 改:
completion_rate = self._compute_completion_rate(ap_status_str, completed_tasks, total_tasks)PYTHONPATH=. pytest test/test_grc_project_repo.py -v預期:8 個 case 全 PASS。
pkill -9 -f main_socketio.py && python main_socketio.py > /dev/null 2>&1 &docs/changelog/2026-05-14-tweak-spec3-followup-pr3-completion-rate-unit-test.md
git add infra/grc/repository/grc_project_repo_impl.py \
test/test_grc_project_repo.py \
docs/changelog/2026-05-14-tweak-spec3-followup-pr3-completion-rate-unit-test.md
git commit -m "$(cat <<'EOF'
tweak(spec3 followup PR3): M12 completion_rate 抽 helper + 補 unit test
M12 hotfix b979a71 (String 漏 import) 暴露 import smoke 對 method-body unresolved
name 不敏感的弱點 — 補純 Python helper + unit test 把 compute path 釘住。
Refs: docs/review/2026-05-13-spec3-review-be-code.md #1
EOF
)"Priority: Medium(UX 問題 — master 軟刪時 inherited hint 仍顯示 + 預設值失效)
工作目錄切換:cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
Files:
src/views/project/ProjectApListView.vue(line 111 defaultFlowTemplateUid computed 加 guard + line 480-484 inherited hint 同步)實際現況(pre-flight 驗證後修正):computed 來源是 apList.value?.[0]?.flow_template?.master_uid,不是 masterUid.value。
// 原(line 111-115):
const defaultFlowTemplateUid = computed<string | null>(() => {
const latest = apList.value?.[0]
return latest?.flow_template?.master_uid ?? null
})
// 改:
const defaultFlowTemplateUid = computed<string | null>(() => {
const latest = apList.value?.[0]
const uid = latest?.flow_template?.master_uid
if (!uid) return null
// master 軟刪 / 不在 active flowTemplates list 內 → 不當 default
const found = flowTemplates.value.find((t: any) => t.uid === uid)
if (!found) return null
// 若 BE 有 is_master_active 旗標再多防一層(沒回則 found 為準)
if (found.is_master_active === false) return null
return uid
})驗證:subagent 開工前先
sed -n '108,135p' src/views/project/ProjectApListView.vue確認現況;若已被 user 動過則對齊實際內容。
src/views/project/ProjectApListView.vue line 480-484:
<!-- 原 -->
<small v-if="defaultFlowTemplateUid && dialogForm.flowTemplateUid === defaultFlowTemplateUid">
{{ t('lang.project_ap_list.flow_template_inherited_hint') }}
</small>
這個條件本身已經 OK — 因為 defaultFlowTemplateUid 為 null 時 hint 自然不顯示。無需再改,但要驗證行為(軟刪後 hint 該消失)。
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
npm run dev # 看 package.json scripts 確認 command在 dev DB 找一個 project 的 master flow_template,UPDATE 設 is_active=FALSE,FE 重整 ProjectApListView,預期:
註:UI 驗證為主,無需寫 E2E 測試(FE 沒有對應 unit test 框架慣例給 computed)。
docs/changelog/2026-05-14-tweak-spec3-followup-pr4-default-flow-template-guard.md(路徑:FE repo 的 docs/changelog/)
git add src/views/project/ProjectApListView.vue \
docs/changelog/2026-05-14-tweak-spec3-followup-pr4-default-flow-template-guard.md
git commit -m "$(cat <<'EOF'
tweak(spec3 followup PR4): defaultFlowTemplateUid 加 master 軟刪 guard
master_uid 不在 flowTemplates list 內 / is_master_active=false 時,預設值改 null。
inherited hint 因條件已含 defaultFlowTemplateUid && === 對齊,自然不再顯示。
Refs: docs/review/2026-05-13-spec3-review-fe-code.md #1
EOF
)"工作目錄切換:cd ~/Projects/Billows/Audit-Manager/compliance-manager-test
Strategy:先看 test repo 的 CLAUDE.md / handoff 索引找出實際待修 4 fixture + 3 scenario 的清單;然後逐項修補 + 跑 cucumber 驗證。
Spec 3 plan / test-plan 應該記了 M8 細項:
grep -n "M8\|fixture.*bug\|Banner.*BDD\|3.*scenario" \
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-026-2605-project-flow-engine-integrate/03-ap-binding/{test-plan.md,implementation-plan.md,design.md} \
2>/dev/null | head -30cd ~/Projects/Billows/Audit-Manager/compliance-manager-test
cat package.json | grep -A 5 '"scripts"' # 找 cucumber 跑法npm run test:<scenario> 或對應 cucumber tag 命令確認該 scenario 過features/ 加 .feature 檔steps/ 補 step 實作pages/ 加 page objecttest repo 有自己的 changelog 慣例,看 docs/changelog/ 既有 file 模仿。
git add features/... steps/... pages/... fixtures/... docs/changelog/...
git commit -m "tweak(spec3 followup M8): 修 4 fixture bug + 補 3 Banner BDD scenario"注意:test repo 是否要跟 BE/FE 同步 push 取決於 user 部署慣例。M8 完成後本計劃的「需求收尾」即告達成。
工作目錄切回:cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
docs/issues/pending/2026-05-13-spec3-phase-6-followups.md 開頭插入:
## ⓪ Resolution
| 項目 | 內容 |
|------|------|
| 修復日期 | 2026-05-14 |
| Commits | PR1 `<hash>` / PR2 `<hash>` / PR3 `<hash>` / PR4 `<hash>` (FE repo) / M8 `<hash>` (test repo) |
| Changelog | docs/changelog/2026-05-14-tweak-spec3-followup-pr1~pr4-*.md |
| Follow-up | PR5-8 + PR-TD1/2/3 留 backlog(Low priority);Stage plugin 架構依需求觸發 |git mv docs/issues/pending/2026-05-13-spec3-phase-6-followups.md \
docs/issues/resolved/2026-05-13-spec3-phase-6-followups.mdgrep -l "issues/pending/2026-05-13-spec3-phase-6-followups" docs/changelog/2026-05-14-tweak-spec3-followup-*.md \
| xargs sed -i '' 's|issues/pending/2026-05-13-spec3-phase-6-followups|issues/resolved/2026-05-13-spec3-phase-6-followups|g'git log --oneline -10 # 找出 PR1-4 commit hash
# 編輯 4 個 changelog 的 frontmatter,加 `commit: <hash>`git add docs/issues/resolved/2026-05-13-spec3-phase-6-followups.md \
docs/changelog/2026-05-14-tweak-spec3-followup-*.md
git commit -m "docs(spec3 followup): issue tracker 歸檔 resolved + changelog 補 commit hash"follow-up 是接續 Spec 3 task arc,但屬獨立 milestone — 建議建新資料夾:
mkdir -p docs/conversation-history/2026-05-14-spec3-phase6-followup解析逐輪 Q&A → 拆 part-NN-of-NN-* 檔(每個 PR 或每個 Task 一份):
part-01-of-06-pre-flight-and-pr1.mdpart-02-of-06-pr2-dead-code.mdpart-03-of-06-pr3-completion-rate-test.mdpart-04-of-06-pr4-fe-guard.mdpart-05-of-06-m8-test-repo.mdpart-06-of-06-wrap-up.mdSUMMARY.md格式參考 docs/conversation-history/README.md。
注意:整個
docs/conversation-history/在.gitignore內,不入版控。但仍必做(per CLAUDE.md「『做 summary』指令的含義」)。
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git status
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe && git status
cd ~/Projects/Billows/Audit-Manager/compliance-manager-test && git statuscd ~/Projects/Billows/Audit-Manager/compliance-manager-be && git log --oneline origin/feature/project-flow-engine-integrate..HEAD
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe && git log --oneline origin/feature/project-flow-engine-integrate..HEAD
cd ~/Projects/Billows/Audit-Manager/compliance-manager-test && git log --oneline origin/main..HEAD # test repo branch 視當下而定# BE
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be && \
git push origin feature/project-flow-engine-integrate
# FE
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe && \
git push origin feature/project-flow-engine-integrate
# test
cd ~/Projects/Billows/Audit-Manager/compliance-manager-test && \
git push origin <branch>⚠️ Push 屬「risky action」(CLAUDE.md「Executing actions with care」)— 計劃停在 Step 8 後,待 user 明確 say push 才執行。
由 user 主導部署流程(依專案 CI/CD 慣例)。
存 docs/conversation-history/2026-05-14-spec3-phase6-followup/SUMMARY.md(gitignored):
_check_participant_role 對 confirm_audit / activate_project 已含 _check(被 helper 影響),需要 case-by-case 看。terminal_close_ap 全 codebase 應只 1-2 hit(service + handler + test)。_sync_project_status import path — ProjectQueryEntity 在 jedi-project 套件內,pre-flight 要先確認 import path 正確。若 jedi-project 套件版本不對齊,會 ImportError。GrcProjectRepoImpl._compute_completion_rate 用 @staticmethod 不依賴 self.session,避開 RLS / session_scope 問題(純 Python helper)。| Tracker / Plan 初版 | 實際 | 修正位置 |
|---|---|---|
app/grc/repo/grc_project_repo_impl.py:746-758 |
infra/grc/repository/grc_project_repo_impl.py:755-758 |
PR3 路徑 |
| terminal_close_ap signature 有 user_id | 沒有 user_id(簽章 (self, project_uid, ap_uid, curr_user)) |
PR1 加參數而非「補上呼叫」 |
| TerminalCloseHandler.execute 沒 user_id | 已有 user_id(line 153)— 只是沒傳給 service | PR1 只需把它接到 service call |
| dead code line 218-271 | line 220 raise → line 270 結束(共 50 行) | PR2 用 grep # ── 首次稽核模式 ── 找實際邊界 |
PR4 假設 defaultFlowTemplateUid 來源是 masterUid.value |
實際是 apList.value?.[0]?.flow_template?.master_uid |
PR4 Step 1(已修正 v1.1) |
| test repo 預期在 main branch | user 已於 pre-flight 後切到 feature/project-flow-engine-integrate |
M8 開工 cd 後再次 git status 確認即可 |
| 版本 | 日期 | 變更 |
|---|---|---|
| v1 | 2026-05-14 | 初版(Tier 1 PR1-4 + M8 收尾) |
| v1.1 | 2026-05-14 | pre-flight 後修正:PR4 defaultFlowTemplateUid 來源改為 apList[0].flow_template.master_uid;Plan vs Reality 表加第 5/6 條 |