diff --git a/apps/api/src/services/ai_agent_result_capture_release_decision_hold.py b/apps/api/src/services/ai_agent_result_capture_release_decision_hold.py
index 4ef57e97f..68fb51718 100644
--- a/apps/api/src/services/ai_agent_result_capture_release_decision_hold.py
+++ b/apps/api/src/services/ai_agent_result_capture_release_decision_hold.py
@@ -48,6 +48,7 @@ def load_latest_ai_agent_result_capture_release_decision_hold(
_require_owner_decision_holds(payload, label)
_require_verifier_decision_holds(payload, label)
_require_rollback_decision_holds(payload, label)
+ _require_maintenance_window_decision_holds(payload, label)
_require_live_apply_decision_holds(payload, label)
_require_blocked_transitions(payload, label)
_require_actions(payload, label)
@@ -219,6 +220,22 @@ def _require_rollback_decision_holds(payload: dict[str, Any], label: str) -> Non
_require_valid_status(item, label, f"rollback decision hold {item_id}")
+def _require_maintenance_window_decision_holds(payload: dict[str, Any], label: str) -> None:
+ items = payload.get("maintenance_window_decision_holds") or []
+ _require_ids(items, "hold_id", _expected_ids("maintenance_window_decision_hold"), label, "maintenance window decision holds")
+ for item in items:
+ item_id = item.get("hold_id")
+ if item.get("hold_mode") != "maintenance_window_decision_hold":
+ raise ValueError(f"{label}: maintenance window decision hold {item_id} mode is invalid")
+ if item.get("maintenance_window_required") is not True:
+ raise ValueError(f"{label}: maintenance window decision hold {item_id} must require maintenance window")
+ if item.get("maintenance_window_approved") is not False or item.get("live_apply_release_passed") is not False:
+ raise ValueError(f"{label}: maintenance window decision hold {item_id} must stay unapproved and unpassed")
+ _require_valid_status(item, label, f"maintenance window decision hold {item_id}")
+ if not item.get("maintenance_summary"):
+ raise ValueError(f"{label}: maintenance window decision hold {item_id}.maintenance_summary is required")
+
+
def _require_live_apply_decision_holds(payload: dict[str, Any], label: str) -> None:
items = payload.get("live_apply_decision_holds") or []
_require_ids(items, "hold_id", _expected_ids("live_apply_decision_hold"), label, "live apply decision holds")
@@ -286,6 +303,7 @@ def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None:
"owner_decision_hold_count": len(payload.get("owner_decision_holds") or []),
"verifier_decision_hold_count": len(payload.get("verifier_decision_holds") or []),
"rollback_decision_hold_count": len(payload.get("rollback_decision_holds") or []),
+ "maintenance_window_decision_hold_count": len(payload.get("maintenance_window_decision_holds") or []),
"live_apply_decision_hold_count": len(payload.get("live_apply_decision_holds") or []),
"blocked_decision_transition_count": len(payload.get("blocked_decision_transitions") or []),
"operator_action_count": len(payload.get("operator_actions") or []),
diff --git a/apps/api/tests/test_ai_agent_result_capture_release_decision_hold.py b/apps/api/tests/test_ai_agent_result_capture_release_decision_hold.py
index 4aa89a369..cd40154e6 100644
--- a/apps/api/tests/test_ai_agent_result_capture_release_decision_hold.py
+++ b/apps/api/tests/test_ai_agent_result_capture_release_decision_hold.py
@@ -25,6 +25,7 @@ def test_load_latest_release_decision_hold_snapshot() -> None:
assert rollups["owner_decision_hold_count"] == 5
assert rollups["verifier_decision_hold_count"] == 5
assert rollups["rollback_decision_hold_count"] == 5
+ assert rollups["maintenance_window_decision_hold_count"] == 5
assert rollups["live_apply_decision_hold_count"] == 5
assert rollups["blocked_decision_transition_count"] == 6
assert rollups["operator_action_count"] == 5
@@ -33,21 +34,24 @@ def test_load_latest_release_decision_hold_snapshot() -> None:
+ rollups["approval_required_owner_decision_count"]
+ rollups["approval_required_verifier_decision_count"]
+ rollups["approval_required_rollback_decision_count"]
+ + rollups["approval_required_maintenance_window_decision_count"]
+ rollups["approval_required_live_apply_decision_count"]
- ) == 10
+ ) == 12
assert (
rollups["blocked_release_decision_count"]
+ rollups["blocked_owner_decision_count"]
+ rollups["blocked_verifier_decision_count"]
+ rollups["blocked_rollback_decision_count"]
+ + rollups["blocked_maintenance_window_decision_count"]
+ rollups["blocked_live_apply_decision_count"]
+ rollups["critical_blocker_count"]
- ) == 10
+ ) == 12
assert rollups["owner_release_authorized_count"] == 0
assert rollups["owner_review_approved_count"] == 0
assert rollups["owner_decision_approved_count"] == 0
assert rollups["verifier_decision_approved_count"] == 0
+ assert rollups["maintenance_window_approved_count"] == 0
assert rollups["release_decision_pass_count"] == 0
assert rollups["release_authorization_granted_count"] == 0
assert rollups["release_authorization_pass_count"] == 0
@@ -71,6 +75,7 @@ def test_release_decision_hold_truth_keeps_all_live_paths_closed() -> None:
assert truth["p2_137_owner_review_packet_loaded"] is True
assert truth["release_decision_hold_ready"] is True
assert truth["owner_decision_required"] is True
+ assert truth["maintenance_window_decision_required"] is True
assert truth["owner_release_authorized"] is False
assert truth["owner_review_approved"] is False
assert truth["owner_decision_approved"] is False
@@ -106,6 +111,15 @@ def test_rejects_owner_decision_approved(tmp_path: Path) -> None:
load_latest_ai_agent_result_capture_release_decision_hold(tmp_path)
+def test_rejects_maintenance_window_approved(tmp_path: Path) -> None:
+ snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_decision_hold())
+ snapshot["maintenance_window_decision_holds"][0]["maintenance_window_approved"] = True
+ _write_snapshot(tmp_path, snapshot)
+
+ with pytest.raises(ValueError, match="must stay unapproved and unpassed"):
+ load_latest_ai_agent_result_capture_release_decision_hold(tmp_path)
+
+
def test_rejects_queue_write_drift(tmp_path: Path) -> None:
snapshot = copy.deepcopy(load_latest_ai_agent_result_capture_release_decision_hold())
snapshot["rollups"]["gateway_queue_write_count"] = 1
diff --git a/apps/api/tests/test_ai_agent_result_capture_release_decision_hold_api.py b/apps/api/tests/test_ai_agent_result_capture_release_decision_hold_api.py
index 714fa50e2..b8dbcb30e 100644
--- a/apps/api/tests/test_ai_agent_result_capture_release_decision_hold_api.py
+++ b/apps/api/tests/test_ai_agent_result_capture_release_decision_hold_api.py
@@ -21,12 +21,14 @@ def test_release_decision_hold_endpoint() -> None:
assert payload["rollups"]["owner_decision_hold_count"] == 5
assert payload["rollups"]["verifier_decision_hold_count"] == 5
assert payload["rollups"]["rollback_decision_hold_count"] == 5
+ assert payload["rollups"]["maintenance_window_decision_hold_count"] == 5
assert payload["rollups"]["live_apply_decision_hold_count"] == 5
assert payload["rollups"]["blocked_decision_transition_count"] == 6
assert payload["rollups"]["operator_action_count"] == 5
assert payload["rollups"]["owner_release_authorized_count"] == 0
assert payload["rollups"]["owner_review_approved_count"] == 0
assert payload["rollups"]["owner_decision_approved_count"] == 0
+ assert payload["rollups"]["maintenance_window_approved_count"] == 0
assert payload["rollups"]["release_decision_pass_count"] == 0
assert payload["rollups"]["release_authorization_granted_count"] == 0
assert payload["rollups"]["release_authorization_pass_count"] == 0
diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json
index 9ce74b767..29fac91fa 100644
--- a/apps/web/messages/en.json
+++ b/apps/web/messages/en.json
@@ -6154,6 +6154,7 @@
"ownerHolds": "負責人決策保留",
"verifierHolds": "驗證器決策保留",
"rollbackHolds": "回滾決策保留",
+ "maintenanceHolds": "維護窗口決策保留",
"liveApplyHolds": "正式套用保留",
"blockers": "已阻擋轉換",
"actions": "操作選項",
@@ -6164,6 +6165,7 @@
"flags": {
"p2Loaded": "已載入 P2-137={value}",
"decisionHoldReady": "釋出決策保留已就緒={value}",
+ "maintenanceDecisionRequired": "維護窗口決策必要={value}",
"liveApplyDecisionRequired": "正式套用決策必要={value}"
},
"labels": {
@@ -6173,6 +6175,9 @@
"authorizationGranted": "釋出授權已核發={value}",
"decisionPassed": "釋出決策通過={value}",
"authorizationPassed": "釋出授權通過={value}",
+ "maintenanceRequired": "維護窗口必要={value}",
+ "maintenanceApproved": "維護窗口已批准={value}",
+ "liveApplyPassed": "正式套用通過={value}",
"gatewayWrites": "Gateway 寫入={value}",
"runtimeWriteAllowed": "runtime 寫入允許={value}"
}
diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json
index 9ce74b767..29fac91fa 100644
--- a/apps/web/messages/zh-TW.json
+++ b/apps/web/messages/zh-TW.json
@@ -6154,6 +6154,7 @@
"ownerHolds": "負責人決策保留",
"verifierHolds": "驗證器決策保留",
"rollbackHolds": "回滾決策保留",
+ "maintenanceHolds": "維護窗口決策保留",
"liveApplyHolds": "正式套用保留",
"blockers": "已阻擋轉換",
"actions": "操作選項",
@@ -6164,6 +6165,7 @@
"flags": {
"p2Loaded": "已載入 P2-137={value}",
"decisionHoldReady": "釋出決策保留已就緒={value}",
+ "maintenanceDecisionRequired": "維護窗口決策必要={value}",
"liveApplyDecisionRequired": "正式套用決策必要={value}"
},
"labels": {
@@ -6173,6 +6175,9 @@
"authorizationGranted": "釋出授權已核發={value}",
"decisionPassed": "釋出決策通過={value}",
"authorizationPassed": "釋出授權通過={value}",
+ "maintenanceRequired": "維護窗口必要={value}",
+ "maintenanceApproved": "維護窗口已批准={value}",
+ "liveApplyPassed": "正式套用通過={value}",
"gatewayWrites": "Gateway 寫入={value}",
"runtimeWriteAllowed": "runtime 寫入允許={value}"
}
diff --git a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx
index ea25c17ff..105fa09c8 100644
--- a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx
+++ b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx
@@ -15,6 +15,7 @@ import {
BellOff,
BellRing,
Boxes,
+ CalendarClock,
Database,
FileText,
GitBranch,
@@ -3317,6 +3318,7 @@ export function AutomationInventoryTab() {
const resultCaptureReleaseOwnerDecisionHolds = resultCaptureReleaseDecisionHold.rollups.owner_decision_hold_count
const resultCaptureReleaseVerifierDecisionHolds = resultCaptureReleaseDecisionHold.rollups.verifier_decision_hold_count
const resultCaptureReleaseRollbackDecisionHolds = resultCaptureReleaseDecisionHold.rollups.rollback_decision_hold_count
+ const resultCaptureReleaseMaintenanceDecisionHolds = resultCaptureReleaseDecisionHold.rollups.maintenance_window_decision_hold_count
const resultCaptureReleaseLiveApplyDecisionHolds = resultCaptureReleaseDecisionHold.rollups.live_apply_decision_hold_count
const resultCaptureReleaseDecisionBlockedTransitions = resultCaptureReleaseDecisionHold.rollups.blocked_decision_transition_count
const resultCaptureReleaseDecisionActions = resultCaptureReleaseDecisionHold.rollups.operator_action_count
@@ -3325,6 +3327,7 @@ export function AutomationInventoryTab() {
+ resultCaptureReleaseDecisionHold.rollups.approval_required_owner_decision_count
+ resultCaptureReleaseDecisionHold.rollups.approval_required_verifier_decision_count
+ resultCaptureReleaseDecisionHold.rollups.approval_required_rollback_decision_count
+ + resultCaptureReleaseDecisionHold.rollups.approval_required_maintenance_window_decision_count
+ resultCaptureReleaseDecisionHold.rollups.approval_required_live_apply_decision_count
)
const resultCaptureReleaseDecisionBlocked = (
@@ -3332,6 +3335,7 @@ export function AutomationInventoryTab() {
+ resultCaptureReleaseDecisionHold.rollups.blocked_owner_decision_count
+ resultCaptureReleaseDecisionHold.rollups.blocked_verifier_decision_count
+ resultCaptureReleaseDecisionHold.rollups.blocked_rollback_decision_count
+ + resultCaptureReleaseDecisionHold.rollups.blocked_maintenance_window_decision_count
+ resultCaptureReleaseDecisionHold.rollups.blocked_live_apply_decision_count
+ resultCaptureReleaseDecisionHold.rollups.critical_blocker_count
)
@@ -7933,6 +7937,7 @@ export function AutomationInventoryTab() {
} />
} />
} />
+ } />
} />
} />
} />
@@ -7962,6 +7967,7 @@ export function AutomationInventoryTab() {
+
@@ -8015,6 +8021,29 @@ export function AutomationInventoryTab() {
))}
+
+ {resultCaptureReleaseDecisionHold.maintenance_window_decision_holds.slice(0, 5).map(hold => (
+
+
+
+ {hold.display_name}
+
+
+
+
+ {hold.maintenance_summary}
+
+
+
+
+
+
+
+
+
+ ))}
+
+
{resultCaptureReleaseDecisionHold.blocked_decision_transitions.slice(0, 6).map(transition => (
diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts
index b6ed0dd5a..b3300778c 100644
--- a/apps/web/src/lib/api-client.ts
+++ b/apps/web/src/lib/api-client.ts
@@ -9214,6 +9214,17 @@ export interface AiAgentResultCaptureReleaseDecisionHoldSnapshot {
rollback_release_passed: boolean
rollback_summary: string
}[]
+ maintenance_window_decision_holds: {
+ hold_id: string
+ display_name: string
+ owner_agent: string
+ status: string
+ hold_mode: string
+ maintenance_window_required: boolean
+ maintenance_window_approved: boolean
+ live_apply_release_passed: boolean
+ maintenance_summary: string
+ }[]
live_apply_decision_holds: {
hold_id: string
display_name: string
@@ -9253,6 +9264,7 @@ export interface AiAgentResultCaptureReleaseDecisionHoldSnapshot {
owner_decision_hold_count: number
verifier_decision_hold_count: number
rollback_decision_hold_count: number
+ maintenance_window_decision_hold_count: number
live_apply_decision_hold_count: number
blocked_decision_transition_count: number
operator_action_count: number
@@ -9264,6 +9276,8 @@ export interface AiAgentResultCaptureReleaseDecisionHoldSnapshot {
blocked_verifier_decision_count: number
approval_required_rollback_decision_count: number
blocked_rollback_decision_count: number
+ approval_required_maintenance_window_decision_count: number
+ blocked_maintenance_window_decision_count: number
approval_required_live_apply_decision_count: number
blocked_live_apply_decision_count: number
critical_blocker_count: number
diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md
index 92c55e327..5d9850f79 100644
--- a/docs/LOGBOOK.md
+++ b/docs/LOGBOOK.md
@@ -4,19 +4,20 @@
**完成內容**:
- 新增 `ai_agent_result_capture_release_decision_hold_v1` schema、committed snapshot、loader 與 API endpoint `GET /api/v1/agents/agent-result-capture-release-decision-hold`。
-- P2-138 snapshot 固定 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 live-apply decision hold、6 個 blocked decision transition 與 5 個 operator action。
-- Governance automation inventory 頁新增 P2-138 區塊,顯示 P2-138 進度 `100%`、釋出決策保留 `5`、負責人決策保留 `5`、驗證器決策保留 `5`、回滾決策保留 `5`、正式套用保留 `5`、已阻擋轉換 `6`、operator action `5`、需批准 `10`、阻擋 `10`、正式寫入 / 發送 `0`。
-- Release decision hold truth 固定為 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API、report receipt、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive operation 仍全部維持 `0 / false`。
+- P2-138 snapshot 固定 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 maintenance window decision hold、5 個 live-apply decision hold、6 個 blocked decision transition 與 5 個 operator action。
+- Governance automation inventory 頁新增 P2-138 區塊,顯示 P2-138 進度 `100%`、釋出決策保留 `5`、負責人決策保留 `5`、驗證器決策保留 `5`、回滾決策保留 `5`、維護窗口決策保留 `5`、正式套用保留 `5`、已阻擋轉換 `6`、operator action `5`、需批准 `12`、阻擋 `12`、正式寫入 / 發送 `0`。
+- Release decision hold truth 固定為 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API、report receipt、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive operation 仍全部維持 `0 / false`。
**本地驗證**:
- JSON parse:P2-138 schema / snapshot、`zh-TW.json`、`en.json` 通過。
- Python 編譯:P2-138 loader 與 `agents.py` 通過。
-- API/service pytest:P2-138 + P2-137 regression `14 passed`。
-- i18n key mirror:`11772` keys,`zh-TW.json` / `en.json` 鏡像差異 `0`。
-- Web typecheck:本臨時 worktree 缺少 `node_modules`,`tsc: command not found`;未安裝依賴,避免增加主機負載,等待 Gitea CD 在乾淨環境補跑。
+- API/service pytest:P2-138 + P2-137 regression `15 passed`。
+- i18n key mirror:`11777` keys,`zh-TW.json` / `en.json` 鏡像差異 `0`。
+- Web typecheck:`pnpm --filter @awoooi/web typecheck` 通過。
+- Web production build:`NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 SENTRY_SUPPRESS_GLOBAL_ERROR_HANDLER_FILE_WARNING=1 pnpm --filter @awoooi/web build` 通過,`/zh-TW/governance` 進 build summary。
**安全邊界**:
-- P2-138 仍是只讀 release decision hold;不接受口頭批准、不把 hold 解讀成 owner release authorized、不把 owner review packet 解讀成決策通過、不核發或通過 release authorization、不通過 rollback release、不釋放 live apply、不套用 writer、不執行正式寫入、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不讀 canonical runtime target、不做 live query、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部工作內容。
+- P2-138 仍是只讀 release decision hold;不接受口頭批准、不把 hold 解讀成 owner release authorized、不把 owner review packet 解讀成決策通過、不批准維護窗口、不核發或通過 release authorization、不通過 rollback release、不釋放 live apply、不套用 writer、不執行正式寫入、不寫 receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不讀 canonical runtime target、不做 live query、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部工作內容。
- 本段尚未正式部署;需要 feature commit、deploy marker、production API readback 與 desktop / mobile Browser smoke 後,才可記錄正式驗證完成。
**下一步**:
diff --git a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md
index c76ec0713..31dc9ffb5 100644
--- a/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md
+++ b/docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md
@@ -66,8 +66,8 @@
### 2026-06-14 10:58 狀態同步
- `P2-138` release decision hold 已本地完成:新增 `ai_agent_result_capture_release_decision_hold_v1`、`GET /api/v1/agents/agent-result-capture-release-decision-hold`、治理頁 P2-138 區塊與繁中 UI 文案。
-- 本地證據:P2-138 + P2-137 API/service regression `14 passed`、JSON parse、Python compile、i18n key mirror `11772` 通過。
-- P2-138 固定 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 live-apply decision hold、6 個 blocked decision transition、5 個 operator action、需批准 `10`、阻擋 `10`、正式寫入 / 發送 `0`。
+- 本地證據:P2-138 + P2-137 API/service regression `15 passed`、JSON parse、Python compile、i18n key mirror `11777`、Web typecheck 與 Web production build 通過。
+- P2-138 固定 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 maintenance window decision hold、5 個 live-apply decision hold、6 個 blocked decision transition、5 個 operator action、需批准 `12`、阻擋 `12`、正式寫入 / 發送 `0`。
- Web typecheck 在本臨時 worktree 因缺少 `node_modules` 停在 `tsc: command not found`;未安裝依賴,避免增加主機負載,等待 Gitea CD 在乾淨環境跑完整前端驗證。
- 邊界仍維持:owner release authorized、owner review approved、owner decision approved、verifier decision approved、release decision passed、release authorization granted / passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API、report receipt、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 全部 `0 / false`。
- P2-138 推送與正式驗證後才可交給 `P2-139` release decision readback;仍不得直接開啟 result capture writer、learning writer、PlayBook trust writer、reviewer queue write、Gateway queue write、Telegram send、Bot API call 或 production write。
@@ -1066,7 +1066,7 @@ UI:
| P2-135 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release authorization readback gate | `ai_agent_result_capture_release_authorization_readback_gate_v1` / schema / snapshot / 只讀 API / governance UI;本地 pytest `14 passed`、JSON parse、Python compile、Web typecheck 通過;5 個 release authorization readback、5 個 rollback release readback、5 個 maintenance window readback hold、5 個 live-apply release readback hold、6 個 blocked release readback transition、5 個 operator action;runtime authority 固定 `result_capture_release_authorization_readback_gate_only_no_live_write`;owner release authorized、release authorization granted / passed、rollback release、live apply release、writer apply、execution apply、receipt write、result capture、learning、PlayBook trust、Gateway、Telegram、production write 全為 `0` | 正式站 deploy marker `8d575c1a` 已驗證;production API readback、desktop / mobile smoke、禁用內部協作片語 `0`、水平溢位 `0`、高風險控制 `0`、console error `0`;已由 P2-136 承接,不核發 release authorization、不釋放 live apply、不套用 writer |
| P2-136 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release verifier preflight gate | `ai_agent_result_capture_release_verifier_preflight_gate_v1` / schema / snapshot / 只讀 API / governance UI;feature commit `913d7f68`、deploy marker `f2fa8454` 已正式驗證;5 個 release verifier preflight、5 個 rollback verifier preflight、5 個 maintenance window verifier hold、5 個 live-apply verifier hold、6 個 blocked verifier preflight transition、5 個 operator action;需批准 `8`、blocked status subtotal `4`、critical blocker `5`、前端顯示阻擋總數 `9`;runtime authority 固定 `result_capture_release_verifier_preflight_gate_only_no_live_write`;post-release verifier ready、release authorization granted / passed、rollback release、live apply release、writer apply、execution apply、receipt write、result capture、learning、PlayBook trust、Gateway、Telegram、production write、secret read、destructive operation 全為 `0` | production API readback、desktop / mobile smoke、禁用內部協作片語 `0`、水平溢位 `0`、危險控制 `0`、console error `0`;已由 P2-137 承接,不把 verifier preflight 視為 post-release verifier ready、不核發 release authorization、不釋放 live apply、不套用 writer |
| P2-137 | 完成 | 100 | OpenClaw + Hermes + NemoTron | release verifier owner review packet | `ai_agent_result_capture_release_verifier_owner_review_packet_v1` / schema / snapshot / 只讀 API / governance UI;feature commit `f737f278`、deploy marker `d023f5d7` 已正式驗證;5 個 owner review packet、5 個 verifier review packet、5 個 rollback owner review packet、5 個 maintenance window review hold、5 個 live-apply owner review hold、6 個 blocked owner review transition、5 個 operator action;需批准 `10`、阻擋 `10`;runtime authority 固定 `result_capture_release_verifier_owner_review_packet_only_no_live_write`;owner release authorized / owner review approved / maintenance window approved / rollback owner confirmed / post-release verifier ready / release authorization granted / release authorization passed / rollback release / live apply release / writer apply / execution apply / receipt write / result capture / learning / PlayBook trust / reviewer queue / Gateway / Telegram / Bot API / production write / secret read / destructive operation 全為 `0` | 本地 pytest `7 passed`、JSON parse、Python compile、Web typecheck 通過;production API readback、desktop / mobile smoke、水平溢位 `0`、P2-137 卡片危險控制 `0`、console error `0`、HTTP 4xx/5xx `0`;已由 P2-138 承接 |
-| P2-138 | 本地完成 | 100 | OpenClaw + Hermes + NemoTron | release decision hold | `ai_agent_result_capture_release_decision_hold_v1` / schema / snapshot / 只讀 API / governance UI;承接 P2-137,只建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 live-apply decision hold、6 個 blocked decision transition、5 個 operator action;需批准 `10`、阻擋 `10`;runtime authority 固定 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized / owner review approved / owner decision approved / verifier decision approved / release decision passed / release authorization granted / passed / rollback release / live apply release / writer apply / execution apply / receipt write / reviewer queue / Gateway / Telegram / Bot API / result capture / learning / PlayBook trust / production write / secret read / destructive operation 全為 `0` | 本地 P2-138 + P2-137 pytest `14 passed`、JSON parse、Python compile、i18n key mirror `11772` 通過;本 worktree 因缺少 `node_modules` 未跑 Web typecheck,待 Gitea CD / production smoke;不得把 P2-138 當 runtime gate |
+| P2-138 | 本地完成 | 100 | OpenClaw + Hermes + NemoTron | release decision hold | `ai_agent_result_capture_release_decision_hold_v1` / schema / snapshot / 只讀 API / governance UI;承接 P2-137,只建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 maintenance window decision hold、5 個 live-apply decision hold、6 個 blocked decision transition、5 個 operator action;需批准 `12`、阻擋 `12`;runtime authority 固定 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized / owner review approved / owner decision approved / verifier decision approved / maintenance window approved / release decision passed / release authorization granted / passed / rollback release / live apply release / writer apply / execution apply / receipt write / reviewer queue / Gateway / Telegram / Bot API / result capture / learning / PlayBook trust / production write / secret read / destructive operation 全為 `0` | 本地 P2-138 + P2-137 pytest `15 passed`、JSON parse、Python compile、i18n key mirror `11777`、Web typecheck 與 Web production build 通過;待 Gitea CD / production smoke;不得把 P2-138 當 runtime gate |
| P2-139 | 計畫中 | 0 | OpenClaw + Hermes + NemoTron | release decision readback | 承接 P2-138,只能建立 release decision hold readback 的只讀證據;不得把 release decision hold 視為決策通過,不得讀 secret、不得寫 reviewer queue、不得寫 Gateway queue、不得送 Telegram、不得呼叫 Bot API、不得 production write | P2-138 正式部署驗證後才可開始;仍不得把 P2-139 當 runtime gate |
diff --git a/docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json b/docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json
index a7d48fff1..89786da5e 100644
--- a/docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json
+++ b/docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json
@@ -365,6 +365,63 @@
"rollback_summary": "rollback owner 未確認前不得通過 Gateway queue rollback release。"
}
],
+ "maintenance_window_decision_holds": [
+ {
+ "hold_id": "maintenance_window_decision_hold_result_capture",
+ "display_name": "Result capture 維護窗口決策保留",
+ "owner_agent": "openclaw",
+ "status": "ready_for_decision_review",
+ "hold_mode": "maintenance_window_decision_hold",
+ "maintenance_window_required": true,
+ "maintenance_window_approved": false,
+ "live_apply_release_passed": false,
+ "maintenance_summary": "維護窗口未批准前不得釋放 Result capture 正式套用。"
+ },
+ {
+ "hold_id": "maintenance_window_decision_hold_learning",
+ "display_name": "Learning 維護窗口決策保留",
+ "owner_agent": "hermes",
+ "status": "approval_required",
+ "hold_mode": "maintenance_window_decision_hold",
+ "maintenance_window_required": true,
+ "maintenance_window_approved": false,
+ "live_apply_release_passed": false,
+ "maintenance_summary": "維護窗口未批准前不得釋放 Learning 正式套用。"
+ },
+ {
+ "hold_id": "maintenance_window_decision_hold_playbook_trust",
+ "display_name": "PlayBook trust 維護窗口決策保留",
+ "owner_agent": "nemotron",
+ "status": "blocked_by_policy",
+ "hold_mode": "maintenance_window_decision_hold",
+ "maintenance_window_required": true,
+ "maintenance_window_approved": false,
+ "live_apply_release_passed": false,
+ "maintenance_summary": "維護窗口未批准前不得釋放 PlayBook trust 正式套用。"
+ },
+ {
+ "hold_id": "maintenance_window_decision_hold_reviewer_queue",
+ "display_name": "Reviewer queue 維護窗口決策保留",
+ "owner_agent": "openclaw",
+ "status": "approval_required",
+ "hold_mode": "maintenance_window_decision_hold",
+ "maintenance_window_required": true,
+ "maintenance_window_approved": false,
+ "live_apply_release_passed": false,
+ "maintenance_summary": "維護窗口未批准前不得釋放 Reviewer queue 正式套用。"
+ },
+ {
+ "hold_id": "maintenance_window_decision_hold_gateway_queue",
+ "display_name": "Gateway queue 維護窗口決策保留",
+ "owner_agent": "nemotron",
+ "status": "ready_for_decision_review",
+ "hold_mode": "maintenance_window_decision_hold",
+ "maintenance_window_required": true,
+ "maintenance_window_approved": false,
+ "live_apply_release_passed": false,
+ "maintenance_summary": "維護窗口未批准前不得釋放 Gateway queue 正式套用。"
+ }
+ ],
"live_apply_decision_holds": [
{
"hold_id": "live_apply_decision_hold_result_capture",
@@ -516,6 +573,7 @@
"owner_decision_hold_count": 5,
"verifier_decision_hold_count": 5,
"rollback_decision_hold_count": 5,
+ "maintenance_window_decision_hold_count": 5,
"live_apply_decision_hold_count": 5,
"blocked_decision_transition_count": 6,
"operator_action_count": 5,
@@ -527,9 +585,11 @@
"blocked_verifier_decision_count": 1,
"approval_required_rollback_decision_count": 2,
"blocked_rollback_decision_count": 1,
+ "approval_required_maintenance_window_decision_count": 2,
+ "blocked_maintenance_window_decision_count": 1,
"approval_required_live_apply_decision_count": 2,
"blocked_live_apply_decision_count": 1,
- "critical_blocker_count": 5,
+ "critical_blocker_count": 6,
"owner_release_authorized_count": 0,
"owner_release_approved_count": 0,
"owner_review_approved_count": 0,
diff --git a/docs/schemas/ai_agent_result_capture_release_decision_hold_v1.schema.json b/docs/schemas/ai_agent_result_capture_release_decision_hold_v1.schema.json
index abc4916dc..5b000b395 100644
--- a/docs/schemas/ai_agent_result_capture_release_decision_hold_v1.schema.json
+++ b/docs/schemas/ai_agent_result_capture_release_decision_hold_v1.schema.json
@@ -14,6 +14,7 @@
"owner_decision_holds",
"verifier_decision_holds",
"rollback_decision_holds",
+ "maintenance_window_decision_holds",
"live_apply_decision_holds",
"blocked_decision_transitions",
"operator_actions",
@@ -74,6 +75,14 @@
"type": "object"
}
},
+ "maintenance_window_decision_holds": {
+ "type": "array",
+ "minItems": 5,
+ "maxItems": 5,
+ "items": {
+ "type": "object"
+ }
+ },
"live_apply_decision_holds": {
"type": "array",
"minItems": 5,
diff --git a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md
index 4b60de1dc..2be75ae02 100644
--- a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md
+++ b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md
@@ -675,7 +675,7 @@ Alert / Sentry / SigNoz / Gitea / Market Watch / Operator
| `docs/evaluations/ai_agent_result_capture_release_authorization_readback_gate_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-authorization-readback-gate` | P2-135 release authorization readback gate;承接 P2-134 release authorization hold,建立 5 個 release authorization readback、5 個 rollback release readback、5 個 maintenance window readback hold、5 個 live-apply release readback hold、6 個 blocked release readback transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_authorization_readback_gate_only_no_live_write`;owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;本地 API / typecheck 已通過,deploy marker `8d575c1a` 已正式驗證,正式 API readback 與 Browser desktop / mobile smoke 已完成 |
| `docs/evaluations/ai_agent_result_capture_release_verifier_preflight_gate_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-verifier-preflight-gate` | P2-136 release verifier preflight gate;承接 P2-135 release authorization readback gate,建立 5 個 release verifier preflight、5 個 rollback verifier preflight、5 個 maintenance window verifier hold、5 個 live-apply verifier hold、6 個 blocked verifier preflight transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_verifier_preflight_gate_only_no_live_write`;post-release verifier ready、owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `f2fa8454` 已正式驗證,正式 API readback 與 Browser desktop / mobile smoke 已完成,下一步 P2-137 owner / verifier review packet |
| `docs/evaluations/ai_agent_result_capture_release_verifier_owner_review_packet_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-verifier-owner-review-packet` | P2-137 release verifier owner review packet;承接 P2-136 release verifier preflight gate,建立 5 個 owner review packet、5 個 verifier review packet、5 個 rollback owner review packet、5 個 maintenance window review hold、5 個 live-apply owner review hold、6 個 blocked owner review transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_verifier_owner_review_packet_only_no_live_write`;owner release authorized、owner review approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;deploy marker `d023f5d7` 已正式驗證,正式 API readback 與 desktop / mobile smoke 已完成,下一步 P2-138 release decision hold |
-| `docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-decision-hold` | P2-138 release decision hold;承接 P2-137 release verifier owner review packet,建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 live-apply decision hold、6 個 blocked decision transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;本地 P2-138 + P2-137 regression `14 passed`、JSON parse、Python compile 與 i18n key mirror 通過,待 Gitea CD 與 production smoke,下一步 P2-139 release decision readback |
+| `docs/evaluations/ai_agent_result_capture_release_decision_hold_2026-06-14.json` + `GET /api/v1/agents/agent-result-capture-release-decision-hold` | P2-138 release decision hold;承接 P2-137 release verifier owner review packet,建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 maintenance window decision hold、5 個 live-apply decision hold、6 個 blocked decision transition 與 5 個 operator action;runtime authority 固定 `result_capture_release_decision_hold_only_no_live_write`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、canonical runtime target read、live query、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read 與 destructive action 全部 `0 / false`;本地 P2-138 + P2-137 regression `15 passed`、JSON parse、Python compile、i18n key mirror、Web typecheck 與 Web production build 通過,待 Gitea CD 與 production smoke,下一步 P2-139 release decision readback |
| `docs/evaluations/ai_agent_live_read_model_gate_2026-06-11.json` + `GET /api/v1/agents/agent-live-read-model-gate` | P2-403B AgentSession / Redis Streams live read model gate;定義 safe fields、Redis envelope、worker gate、rollback plan 與 no-write smoke,不連 DB、不讀寫 Redis、不啟動 worker |
#### 3.2.1c 2026-06-11 AI Agent 主動營運委派與版本生命週期契約
@@ -802,7 +802,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence
56. 建立 release authorization readback gate。✅ P2-135 已完成並正式驗證;release authorization readback `5`、rollback release readback `5`、maintenance window readback hold `5`、live-apply release readback hold `5`、blocked release readback transition `6`、operator action `5`,approval-required readback / rollback / maintenance / live apply `2 / 2 / 2 / 2`、blocked readback / rollback / maintenance / live apply `1 / 1 / 1 / 1`、critical blocker `5`;owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write 仍為 `0 / false`;deploy marker `8d575c1a`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-136 承接。
57. 建立 release verifier preflight gate。✅ P2-136 已完成並正式驗證;release verifier preflight `5`、rollback verifier preflight `5`、maintenance window verifier hold `5`、live-apply verifier hold `5`、blocked verifier preflight transition `6`、operator action `5`,approval-required preflight / rollback / maintenance / live apply `2 / 2 / 2 / 2`、blocked preflight / rollback / maintenance / live apply `1 / 1 / 1 / 1`、critical blocker `5`,前端顯示阻擋總數 `9`;post-release verifier ready、owner release authorized、owner release approved、maintenance window approved、rollback owner confirmed、final release candidate approved、final release candidate passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;deploy marker `f2fa8454`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-137 承接。
58. 建立 owner / verifier review packet。✅ P2-137 已完成並正式驗證;owner review packet `5`、verifier review packet `5`、rollback owner review packet `5`、maintenance window review hold `5`、live-apply owner review hold `5`、blocked owner review transition `6`、operator action `5`,approval-required owner / verifier / rollback / maintenance / live apply `2 / 2 / 2 / 2 / 2`、blocked owner / verifier / rollback / maintenance / live apply `1 / 1 / 1 / 1 / 1`、critical blocker `5`;owner release authorized、owner review approved、maintenance window approved、rollback owner confirmed、post-release verifier ready、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;本地 API/service pytest `7 passed`、JSON parse、Python compile、Web typecheck 通過;deploy marker `d023f5d7`、正式 API readback 與 desktop / mobile smoke 已完成。已由 P2-138 承接。
-59. 建立 release decision hold。✅ P2-138 本地完成;release decision hold `5`、owner decision hold `5`、verifier decision hold `5`、rollback decision hold `5`、live-apply decision hold `5`、blocked decision transition `6`、operator action `5`,approval-required release / owner / verifier / rollback / live apply `2 / 2 / 2 / 2 / 2`、blocked release / owner / verifier / rollback / live apply `1 / 1 / 1 / 1 / 1`、critical blocker `5`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;本地 P2-138 + P2-137 regression `14 passed`、JSON parse、Python compile、i18n key mirror 通過;待 Gitea CD 與正式站 smoke。
+59. 建立 release decision hold。✅ P2-138 本地完成;release decision hold `5`、owner decision hold `5`、verifier decision hold `5`、rollback decision hold `5`、maintenance window decision hold `5`、live-apply decision hold `5`、blocked decision transition `6`、operator action `5`,approval-required release / owner / verifier / rollback / maintenance / live apply `2 / 2 / 2 / 2 / 2 / 2`、blocked release / owner / verifier / rollback / maintenance / live apply `1 / 1 / 1 / 1 / 1 / 1`、critical blocker `6`;owner release authorized、owner review approved、owner decision approved、verifier decision approved、maintenance window approved、release decision passed、release authorization granted、release authorization passed、rollback release passed、live apply release passed、writer apply、execution apply、receipt write、reviewer queue write、Gateway queue write、Telegram send、Bot API call、report receipt write、result capture write、learning write、PlayBook trust write、production write、secret read、destructive operation 仍為 `0 / false`;本地 P2-138 + P2-137 regression `15 passed`、JSON parse、Python compile、i18n key mirror、Web typecheck 與 Web production build 通過;待 Gitea CD 與正式站 smoke。
60. 建立 release decision readback。⬜ P2-139 planned;承接 P2-138,只能整理 release decision hold readback 的只讀證據,不得把 hold 視為決策通過,不得寫 reviewer queue、Gateway queue、Telegram、Bot API、result capture、learning、PlayBook trust 或 production target。
#### 3.2.1d 2026-06-11 Agent 互動、學習與成長證據面
@@ -1948,8 +1948,8 @@ Phase 6 完成後
### 2026-06-14 10:58 (台北) — §3.2 / §5 — 新增 P2-138 release decision hold — 本地完成決策保留只讀關卡
- 新增 `ai_agent_result_capture_release_decision_hold_v1` schema、snapshot、service loader、FastAPI endpoint `GET /api/v1/agents/agent-result-capture-release-decision-hold`、governance automation inventory UI 與 i18n 文案。
-- P2-138 承接 P2-137 owner review packet,只建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 live-apply decision hold、6 個 blocked decision transition 與 5 個 operator action。
-- 本地驗證:P2-138 + P2-137 API/service regression `14 passed`、JSON parse、Python compile、i18n key mirror `11772` 通過;本 worktree 缺少 `node_modules`,Web typecheck 停在 `tsc: command not found`,待 Gitea CD 於乾淨環境補跑。
+- P2-138 承接 P2-137 owner review packet,只建立 5 個 release decision hold、5 個 owner decision hold、5 個 verifier decision hold、5 個 rollback decision hold、5 個 maintenance window decision hold、5 個 live-apply decision hold、6 個 blocked decision transition 與 5 個 operator action。
+- 本地驗證:P2-138 + P2-137 API/service regression `15 passed`、JSON parse、Python compile、i18n key mirror `11777`、Web typecheck 與 Web production build 通過。
- 本波仍不讀 canonical runtime target、不做 live query、不寫 reviewer queue、不寫 Gateway queue、不送 Telegram、不呼叫 Bot API、不寫 report receipt、不寫 result capture、不寫 learning、不更新 PlayBook trust、不寫 production target、不讀 secret、不執行 destructive action、不回傳內部工作內容;正式驗證後才可由 P2-139 release decision readback 承接。
### 2026-06-14 08:36 (台北) — §3.2 / §5 — 正式驗證 P2-134 release authorization hold — 完成釋出授權保留只讀關卡