feat(governance): 新增 Status Cleanup Dashboard read model

This commit is contained in:
Your Name
2026-06-24 23:45:37 +08:00
parent 6b9a09a01a
commit e4c13530fd
12 changed files with 1847 additions and 0 deletions

View File

@@ -73,6 +73,9 @@ from src.services.ai_agent_critic_reviewer_result_capture import (
from src.services.ai_agent_deployment_layout import (
load_latest_ai_agent_deployment_layout,
)
from src.services.awoooi_status_cleanup_dashboard import (
load_latest_awoooi_status_cleanup_dashboard,
)
from src.services.ai_agent_failure_receipt_no_send_replay import (
load_latest_ai_agent_failure_receipt_no_send_replay,
)
@@ -763,6 +766,36 @@ async def get_agent_deployment_layout() -> dict[str, Any]:
) from exc
@router.get(
"/awoooi-status-cleanup-dashboard",
response_model=dict[str, Any],
summary="取得 AWOOOI 狀態清理儀表板",
description=(
"讀取最新已提交的 AWOOOI Status Cleanup Dashboard 只讀快照;"
"此端點只呈現狀態清理完成度、owner gate、apply gate、artifact sync 與 Wazuh handoff 邊界。"
"它不更新 project_current_status / memory、不同步 raw Codex App DB / auth / conversations / sessions、"
"不呼叫 Wazuh live API、不執行 active response、不改主機、不修改 workflow / repo refs、"
"不執行 backup / restore / migration。"
),
)
async def get_awoooi_status_cleanup_dashboard() -> dict[str, Any]:
"""回傳最新 AWOOOI 狀態清理儀表板只讀快照。"""
try:
payload = await asyncio.to_thread(load_latest_awoooi_status_cleanup_dashboard)
return redact_public_lan_topology(payload)
except FileNotFoundError as exc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=str(exc),
) from exc
except (json.JSONDecodeError, ValueError) as exc:
logger.error("awoooi_status_cleanup_dashboard_invalid", error=str(exc))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="AWOOOI 狀態清理儀表板快照無效",
) from exc
@router.get(
"/agent-12-agent-war-room",
response_model=dict[str, Any],

View File

@@ -0,0 +1,276 @@
"""
AWOOOI Status Cleanup dashboard snapshot.
Loads the read-only dashboard that combines status cleanup preflight, owner
review, owner response preflight, dry-run execution plan, apply gate, and
artifact sync readback. This module never writes memory, syncs raw Codex app
data, fetches repos, modifies workflows, queries Wazuh live APIs, or authorizes
runtime writes.
"""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
from src.services.snapshot_paths import default_operations_dir
_DEFAULT_OPERATIONS_DIR = default_operations_dir(Path(__file__))
_SNAPSHOT_PATTERN = "awoooi-status-cleanup-dashboard.snapshot.json"
_SCHEMA_VERSION = "awoooi_status_cleanup_dashboard_v1"
def load_latest_awoooi_status_cleanup_dashboard(
operations_dir: Path | None = None,
) -> dict[str, Any]:
"""Load the committed AWOOOI Status Cleanup dashboard snapshot."""
directory = operations_dir or _DEFAULT_OPERATIONS_DIR
candidates = sorted(directory.glob(_SNAPSHOT_PATTERN))
if not candidates:
raise FileNotFoundError(f"no AWOOOI status cleanup dashboard found in {directory}")
latest = candidates[-1]
with latest.open(encoding="utf-8") as handle:
payload = json.load(handle)
if not isinstance(payload, dict):
raise ValueError(f"{latest}: expected JSON object")
_require_schema(payload, _SCHEMA_VERSION, str(latest))
_require_read_only_boundaries(payload, str(latest))
_require_summary(payload, str(latest))
_require_cards(payload, str(latest))
_require_risk_controls(payload, str(latest))
_require_wazuh_boundary(payload, str(latest))
_require_hard_gates(payload, str(latest))
return payload
def _require_schema(payload: dict[str, Any], expected: str, label: str) -> None:
actual = payload.get("schema_version")
if actual != expected:
raise ValueError(f"{label}: expected schema_version={expected}, got {actual!r}")
def _require_read_only_boundaries(payload: dict[str, Any], label: str) -> None:
blocked_flags = {
"secret_values_collected",
"remote_write_performed",
"local_product_write_performed",
"execution_authorized",
"memory_write_authorized",
"wazuh_api_live_query_authorized",
"runtime_execution_authorized",
"ui_implementation_authorized",
}
invalid = sorted(flag for flag in blocked_flags if payload.get(flag) is not False)
if invalid:
raise ValueError(f"{label}: dashboard boundaries must remain false: {invalid}")
operation_boundaries = payload.get("operation_boundaries") or {}
invalid_ops = sorted(key for key, value in operation_boundaries.items() if value is not False)
if invalid_ops:
raise ValueError(f"{label}: operation boundaries must remain false: {invalid_ops}")
def _require_summary(payload: dict[str, Any], label: str) -> None:
summary = payload.get("summary") or {}
gates = payload.get("gate_cards") or []
blockers = payload.get("blocking_reasons") or []
actions = payload.get("next_actions") or []
if payload.get("target_route") != "/workspace/status-cleanup":
raise ValueError(f"{label}: target_route must remain /workspace/status-cleanup")
if summary.get("dashboard_status") != "blocked_status_cleanup_apply_not_authorized":
raise ValueError(f"{label}: dashboard_status must remain blocked")
if summary.get("gate_count") != len(gates):
raise ValueError(f"{label}: gate_count mismatch")
if summary.get("blocked_gate_count") != sum(1 for item in gates if item.get("blocked") is True):
raise ValueError(f"{label}: blocked_gate_count mismatch")
if summary.get("blocking_reason_count") != len(blockers):
raise ValueError(f"{label}: blocking_reason_count mismatch")
if summary.get("next_action_count") != len(actions):
raise ValueError(f"{label}: next_action_count mismatch")
for flag in (
"apply_allowed",
"memory_write_authorized",
"wazuh_api_live_query_authorized",
"runtime_execution_authorized",
"ui_implementation_allowed",
):
if summary.get(flag) is not False:
raise ValueError(f"{label}: summary.{flag} must remain false")
if summary.get("gate_count") != 5:
raise ValueError(f"{label}: dashboard must contain five status cleanup gates")
if summary.get("wazuh_handoff_status") != "blocked_not_released":
raise ValueError(f"{label}: Wazuh handoff status must remain blocked")
if summary.get("wazuh_handoff_base_commit") != "b540fc0c":
raise ValueError(f"{label}: Wazuh handoff base must remain b540fc0c")
if summary.get("wazuh_handoff_commit_count") != 7:
raise ValueError(f"{label}: Wazuh handoff commit count must be 7")
if summary.get("wazuh_handoff_patch_count") != 7:
raise ValueError(f"{label}: Wazuh handoff patch count must be 7")
zero_wazuh_summary = (
"wazuh_release_owner_request_sent_count",
"wazuh_release_owner_response_accepted_count",
"wazuh_acknowledged_release_owner_ack_count",
"wazuh_accepted_evidence_count",
"wazuh_live_metadata_owner_count",
"wazuh_secret_metadata_count",
"wazuh_live_agent_registry_readback",
"iwooos_wazuh_runtime_gate",
"wazuh_active_response_count",
"wazuh_agent_visibility_runtime_gate_count",
"wazuh_push_gate_count",
"wazuh_deploy_gate_count",
"wazuh_readback_gate_count",
"wazuh_runtime_gate_count",
)
non_zero_wazuh = sorted(key for key in zero_wazuh_summary if summary.get(key) != 0)
if non_zero_wazuh:
raise ValueError(f"{label}: Wazuh release summary gates must remain zero: {non_zero_wazuh}")
def _require_cards(payload: dict[str, Any], label: str) -> None:
gate_ids = {item.get("gate_id") for item in payload.get("gate_cards") or []}
required_gates = {
"status_cleanup_preflight",
"owner_review_package",
"owner_response_preflight",
"execution_plan",
"apply_gate",
}
missing_gates = sorted(required_gates - gate_ids)
if missing_gates:
raise ValueError(f"{label}: gate_cards missing required gates: {missing_gates}")
metric_ids = {item.get("metric_id") for item in payload.get("metric_cards") or []}
required_metrics = {
"overall_completion",
"project_status_age",
"owner_flags",
"approved_sections",
"execution_preview",
"apply_confirmation",
"artifact_sync",
}
missing_metrics = sorted(required_metrics - metric_ids)
if missing_metrics:
raise ValueError(f"{label}: metric_cards missing required metrics: {missing_metrics}")
unsafe = [
item.get("gate_id")
for item in payload.get("gate_cards") or []
if item.get("memory_write_authorized") is not False
or item.get("execution_authorized") is not False
]
if unsafe:
raise ValueError(f"{label}: gate cards must remain read-only: {sorted(unsafe)}")
def _require_risk_controls(payload: dict[str, Any], label: str) -> None:
control_ids = {item.get("control_id") for item in payload.get("risk_controls") or []}
required = {
"memory_write",
"raw_codex_history",
"wazuh_runtime",
"workflow",
"repo_refs",
"host",
"backup_restore",
"ui",
}
missing = sorted(required - control_ids)
if missing:
raise ValueError(f"{label}: risk_controls missing controls: {missing}")
unsafe = sorted(
item.get("control_id")
for item in payload.get("risk_controls") or []
if item.get("authorized") is not False
)
if unsafe:
raise ValueError(f"{label}: risk controls must not authorize actions: {unsafe}")
def _require_wazuh_boundary(payload: dict[str, Any], label: str) -> None:
handoff = payload.get("wazuh_handoff") or {}
if handoff.get("status") != "blocked_not_released":
raise ValueError(f"{label}: Wazuh handoff status must remain blocked_not_released")
if handoff.get("base_commit") != "b540fc0c":
raise ValueError(f"{label}: Wazuh handoff base must remain b540fc0c")
if handoff.get("commit_count") != 7:
raise ValueError(f"{label}: Wazuh handoff commit_count must be 7")
if handoff.get("patch_count") != 7:
raise ValueError(f"{label}: Wazuh handoff patch_count must be 7")
zero_handoff_keys = (
"release_owner_request_sent_count",
"release_owner_response_accepted_count",
"acknowledged_release_owner_ack_count",
"accepted_evidence_count",
"live_metadata_owner_count",
"secret_metadata_count",
"wazuh_live_agent_registry_readback",
"iwooos_wazuh_runtime_gate",
"active_response",
"push_gate_count",
"deploy_gate_count",
"readback_gate_count",
"runtime_gate_count",
)
non_zero_handoff = sorted(key for key in zero_handoff_keys if handoff.get(key) != 0)
if non_zero_handoff:
raise ValueError(f"{label}: Wazuh handoff gates must remain zero: {non_zero_handoff}")
if handoff.get("runtime_execution_authorized") is not False:
raise ValueError(f"{label}: Wazuh runtime execution must remain false")
if handoff.get("wazuh_api_live_query_authorized") is not False:
raise ValueError(f"{label}: Wazuh live query must remain false")
if handoff.get("stored_api_secret_metadata_changed") is not False:
raise ValueError(f"{label}: Wazuh stored API secret metadata must remain unchanged")
if handoff.get("agent_visibility_status") != "blocked_waiting_manager_agent_registry_readback":
raise ValueError(f"{label}: Wazuh agent visibility must remain blocked")
visibility_false = (
"manager_agent_registry_readback_passed",
"iwooos_live_route_readback_passed",
"dashboard_agent_list_recovered",
)
invalid_visibility = sorted(key for key in visibility_false if handoff.get(key) is not False)
if invalid_visibility:
raise ValueError(f"{label}: Wazuh visibility flags must remain false: {invalid_visibility}")
if handoff.get("agent_visibility_runtime_gate_count") != 0:
raise ValueError(f"{label}: Wazuh visibility runtime gate count must remain zero")
boundary = str(handoff.get("boundary", ""))
for token in (
"base=b540fc0c",
"38dc3c2f",
"9a53d3e1",
"e9972d47",
"758d419e",
"04db4b8a",
"8eec298e",
"325f262a",
"release_lane_preflight=ready0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0",
"owner_gate=request_sent0_response_accepted0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0",
"live_metadata_env_gate=owner0_secret_metadata0_push0_deploy0_readback0_runtime0",
"wazuh_live_agent_registry_readback=0",
"iwooos_wazuh_runtime_gate=0",
"active_response=0",
"manager_agent_registry_readback_passed=false",
"iwooos_live_route_readback_passed=false",
"dashboard_agent_list_recovered=false",
"push_blocked",
):
if token not in boundary:
raise ValueError(f"{label}: Wazuh handoff boundary missing {token}")
def _require_hard_gates(payload: dict[str, Any], label: str) -> None:
gate_text = "\n".join(payload.get("hard_gates") or [])
for token in (
"project_current_status",
"memory_write_authorized=false",
"raw Codex App",
"Wazuh",
".gitea/workflows",
"apps/web",
):
if token not in gate_text:
raise ValueError(f"{label}: hard_gates missing {token}")

View File

@@ -30,3 +30,8 @@ def resolve_repo_root(anchor: Path) -> Path:
def default_evaluations_dir(anchor: Path) -> Path:
"""Resolve the default committed evaluations snapshot directory."""
return resolve_repo_root(anchor) / "docs" / "evaluations"
def default_operations_dir(anchor: Path) -> Path:
"""Resolve the default committed operations snapshot directory."""
return resolve_repo_root(anchor) / "docs" / "operations"

View File

@@ -0,0 +1,112 @@
from __future__ import annotations
import copy
import json
import pytest
from src.services.awoooi_status_cleanup_dashboard import (
load_latest_awoooi_status_cleanup_dashboard,
)
def test_load_latest_awoooi_status_cleanup_dashboard_reads_committed_snapshot():
data = load_latest_awoooi_status_cleanup_dashboard()
assert data["schema_version"] == "awoooi_status_cleanup_dashboard_v1"
assert data["summary"]["dashboard_status"] == "blocked_status_cleanup_apply_not_authorized"
assert data["summary"]["gate_count"] == 5
assert data["summary"]["blocked_gate_count"] == 5
assert data["summary"]["accepted_owner_flag_count"] == 0
assert data["summary"]["required_owner_flag_count"] == 6
assert data["summary"]["apply_allowed"] is False
assert data["summary"]["memory_write_authorized"] is False
assert data["summary"]["wazuh_api_live_query_authorized"] is False
assert data["summary"]["runtime_execution_authorized"] is False
assert data["summary"]["wazuh_handoff_status"] == "blocked_not_released"
assert data["summary"]["wazuh_handoff_base_commit"] == "b540fc0c"
assert data["summary"]["wazuh_handoff_commit_count"] == 7
assert data["summary"]["wazuh_handoff_patch_count"] == 7
assert data["summary"]["wazuh_live_metadata_owner_count"] == 0
assert data["summary"]["wazuh_secret_metadata_count"] == 0
assert data["summary"]["wazuh_live_agent_registry_readback"] == 0
assert data["summary"]["iwooos_wazuh_runtime_gate"] == 0
assert data["summary"]["wazuh_active_response_count"] == 0
assert data["summary"]["wazuh_agent_visibility_status"] == "blocked_waiting_manager_agent_registry_readback"
assert data["summary"]["wazuh_manager_agent_registry_readback_passed"] is False
assert data["summary"]["wazuh_iwooos_live_route_readback_passed"] is False
assert data["summary"]["wazuh_dashboard_agent_list_recovered"] is False
assert data["summary"]["wazuh_agent_visibility_runtime_gate_count"] == 0
assert data["summary"]["wazuh_runtime_gate_count"] == 0
assert data["memory_write_authorized"] is False
assert data["runtime_execution_authorized"] is False
assert data["wazuh_handoff"]["wazuh_api_live_query_authorized"] is False
assert data["wazuh_handoff"]["base_commit"] == "b540fc0c"
assert data["wazuh_handoff"]["patch_count"] == 7
assert data["wazuh_handoff"]["live_metadata_owner_count"] == 0
assert data["wazuh_handoff"]["wazuh_live_agent_registry_readback"] == 0
assert data["wazuh_handoff"]["active_response"] == 0
assert data["wazuh_handoff"]["agent_visibility_status"] == "blocked_waiting_manager_agent_registry_readback"
assert data["wazuh_handoff"]["manager_agent_registry_readback_passed"] is False
assert "base=b540fc0c" in data["wazuh_handoff"]["boundary"]
assert "release_lane_preflight=ready0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0" in data["wazuh_handoff"]["boundary"]
assert "owner_gate=request_sent0_response_accepted0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0" in data["wazuh_handoff"]["boundary"]
assert "live_metadata_env_gate=owner0_secret_metadata0_push0_deploy0_readback0_runtime0" in data["wazuh_handoff"]["boundary"]
assert "wazuh_live_agent_registry_readback=0" in data["wazuh_handoff"]["boundary"]
assert "manager_agent_registry_readback_passed=false" in data["wazuh_handoff"]["boundary"]
assert {item["gate_id"] for item in data["gate_cards"]} >= {
"status_cleanup_preflight",
"owner_review_package",
"owner_response_preflight",
"execution_plan",
"apply_gate",
}
def test_awoooi_status_cleanup_dashboard_rejects_memory_write_authorization(tmp_path):
snapshot = _snapshot()
snapshot["memory_write_authorized"] = True
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="dashboard boundaries"):
load_latest_awoooi_status_cleanup_dashboard(tmp_path)
def test_awoooi_status_cleanup_dashboard_rejects_wazuh_live_query(tmp_path):
snapshot = _snapshot()
snapshot["wazuh_handoff"]["wazuh_api_live_query_authorized"] = True
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="Wazuh live query"):
load_latest_awoooi_status_cleanup_dashboard(tmp_path)
def test_awoooi_status_cleanup_dashboard_rejects_live_metadata_gate(tmp_path):
snapshot = _snapshot()
snapshot["summary"]["wazuh_live_metadata_owner_count"] = 1
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="Wazuh release summary gates"):
load_latest_awoooi_status_cleanup_dashboard(tmp_path)
def test_awoooi_status_cleanup_dashboard_rejects_missing_risk_control(tmp_path):
snapshot = _snapshot()
snapshot["risk_controls"] = [
item for item in snapshot["risk_controls"] if item["control_id"] != "host"
]
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="risk_controls"):
load_latest_awoooi_status_cleanup_dashboard(tmp_path)
def _snapshot() -> dict:
return copy.deepcopy(load_latest_awoooi_status_cleanup_dashboard())
def _write_snapshot(tmp_path, snapshot: dict) -> None:
(tmp_path / "awoooi-status-cleanup-dashboard.snapshot.json").write_text(
json.dumps(snapshot),
encoding="utf-8",
)

View File

@@ -0,0 +1,25 @@
from __future__ import annotations
from fastapi import FastAPI
from fastapi.testclient import TestClient
from src.api.v1.agents import router
def test_awoooi_status_cleanup_dashboard_endpoint_returns_snapshot():
app = FastAPI()
app.include_router(router, prefix="/api/v1")
client = TestClient(app)
response = client.get("/api/v1/agents/awoooi-status-cleanup-dashboard")
assert response.status_code == 200
data = response.json()
assert data["schema_version"] == "awoooi_status_cleanup_dashboard_v1"
assert data["summary"]["dashboard_status"] == "blocked_status_cleanup_apply_not_authorized"
assert data["summary"]["gate_count"] == 5
assert data["summary"]["apply_allowed"] is False
assert data["summary"]["memory_write_authorized"] is False
assert data["summary"]["wazuh_api_live_query_authorized"] is False
assert data["memory_write_authorized"] is False
assert data["runtime_execution_authorized"] is False

View File

@@ -329,6 +329,11 @@ export const apiClient = {
return handleResponse<AiAgentDeploymentLayoutSnapshot>(res)
},
async getAwoooIStatusCleanupDashboard() {
const res = await fetch(`${API_BASE_URL}/agents/awoooi-status-cleanup-dashboard`)
return handleResponse<AwoooIStatusCleanupDashboardSnapshot>(res)
},
async getAiAgent12AgentWarRoom() {
const res = await fetch(`${API_BASE_URL}/agents/agent-12-agent-war-room`)
return handleResponse<AiAgent12AgentWarRoomSnapshot>(res)
@@ -1349,6 +1354,43 @@ export interface AiAgentDeploymentLayoutSnapshot {
>
}
export interface AwoooIStatusCleanupDashboardSnapshot {
schema_version: 'awoooi_status_cleanup_dashboard_v1'
generated_at: string
target_route: '/workspace/status-cleanup'
summary: {
dashboard_status: string
overall_completion_percent: number
gate_count: number
blocked_gate_count: number
accepted_owner_flag_count: number
required_owner_flag_count: number
apply_allowed: false
memory_write_authorized: false
wazuh_api_live_query_authorized: false
runtime_execution_authorized: false
ui_implementation_allowed: false
[key: string]: unknown
}
metric_cards: Array<Record<string, unknown>>
gate_cards: Array<Record<string, unknown>>
workflow_rows: Array<Record<string, unknown>>
risk_controls: Array<Record<string, unknown>>
blocking_reasons: string[]
next_actions: string[]
wazuh_handoff: Record<string, unknown>
hard_gates: string[]
operation_boundaries: Record<string, false>
secret_values_collected: false
remote_write_performed: false
local_product_write_performed: false
execution_authorized: false
memory_write_authorized: false
wazuh_api_live_query_authorized: false
runtime_execution_authorized: false
ui_implementation_authorized: false
}
export interface AiAgent12AgentWarRoomSnapshot {
schema_version: 'ai_agent_12_agent_war_room_v1'
generated_at: string

View File

@@ -1,3 +1,20 @@
## 2026-06-24Status Cleanup Dashboard 繁中化與 read-only API 切片
**本輪收斂範圍:**
- 新增 AWOOOI Status Cleanup Dashboard read-only service / schema / snapshot / Markdown / generator將狀態清理完成度、owner gate、apply gate、artifact sync 與 Wazuh handoff 邊界整理成單一資料模型。
- 人類可讀標題、卡片 caption、Markdown 區塊標題與 risk control 顯示文字使用繁體中文;保留 `metric_id``gate_id`、API status、schema key 等技術識別碼。
- 修正 Wazuh visibility boundary`manager_agent_registry_readback_passed=false``iwooos_live_route_readback_passed=false``dashboard_agent_list_recovered=false``agent_visibility_runtime_gate_count=0` 寫入 boundary讓 read-model guard、報告文字與 API payload 對齊。
- 新增 `GET /api/v1/agents/awoooi-status-cleanup-dashboard``getAwoooIStatusCleanupDashboard()`;端點回傳前會走既有 public LAN topology redaction。
**readback**
- Status Cleanup Dashboard`AWOOOI_STATUS_CLEANUP_DASHBOARD_OK status=blocked_status_cleanup_apply_not_authorized gates=5/5 owner_flags=0/6 apply_allowed=False memory_write=False`
- API / read-model tests`PYTHONPATH=apps/api PYTHONDONTWRITEBYTECODE=1 apps/api/.venv/bin/python -m pytest apps/api/tests/test_awoooi_status_cleanup_dashboard.py apps/api/tests/test_awoooi_status_cleanup_dashboard_api.py -q``6 passed`
**仍禁止 / 未完成:**
- 整體治理完成度維持 `41.9%`Status Cleanup 仍 `gates=5/5 blocked``owner_flags=0/6``apply_allowed=false``memory_write_authorized=false`
- 本輪沒有更新 `project_current_status` / memory沒有 Wazuh live query / active response / runtime deploy沒有 host、Nginx、Docker、K8s、firewall、workflow、repo refs、backup、restore 或 migration 操作。
- 本輪只交付 read-only API / client / report model未宣稱可視 UI 已恢復或正式展示完成。
## 2026-06-2423:15 110 cold-start monitor live-sync gate readback
**背景**23:04 已把 MOMO source absence classifier 納入 repo-side cold-start v1.42,但這不等於 110 上 `/home/wooo/scripts/full-stack-cold-start-check.sh` 已更新。為避免下次重啟時 operator 以 live 110 舊腳本輸出做錯判,本輪只做部署 parity 的 read-only 驗證與 SOP gate 補強。

View File

@@ -0,0 +1,121 @@
# AWOOOI 狀態清理儀表板
- generated_at: `2026-06-24T15:39:52+00:00`
- dashboard_status: `blocked_status_cleanup_apply_not_authorized`
- overall_completion_percent: `41.9%`
- gates: `5/5 blocked`
- owner_flags: `0/6`
- sections: `0/7`
- confirmed_commands: `0/1`
- artifact_count: `47`
- wazuh_handoff: `blocked_not_released base=b540fc0c patches=7`
- wazuh_live_metadata: `owner=0 secret_metadata=0`
- wazuh_live_agent_registry_readback: `0`
- iwooos_wazuh_runtime_gate: `0`
- wazuh_active_response_count: `0`
- wazuh_agent_visibility_status: `blocked_waiting_manager_agent_registry_readback`
- memory_write_authorized: `False`
- runtime_execution_authorized: `False`
- wazuh_api_live_query_authorized: `False`
## 指標卡片
| 指標 | 數值 | 狀態 | 說明 |
|--------|-------|--------|---------|
| `overall_completion` | `41.9%` | `orange` | 產品 Runtime 治理完成度計分卡 |
| `project_status_age` | `11 days` | `blocked` | stale_after_days=2 |
| `owner_flags` | `0/6` | `blocked` | pending_owner_response |
| `approved_sections` | `0/7` | `blocked` | targets=0/1 |
| `execution_preview` | `blocked_owner_response_preflight_not_ready` | `blocked` | dry_run_only=true |
| `apply_confirmation` | `0/1` | `blocked` | pending_final_confirmation |
| `artifact_sync` | `1/2` | `blocked` | artifacts=47 |
## 閘門卡片
| 閘門 | 狀態 | 是否封鎖 | 證據 |
|------|------|----------|------|
| `status_cleanup_preflight` | `blocked_status_cleanup_required` | `True` | `docs/operations/codex-status-cleanup-preflight.snapshot.json` |
| `owner_review_package` | `owner_decision_required` | `True` | `docs/operations/codex-status-cleanup-owner-review-package.snapshot.json` |
| `owner_response_preflight` | `blocked_owner_response_required` | `True` | `docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json` |
| `execution_plan` | `blocked_owner_response_preflight_not_ready` | `True` | `docs/operations/codex-status-cleanup-execution-plan.snapshot.json` |
| `apply_gate` | `blocked_status_cleanup_apply_not_authorized` | `True` | `docs/operations/codex-status-cleanup-apply-gate.snapshot.json` |
## 風險控制
| 控制項 | 狀態 | 已授權 |
|--------|------|--------|
| `memory_write` | `blocked_final_apply_gate_required` | `False` |
| `raw_codex_history` | `blocked_raw_history_never_synced` | `False` |
| `wazuh_runtime` | `blocked_iwooos_runtime_lane_only` | `False` |
| `workflow` | `blocked_workflow_authorization_required` | `False` |
| `repo_refs` | `blocked_source_control_approval_required` | `False` |
| `host` | `blocked_host_maintenance_required` | `False` |
| `backup_restore` | `blocked_data_owner_approval_required` | `False` |
| `ui` | `blocked_apps_web_readiness_required` | `False` |
## 下一步
- 收齊 owner 旗標0/6。
- 收齊已批准章節0/7。
- 確認目標路徑0/1。
- 確認邊界 acknowledgement0/5。
- owner response preflight ready 後,重新產生 dry-run execution plan。
- apply gate 目前 apply_allowed=False未變 true 前不得寫 project_current_status。
## 封鎖原因
- `project_current_status 過期只代表需要狀態清理,不代表可修改 memory / runtime。`
- `不得把一般『批准繼續』解讀成 force push、workflow copy、workflow trigger、repo creation 或 refs sync 授權。`
- `不得同步 raw Codex App DB / auth / conversations / sessions。`
- `不得碰 MacBook Pro MOMO PRO protected legacy paths。`
- `不得新增 Wazuh / Kali / SOC runtime UI/API 或 live query。`
- `不得 SSH 修改主機、改 firewall / Nginx / Docker / K8s 或執行 active scan。`
- `Data / Backup coverage 是治理 evidence不是 backup / restore / migration executor。`
- `owner_response_preflight:owner_response_status_not_approved_status_cleanup_preview`
- `owner_response_preflight:owner_flag_not_accepted:accept_status_cleanup_scope`
- `owner_response_preflight:owner_flag_not_accepted:approve_project_current_status_update_preview`
- `owner_response_preflight:owner_flag_not_accepted:confirm_latest_logbook_and_scorecard_as_sources`
- `owner_response_preflight:owner_flag_not_accepted:confirm_no_runtime_or_host_authorization`
- `owner_response_preflight:owner_flag_not_accepted:confirm_no_raw_codex_history_sync`
- `owner_response_preflight:owner_flag_not_accepted:confirm_iwooos_wazuh_boundary_preserved`
- `owner_response_preflight:update_section_not_approved:artifact_sync_gate`
- `owner_response_preflight:update_section_not_approved:completion_scorecard`
- `owner_response_preflight:update_section_not_approved:data_backup_gate`
- `owner_response_preflight:update_section_not_approved:gitea_warning_gate`
- `owner_response_preflight:update_section_not_approved:iwooos_wazuh_boundary`
- `owner_response_preflight:update_section_not_approved:latest_logbook_heading`
- `owner_response_preflight:update_section_not_approved:operation_boundaries`
- `owner_response_preflight:target_path_not_approved:/Users/ogt/.claude/projects/-Users-ogt-awoooi/memory/project_current_status.md`
- `owner_response_preflight:boundary_not_acknowledged:memory_write_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:refs_sync_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:repo_creation_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:runtime_execution_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:wazuh_api_live_query_authorized=false`
- `execution_plan_blocked_until:owner response preflight ready_for_status_cleanup_apply_gate=true`
- `execution_plan_blocked_until:all owner flags accepted`
- `execution_plan_blocked_until:all update sections approved`
- `execution_plan_blocked_until:target path approved`
- `execution_plan_blocked_until:all critical false boundaries acknowledged`
- `execution_plan_blocked_until:final status cleanup apply confirmation accepted`
- `apply_gate:execution_plan_not_ready_for_final_confirmation`
- `apply_gate:owner_response_preflight_not_ready`
- `apply_gate:final_confirmation_status_not_approved_status_cleanup_apply`
- `apply_gate:final_flag_not_accepted:confirm_status_cleanup_command_preview`
- `apply_gate:final_flag_not_accepted:confirm_project_current_status_target_path`
- `apply_gate:final_flag_not_accepted:confirm_post_apply_validation`
- `apply_gate:final_flag_not_accepted:confirm_no_runtime_or_wazuh_deploy`
- `apply_gate:command_preview_not_confirmed`
- `apply_gate:target_path_not_confirmed:/Users/ogt/.claude/projects/-Users-ogt-awoooi/memory/project_current_status.md`
- `wazuh_boundary:Wazuh route / production 404 由另一受控 branch 處理branch=codex/iwooos-wazuh-boundary-guard-20260624 base=b540fc0c commits=38dc3c2f,9a53d3e1,e9972d47,758d419e,04db4b8a,8eec298e,325f262a patch_sha_1=08f8b36d7261b0dde6bfb0c47597bd0727d578dec3335c5ff7ded2bcaa2b7eb4 patch_sha_2=e6ec8f8d10e8a2bd711c399fa14ba0ab2dfb22f8ab6a733402944302eec7da7c patch_sha_3=7e99bd5284a25519313aea05bb314d3386454b91ce86241424385752d358900d patch_sha_4=f4ffbaecd94d3696660766cc6f4a6bd195762bc533d9502f8edfed2bb8379fab patch_sha_5=9035d6c411bf86d0857970b69dd33631f052aa90de27e52d82d448d4b8e4cec5 patch_sha_6=d3bb98711a3ebf91b9936b41bc232b689befc68a4a7cec38bf9cab4c8d015827 patch_sha_7=5aa3e69fee9624d0ff3f2bfad90595a81eb9306ad6387d640690a85a2f8038d7 apply_proof=release_apply_check_20260624_2248 release_gate=source1_push0_deploy0_readback0_runtime0 release_lane_preflight=ready0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 owner_gate=request_sent0_response_accepted0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 live_metadata_env_gate=owner0_secret_metadata0_push0_deploy0_readback0_runtime0wazuh_live_agent_registry_readback=0 manager_agent_registry_readback_passed=false iwooos_live_route_readback_passed=false dashboard_agent_list_recovered=false iwooos_wazuh_runtime_gate=0 active_response=0push_blocked=missing_noninteractive_gitea_https_credential本視窗不改 runtime / Nginx / Docker / K8s / firewall / Wazuh secret。 agent_visibility_status=blocked_waiting_manager_agent_registry_readback agent_visibility_runtime_gate_count=0`
## 強制閘門
- 本 dashboard 只整合 read-only snapshots不代表 project_current_status / memory 已更新。
- memory_write_authorized=false 時不得修改 project_current_status 或任何 Memory 檔案。
- 不得同步 raw Codex App DB / auth / conversations / sessions。
- 不得把一般批准繼續視為 owner response 或 final apply confirmation。
- 不得新增 Wazuh / Kali / SOC runtime UI/API、live query、active response 或 host containment。
- 不得修改 Nginx / Docker / K8s / firewall / Wazuh secret也不得重啟 host。
- 不得修改 .gitea/workflows、workflow_dispatch、repo refs、GitHub mirror 或 Gitea environment。
- 不得執行 backup、restore、migration、kubectl、docker compose up 或資料庫寫入。
- apps/web build/i18n 必要檔案未恢復前,本 dashboard 只可作 page model 資料,不代表 UI 實作授權。

View File

@@ -0,0 +1,121 @@
# AWOOOI 狀態清理儀表板
- generated_at: `2026-06-24T15:39:52+00:00`
- dashboard_status: `blocked_status_cleanup_apply_not_authorized`
- overall_completion_percent: `41.9%`
- gates: `5/5 blocked`
- owner_flags: `0/6`
- sections: `0/7`
- confirmed_commands: `0/1`
- artifact_count: `47`
- wazuh_handoff: `blocked_not_released base=b540fc0c patches=7`
- wazuh_live_metadata: `owner=0 secret_metadata=0`
- wazuh_live_agent_registry_readback: `0`
- iwooos_wazuh_runtime_gate: `0`
- wazuh_active_response_count: `0`
- wazuh_agent_visibility_status: `blocked_waiting_manager_agent_registry_readback`
- memory_write_authorized: `False`
- runtime_execution_authorized: `False`
- wazuh_api_live_query_authorized: `False`
## 指標卡片
| 指標 | 數值 | 狀態 | 說明 |
|--------|-------|--------|---------|
| `overall_completion` | `41.9%` | `orange` | 產品 Runtime 治理完成度計分卡 |
| `project_status_age` | `11 days` | `blocked` | stale_after_days=2 |
| `owner_flags` | `0/6` | `blocked` | pending_owner_response |
| `approved_sections` | `0/7` | `blocked` | targets=0/1 |
| `execution_preview` | `blocked_owner_response_preflight_not_ready` | `blocked` | dry_run_only=true |
| `apply_confirmation` | `0/1` | `blocked` | pending_final_confirmation |
| `artifact_sync` | `1/2` | `blocked` | artifacts=47 |
## 閘門卡片
| 閘門 | 狀態 | 是否封鎖 | 證據 |
|------|------|----------|------|
| `status_cleanup_preflight` | `blocked_status_cleanup_required` | `True` | `docs/operations/codex-status-cleanup-preflight.snapshot.json` |
| `owner_review_package` | `owner_decision_required` | `True` | `docs/operations/codex-status-cleanup-owner-review-package.snapshot.json` |
| `owner_response_preflight` | `blocked_owner_response_required` | `True` | `docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json` |
| `execution_plan` | `blocked_owner_response_preflight_not_ready` | `True` | `docs/operations/codex-status-cleanup-execution-plan.snapshot.json` |
| `apply_gate` | `blocked_status_cleanup_apply_not_authorized` | `True` | `docs/operations/codex-status-cleanup-apply-gate.snapshot.json` |
## 風險控制
| 控制項 | 狀態 | 已授權 |
|--------|------|--------|
| `memory_write` | `blocked_final_apply_gate_required` | `False` |
| `raw_codex_history` | `blocked_raw_history_never_synced` | `False` |
| `wazuh_runtime` | `blocked_iwooos_runtime_lane_only` | `False` |
| `workflow` | `blocked_workflow_authorization_required` | `False` |
| `repo_refs` | `blocked_source_control_approval_required` | `False` |
| `host` | `blocked_host_maintenance_required` | `False` |
| `backup_restore` | `blocked_data_owner_approval_required` | `False` |
| `ui` | `blocked_apps_web_readiness_required` | `False` |
## 下一步
- 收齊 owner 旗標0/6。
- 收齊已批准章節0/7。
- 確認目標路徑0/1。
- 確認邊界 acknowledgement0/5。
- owner response preflight ready 後,重新產生 dry-run execution plan。
- apply gate 目前 apply_allowed=False未變 true 前不得寫 project_current_status。
## 封鎖原因
- `project_current_status 過期只代表需要狀態清理,不代表可修改 memory / runtime。`
- `不得把一般『批准繼續』解讀成 force push、workflow copy、workflow trigger、repo creation 或 refs sync 授權。`
- `不得同步 raw Codex App DB / auth / conversations / sessions。`
- `不得碰 MacBook Pro MOMO PRO protected legacy paths。`
- `不得新增 Wazuh / Kali / SOC runtime UI/API 或 live query。`
- `不得 SSH 修改主機、改 firewall / Nginx / Docker / K8s 或執行 active scan。`
- `Data / Backup coverage 是治理 evidence不是 backup / restore / migration executor。`
- `owner_response_preflight:owner_response_status_not_approved_status_cleanup_preview`
- `owner_response_preflight:owner_flag_not_accepted:accept_status_cleanup_scope`
- `owner_response_preflight:owner_flag_not_accepted:approve_project_current_status_update_preview`
- `owner_response_preflight:owner_flag_not_accepted:confirm_latest_logbook_and_scorecard_as_sources`
- `owner_response_preflight:owner_flag_not_accepted:confirm_no_runtime_or_host_authorization`
- `owner_response_preflight:owner_flag_not_accepted:confirm_no_raw_codex_history_sync`
- `owner_response_preflight:owner_flag_not_accepted:confirm_iwooos_wazuh_boundary_preserved`
- `owner_response_preflight:update_section_not_approved:artifact_sync_gate`
- `owner_response_preflight:update_section_not_approved:completion_scorecard`
- `owner_response_preflight:update_section_not_approved:data_backup_gate`
- `owner_response_preflight:update_section_not_approved:gitea_warning_gate`
- `owner_response_preflight:update_section_not_approved:iwooos_wazuh_boundary`
- `owner_response_preflight:update_section_not_approved:latest_logbook_heading`
- `owner_response_preflight:update_section_not_approved:operation_boundaries`
- `owner_response_preflight:target_path_not_approved:/Users/ogt/.claude/projects/-Users-ogt-awoooi/memory/project_current_status.md`
- `owner_response_preflight:boundary_not_acknowledged:memory_write_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:refs_sync_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:repo_creation_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:runtime_execution_authorized=false`
- `owner_response_preflight:boundary_not_acknowledged:wazuh_api_live_query_authorized=false`
- `execution_plan_blocked_until:owner response preflight ready_for_status_cleanup_apply_gate=true`
- `execution_plan_blocked_until:all owner flags accepted`
- `execution_plan_blocked_until:all update sections approved`
- `execution_plan_blocked_until:target path approved`
- `execution_plan_blocked_until:all critical false boundaries acknowledged`
- `execution_plan_blocked_until:final status cleanup apply confirmation accepted`
- `apply_gate:execution_plan_not_ready_for_final_confirmation`
- `apply_gate:owner_response_preflight_not_ready`
- `apply_gate:final_confirmation_status_not_approved_status_cleanup_apply`
- `apply_gate:final_flag_not_accepted:confirm_status_cleanup_command_preview`
- `apply_gate:final_flag_not_accepted:confirm_project_current_status_target_path`
- `apply_gate:final_flag_not_accepted:confirm_post_apply_validation`
- `apply_gate:final_flag_not_accepted:confirm_no_runtime_or_wazuh_deploy`
- `apply_gate:command_preview_not_confirmed`
- `apply_gate:target_path_not_confirmed:/Users/ogt/.claude/projects/-Users-ogt-awoooi/memory/project_current_status.md`
- `wazuh_boundary:Wazuh route / production 404 由另一受控 branch 處理branch=codex/iwooos-wazuh-boundary-guard-20260624 base=b540fc0c commits=38dc3c2f,9a53d3e1,e9972d47,758d419e,04db4b8a,8eec298e,325f262a patch_sha_1=08f8b36d7261b0dde6bfb0c47597bd0727d578dec3335c5ff7ded2bcaa2b7eb4 patch_sha_2=e6ec8f8d10e8a2bd711c399fa14ba0ab2dfb22f8ab6a733402944302eec7da7c patch_sha_3=7e99bd5284a25519313aea05bb314d3386454b91ce86241424385752d358900d patch_sha_4=f4ffbaecd94d3696660766cc6f4a6bd195762bc533d9502f8edfed2bb8379fab patch_sha_5=9035d6c411bf86d0857970b69dd33631f052aa90de27e52d82d448d4b8e4cec5 patch_sha_6=d3bb98711a3ebf91b9936b41bc232b689befc68a4a7cec38bf9cab4c8d015827 patch_sha_7=5aa3e69fee9624d0ff3f2bfad90595a81eb9306ad6387d640690a85a2f8038d7 apply_proof=release_apply_check_20260624_2248 release_gate=source1_push0_deploy0_readback0_runtime0 release_lane_preflight=ready0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 owner_gate=request_sent0_response_accepted0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 live_metadata_env_gate=owner0_secret_metadata0_push0_deploy0_readback0_runtime0wazuh_live_agent_registry_readback=0 manager_agent_registry_readback_passed=false iwooos_live_route_readback_passed=false dashboard_agent_list_recovered=false iwooos_wazuh_runtime_gate=0 active_response=0push_blocked=missing_noninteractive_gitea_https_credential本視窗不改 runtime / Nginx / Docker / K8s / firewall / Wazuh secret。 agent_visibility_status=blocked_waiting_manager_agent_registry_readback agent_visibility_runtime_gate_count=0`
## 強制閘門
- 本 dashboard 只整合 read-only snapshots不代表 project_current_status / memory 已更新。
- memory_write_authorized=false 時不得修改 project_current_status 或任何 Memory 檔案。
- 不得同步 raw Codex App DB / auth / conversations / sessions。
- 不得把一般批准繼續視為 owner response 或 final apply confirmation。
- 不得新增 Wazuh / Kali / SOC runtime UI/API、live query、active response 或 host containment。
- 不得修改 Nginx / Docker / K8s / firewall / Wazuh secret也不得重啟 host。
- 不得修改 .gitea/workflows、workflow_dispatch、repo refs、GitHub mirror 或 Gitea environment。
- 不得執行 backup、restore、migration、kubectl、docker compose up 或資料庫寫入。
- apps/web build/i18n 必要檔案未恢復前,本 dashboard 只可作 page model 資料,不代表 UI 實作授權。

View File

@@ -0,0 +1,399 @@
{
"schema_version": "awoooi_status_cleanup_dashboard_v1",
"generated_at": "2026-06-24T15:39:52+00:00",
"target_route": "/workspace/status-cleanup",
"source_reviews": {
"status_cleanup_preflight": "docs/operations/codex-status-cleanup-preflight.snapshot.json",
"owner_review_package": "docs/operations/codex-status-cleanup-owner-review-package.snapshot.json",
"owner_response_preflight": "docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json",
"execution_plan": "docs/operations/codex-status-cleanup-execution-plan.snapshot.json",
"apply_gate": "docs/operations/codex-status-cleanup-apply-gate.snapshot.json",
"artifact_sync_readback": "docs/operations/codex-workstation-artifact-sync-readback.snapshot.json",
"scorecard": "docs/operations/product-runtime-governance-completion-scorecard.snapshot.json",
"iwooos_wazuh_release_handoff": "docs/operations/iwooos-wazuh-release-handoff.snapshot.json"
},
"summary": {
"dashboard_status": "blocked_status_cleanup_apply_not_authorized",
"overall_completion_percent": 41.9,
"p0_009_completion_percent": 87,
"p0_010_completion_percent": 50,
"p1_006_completion_percent": 83,
"p2_001_completion_percent": 41,
"p2_002_completion_percent": 72,
"gate_count": 5,
"blocked_gate_count": 5,
"project_current_status_age_days": 11,
"cleanup_required": true,
"accepted_owner_flag_count": 0,
"required_owner_flag_count": 6,
"approved_update_section_count": 0,
"required_update_section_count": 7,
"approved_target_path_count": 0,
"target_path_count": 1,
"boundary_ack_count": 0,
"required_boundary_ack_count": 5,
"execution_plan_status": "blocked_owner_response_preflight_not_ready",
"apply_gate_status": "blocked_status_cleanup_apply_not_authorized",
"confirmed_command_count": 0,
"planned_command_count": 1,
"artifact_count": 47,
"artifact_sync_blocked_count": 1,
"wazuh_handoff_status": "blocked_not_released",
"wazuh_handoff_base_commit": "b540fc0c",
"wazuh_handoff_commit_count": 7,
"wazuh_handoff_patch_count": 7,
"wazuh_release_owner_request_sent_count": 0,
"wazuh_release_owner_response_accepted_count": 0,
"wazuh_acknowledged_release_owner_ack_count": 0,
"wazuh_required_release_owner_ack_count": 6,
"wazuh_accepted_evidence_count": 0,
"wazuh_required_evidence_count": 6,
"wazuh_live_metadata_owner_count": 0,
"wazuh_secret_metadata_count": 0,
"wazuh_live_agent_registry_readback": 0,
"iwooos_wazuh_runtime_gate": 0,
"wazuh_active_response_count": 0,
"wazuh_agent_visibility_status": "blocked_waiting_manager_agent_registry_readback",
"wazuh_manager_agent_registry_readback_passed": false,
"wazuh_iwooos_live_route_readback_passed": false,
"wazuh_dashboard_agent_list_recovered": false,
"wazuh_agent_visibility_runtime_gate_count": 0,
"wazuh_push_gate_count": 0,
"wazuh_deploy_gate_count": 0,
"wazuh_readback_gate_count": 0,
"wazuh_runtime_gate_count": 0,
"blocking_reason_count": 43,
"next_action_count": 6,
"apply_allowed": false,
"memory_write_authorized": false,
"wazuh_api_live_query_authorized": false,
"runtime_execution_authorized": false,
"ui_implementation_allowed": false
},
"metric_cards": [
{
"metric_id": "overall_completion",
"title": "整體治理完成度",
"value": "41.9%",
"status": "orange",
"caption": "產品 Runtime 治理完成度計分卡"
},
{
"metric_id": "project_status_age",
"title": "project_current_status 年齡",
"value": "11 days",
"status": "blocked",
"caption": "stale_after_days=2"
},
{
"metric_id": "owner_flags",
"title": "Owner 旗標",
"value": "0/6",
"status": "blocked",
"caption": "pending_owner_response"
},
{
"metric_id": "approved_sections",
"title": "已批准章節",
"value": "0/7",
"status": "blocked",
"caption": "targets=0/1"
},
{
"metric_id": "execution_preview",
"title": "執行預覽",
"value": "blocked_owner_response_preflight_not_ready",
"status": "blocked",
"caption": "dry_run_only=true"
},
{
"metric_id": "apply_confirmation",
"title": "套用確認",
"value": "0/1",
"status": "blocked",
"caption": "pending_final_confirmation"
},
{
"metric_id": "artifact_sync",
"title": "安全交接 artifacts",
"value": "1/2",
"status": "blocked",
"caption": "artifacts=47"
}
],
"gate_cards": [
{
"gate_id": "status_cleanup_preflight",
"title": "狀態清理預檢",
"status": "blocked_status_cleanup_required",
"completion_label": "age_days=11 stale_after=2",
"evidence_ref": "docs/operations/codex-status-cleanup-preflight.snapshot.json",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"gate_id": "owner_review_package",
"title": "Owner 審核包",
"status": "owner_decision_required",
"completion_label": "7 sections / 6 owner flags",
"evidence_ref": "docs/operations/codex-status-cleanup-owner-review-package.snapshot.json",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"gate_id": "owner_response_preflight",
"title": "Owner 回覆預檢",
"status": "blocked_owner_response_required",
"completion_label": "0/6 flags, 0/7 sections",
"evidence_ref": "docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"gate_id": "execution_plan",
"title": "Dry-run 執行計畫",
"status": "blocked_owner_response_preflight_not_ready",
"completion_label": "0/7 sections, 0/1 targets",
"evidence_ref": "docs/operations/codex-status-cleanup-execution-plan.snapshot.json",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"gate_id": "apply_gate",
"title": "最終套用閘門",
"status": "blocked_status_cleanup_apply_not_authorized",
"completion_label": "0/1 commands, 0/1 targets",
"evidence_ref": "docs/operations/codex-status-cleanup-apply-gate.snapshot.json",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
}
],
"workflow_rows": [
{
"step_id": "status_cleanup_preflight",
"title": "狀態清理預檢",
"status": "blocked_status_cleanup_required",
"evidence_ref": "docs/operations/codex-status-cleanup-preflight.snapshot.json",
"next_step": "owner_review_package",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"step_id": "owner_review_package",
"title": "Owner 審核包",
"status": "owner_decision_required",
"evidence_ref": "docs/operations/codex-status-cleanup-owner-review-package.snapshot.json",
"next_step": "owner_response_preflight",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"step_id": "owner_response_preflight",
"title": "Owner 回覆預檢",
"status": "blocked_owner_response_required",
"evidence_ref": "docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json",
"next_step": "execution_plan",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"step_id": "execution_plan",
"title": "Dry-run 執行計畫",
"status": "blocked_owner_response_preflight_not_ready",
"evidence_ref": "docs/operations/codex-status-cleanup-execution-plan.snapshot.json",
"next_step": "apply_gate",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
},
{
"step_id": "apply_gate",
"title": "最終套用閘門",
"status": "blocked_status_cleanup_apply_not_authorized",
"evidence_ref": "docs/operations/codex-status-cleanup-apply-gate.snapshot.json",
"next_step": "manual_project_current_status_update_after_explicit_final_confirmation",
"blocked": true,
"memory_write_authorized": false,
"execution_authorized": false
}
],
"risk_controls": [
{
"control_id": "memory_write",
"title": "更新 project_current_status / memory",
"status": "blocked_final_apply_gate_required",
"authorized": false
},
{
"control_id": "raw_codex_history",
"title": "同步 raw Codex App history",
"status": "blocked_raw_history_never_synced",
"authorized": false
},
{
"control_id": "wazuh_runtime",
"title": "部署或查詢 live Wazuh runtime",
"status": "blocked_iwooos_runtime_lane_only",
"authorized": false
},
{
"control_id": "workflow",
"title": "修改或觸發 CI/CD workflow",
"status": "blocked_workflow_authorization_required",
"authorized": false
},
{
"control_id": "repo_refs",
"title": "建立 repo / branch / mirror refs",
"status": "blocked_source_control_approval_required",
"authorized": false
},
{
"control_id": "host",
"title": "SSH / restart / firewall / Nginx / Docker / K8s",
"status": "blocked_host_maintenance_required",
"authorized": false
},
{
"control_id": "backup_restore",
"title": "執行 backup / restore / migration",
"status": "blocked_data_owner_approval_required",
"authorized": false
},
{
"control_id": "ui",
"title": "實作可見 AWOOOI UI",
"status": "blocked_apps_web_readiness_required",
"authorized": false
}
],
"blocking_reasons": [
"project_current_status 過期只代表需要狀態清理,不代表可修改 memory / runtime。",
"不得把一般『批准繼續』解讀成 force push、workflow copy、workflow trigger、repo creation 或 refs sync 授權。",
"不得同步 raw Codex App DB / auth / conversations / sessions。",
"不得碰 MacBook Pro MOMO PRO protected legacy paths。",
"不得新增 Wazuh / Kali / SOC runtime UI/API 或 live query。",
"不得 SSH 修改主機、改 firewall / Nginx / Docker / K8s 或執行 active scan。",
"Data / Backup coverage 是治理 evidence不是 backup / restore / migration executor。",
"owner_response_preflight:owner_response_status_not_approved_status_cleanup_preview",
"owner_response_preflight:owner_flag_not_accepted:accept_status_cleanup_scope",
"owner_response_preflight:owner_flag_not_accepted:approve_project_current_status_update_preview",
"owner_response_preflight:owner_flag_not_accepted:confirm_latest_logbook_and_scorecard_as_sources",
"owner_response_preflight:owner_flag_not_accepted:confirm_no_runtime_or_host_authorization",
"owner_response_preflight:owner_flag_not_accepted:confirm_no_raw_codex_history_sync",
"owner_response_preflight:owner_flag_not_accepted:confirm_iwooos_wazuh_boundary_preserved",
"owner_response_preflight:update_section_not_approved:artifact_sync_gate",
"owner_response_preflight:update_section_not_approved:completion_scorecard",
"owner_response_preflight:update_section_not_approved:data_backup_gate",
"owner_response_preflight:update_section_not_approved:gitea_warning_gate",
"owner_response_preflight:update_section_not_approved:iwooos_wazuh_boundary",
"owner_response_preflight:update_section_not_approved:latest_logbook_heading",
"owner_response_preflight:update_section_not_approved:operation_boundaries",
"owner_response_preflight:target_path_not_approved:/Users/ogt/.claude/projects/-Users-ogt-awoooi/memory/project_current_status.md",
"owner_response_preflight:boundary_not_acknowledged:memory_write_authorized=false",
"owner_response_preflight:boundary_not_acknowledged:refs_sync_authorized=false",
"owner_response_preflight:boundary_not_acknowledged:repo_creation_authorized=false",
"owner_response_preflight:boundary_not_acknowledged:runtime_execution_authorized=false",
"owner_response_preflight:boundary_not_acknowledged:wazuh_api_live_query_authorized=false",
"execution_plan_blocked_until:owner response preflight ready_for_status_cleanup_apply_gate=true",
"execution_plan_blocked_until:all owner flags accepted",
"execution_plan_blocked_until:all update sections approved",
"execution_plan_blocked_until:target path approved",
"execution_plan_blocked_until:all critical false boundaries acknowledged",
"execution_plan_blocked_until:final status cleanup apply confirmation accepted",
"apply_gate:execution_plan_not_ready_for_final_confirmation",
"apply_gate:owner_response_preflight_not_ready",
"apply_gate:final_confirmation_status_not_approved_status_cleanup_apply",
"apply_gate:final_flag_not_accepted:confirm_status_cleanup_command_preview",
"apply_gate:final_flag_not_accepted:confirm_project_current_status_target_path",
"apply_gate:final_flag_not_accepted:confirm_post_apply_validation",
"apply_gate:final_flag_not_accepted:confirm_no_runtime_or_wazuh_deploy",
"apply_gate:command_preview_not_confirmed",
"apply_gate:target_path_not_confirmed:/Users/ogt/.claude/projects/-Users-ogt-awoooi/memory/project_current_status.md",
"wazuh_boundary:Wazuh route / production 404 由另一受控 branch 處理branch=codex/iwooos-wazuh-boundary-guard-20260624 base=b540fc0c commits=38dc3c2f,9a53d3e1,e9972d47,758d419e,04db4b8a,8eec298e,325f262a patch_sha_1=08f8b36d7261b0dde6bfb0c47597bd0727d578dec3335c5ff7ded2bcaa2b7eb4 patch_sha_2=e6ec8f8d10e8a2bd711c399fa14ba0ab2dfb22f8ab6a733402944302eec7da7c patch_sha_3=7e99bd5284a25519313aea05bb314d3386454b91ce86241424385752d358900d patch_sha_4=f4ffbaecd94d3696660766cc6f4a6bd195762bc533d9502f8edfed2bb8379fab patch_sha_5=9035d6c411bf86d0857970b69dd33631f052aa90de27e52d82d448d4b8e4cec5 patch_sha_6=d3bb98711a3ebf91b9936b41bc232b689befc68a4a7cec38bf9cab4c8d015827 patch_sha_7=5aa3e69fee9624d0ff3f2bfad90595a81eb9306ad6387d640690a85a2f8038d7 apply_proof=release_apply_check_20260624_2248 release_gate=source1_push0_deploy0_readback0_runtime0 release_lane_preflight=ready0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 owner_gate=request_sent0_response_accepted0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 live_metadata_env_gate=owner0_secret_metadata0_push0_deploy0_readback0_runtime0wazuh_live_agent_registry_readback=0 manager_agent_registry_readback_passed=false iwooos_live_route_readback_passed=false dashboard_agent_list_recovered=false iwooos_wazuh_runtime_gate=0 active_response=0push_blocked=missing_noninteractive_gitea_https_credential本視窗不改 runtime / Nginx / Docker / K8s / firewall / Wazuh secret。 agent_visibility_status=blocked_waiting_manager_agent_registry_readback agent_visibility_runtime_gate_count=0"
],
"next_actions": [
"收齊 owner 旗標0/6。",
"收齊已批准章節0/7。",
"確認目標路徑0/1。",
"確認邊界 acknowledgement0/5。",
"owner response preflight ready 後,重新產生 dry-run execution plan。",
"apply gate 目前 apply_allowed=False未變 true 前不得寫 project_current_status。"
],
"wazuh_handoff": {
"status": "blocked_not_released",
"source_ref": "docs/operations/iwooos-wazuh-release-handoff.snapshot.json",
"branch": "codex/iwooos-wazuh-boundary-guard-20260624",
"base_commit": "b540fc0c",
"commit_count": 7,
"patch_count": 7,
"release_owner_request_sent_count": 0,
"release_owner_response_accepted_count": 0,
"acknowledged_release_owner_ack_count": 0,
"required_release_owner_ack_count": 6,
"accepted_evidence_count": 0,
"required_evidence_count": 6,
"live_metadata_owner_count": 0,
"secret_metadata_count": 0,
"wazuh_live_agent_registry_readback": 0,
"iwooos_wazuh_runtime_gate": 0,
"active_response": 0,
"stored_api_secret_metadata_changed": false,
"agent_visibility_status": "blocked_waiting_manager_agent_registry_readback",
"manager_agent_registry_readback_passed": false,
"iwooos_live_route_readback_passed": false,
"dashboard_agent_list_recovered": false,
"agent_visibility_runtime_gate_count": 0,
"push_gate_count": 0,
"deploy_gate_count": 0,
"readback_gate_count": 0,
"runtime_gate_count": 0,
"production_readback_status": "predeploy_404",
"boundary": "Wazuh route / production 404 由另一受控 branch 處理branch=codex/iwooos-wazuh-boundary-guard-20260624 base=b540fc0c commits=38dc3c2f,9a53d3e1,e9972d47,758d419e,04db4b8a,8eec298e,325f262a patch_sha_1=08f8b36d7261b0dde6bfb0c47597bd0727d578dec3335c5ff7ded2bcaa2b7eb4 patch_sha_2=e6ec8f8d10e8a2bd711c399fa14ba0ab2dfb22f8ab6a733402944302eec7da7c patch_sha_3=7e99bd5284a25519313aea05bb314d3386454b91ce86241424385752d358900d patch_sha_4=f4ffbaecd94d3696660766cc6f4a6bd195762bc533d9502f8edfed2bb8379fab patch_sha_5=9035d6c411bf86d0857970b69dd33631f052aa90de27e52d82d448d4b8e4cec5 patch_sha_6=d3bb98711a3ebf91b9936b41bc232b689befc68a4a7cec38bf9cab4c8d015827 patch_sha_7=5aa3e69fee9624d0ff3f2bfad90595a81eb9306ad6387d640690a85a2f8038d7 apply_proof=release_apply_check_20260624_2248 release_gate=source1_push0_deploy0_readback0_runtime0 release_lane_preflight=ready0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 owner_gate=request_sent0_response_accepted0_acks0of6_evidence0of6_push0_deploy0_readback0_runtime0 live_metadata_env_gate=owner0_secret_metadata0_push0_deploy0_readback0_runtime0wazuh_live_agent_registry_readback=0 manager_agent_registry_readback_passed=false iwooos_live_route_readback_passed=false dashboard_agent_list_recovered=false iwooos_wazuh_runtime_gate=0 active_response=0push_blocked=missing_noninteractive_gitea_https_credential本視窗不改 runtime / Nginx / Docker / K8s / firewall / Wazuh secret。 agent_visibility_status=blocked_waiting_manager_agent_registry_readback agent_visibility_runtime_gate_count=0",
"runtime_execution_authorized": false,
"wazuh_api_live_query_authorized": false
},
"hard_gates": [
"本 dashboard 只整合 read-only snapshots不代表 project_current_status / memory 已更新。",
"memory_write_authorized=false 時不得修改 project_current_status 或任何 Memory 檔案。",
"不得同步 raw Codex App DB / auth / conversations / sessions。",
"不得把一般批准繼續視為 owner response 或 final apply confirmation。",
"不得新增 Wazuh / Kali / SOC runtime UI/API、live query、active response 或 host containment。",
"不得修改 Nginx / Docker / K8s / firewall / Wazuh secret也不得重啟 host。",
"不得修改 .gitea/workflows、workflow_dispatch、repo refs、GitHub mirror 或 Gitea environment。",
"不得執行 backup、restore、migration、kubectl、docker compose up 或資料庫寫入。",
"apps/web build/i18n 必要檔案未恢復前,本 dashboard 只可作 page model 資料,不代表 UI 實作授權。"
],
"operation_boundaries": {
"memory_write_authorized": false,
"raw_codex_history_sync_authorized": false,
"runtime_execution_authorized": false,
"active_scan_authorized": false,
"wazuh_api_live_query_authorized": false,
"wazuh_active_response_authorized": false,
"repo_creation_authorized": false,
"refs_sync_authorized": false,
"workflow_modification_authorized": false,
"workflow_trigger_authorized": false,
"host_update_authorized": false,
"backup_execution_authorized": false,
"restore_execution_authorized": false,
"migration_authorized": false
},
"secret_values_collected": false,
"remote_write_performed": false,
"local_product_write_performed": false,
"execution_authorized": false,
"memory_write_authorized": false,
"wazuh_api_live_query_authorized": false,
"runtime_execution_authorized": false,
"ui_implementation_authorized": false
}

View File

@@ -0,0 +1,88 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "awoooi_status_cleanup_dashboard_v1",
"title": "AWOOOI 狀態清理儀表板",
"type": "object",
"required": [
"schema_version",
"generated_at",
"target_route",
"source_reviews",
"summary",
"metric_cards",
"gate_cards",
"workflow_rows",
"risk_controls",
"blocking_reasons",
"next_actions",
"wazuh_handoff",
"hard_gates",
"operation_boundaries",
"secret_values_collected",
"remote_write_performed",
"local_product_write_performed",
"execution_authorized",
"memory_write_authorized",
"wazuh_api_live_query_authorized",
"runtime_execution_authorized",
"ui_implementation_authorized"
],
"properties": {
"schema_version": {"const": "awoooi_status_cleanup_dashboard_v1"},
"generated_at": {"type": "string"},
"target_route": {"const": "/workspace/status-cleanup"},
"source_reviews": {"type": "object", "additionalProperties": {"type": "string"}},
"summary": {
"type": "object",
"required": [
"dashboard_status",
"overall_completion_percent",
"gate_count",
"blocked_gate_count",
"accepted_owner_flag_count",
"required_owner_flag_count",
"approved_update_section_count",
"required_update_section_count",
"wazuh_handoff_status",
"wazuh_handoff_base_commit",
"wazuh_handoff_commit_count",
"wazuh_handoff_patch_count",
"wazuh_live_metadata_owner_count",
"wazuh_secret_metadata_count",
"wazuh_live_agent_registry_readback",
"iwooos_wazuh_runtime_gate",
"wazuh_active_response_count",
"wazuh_agent_visibility_status",
"wazuh_manager_agent_registry_readback_passed",
"wazuh_iwooos_live_route_readback_passed",
"wazuh_dashboard_agent_list_recovered",
"wazuh_agent_visibility_runtime_gate_count",
"wazuh_runtime_gate_count",
"apply_allowed",
"memory_write_authorized",
"wazuh_api_live_query_authorized",
"runtime_execution_authorized",
"ui_implementation_allowed"
],
"additionalProperties": true
},
"metric_cards": {"type": "array", "items": {"type": "object"}},
"gate_cards": {"type": "array", "items": {"type": "object"}},
"workflow_rows": {"type": "array", "items": {"type": "object"}},
"risk_controls": {"type": "array", "items": {"type": "object"}},
"blocking_reasons": {"type": "array", "items": {"type": "string"}},
"next_actions": {"type": "array", "items": {"type": "string"}},
"wazuh_handoff": {"type": "object", "additionalProperties": true},
"hard_gates": {"type": "array", "items": {"type": "string"}},
"operation_boundaries": {"type": "object", "additionalProperties": {"const": false}},
"secret_values_collected": {"const": false},
"remote_write_performed": {"const": false},
"local_product_write_performed": {"const": false},
"execution_authorized": {"const": false},
"memory_write_authorized": {"const": false},
"wazuh_api_live_query_authorized": {"const": false},
"runtime_execution_authorized": {"const": false},
"ui_implementation_authorized": {"const": false}
},
"additionalProperties": false
}

View File

@@ -0,0 +1,608 @@
#!/usr/bin/env python3
"""產生 AWOOOI Status Cleanup dashboard。
本工具只整合 status cleanup 的 read-only snapshots提供未來 AWOOOI
Workspace / Delivery 頁面單一資料來源:
- 不修改 project_current_status / memory。
- 不同步 raw Codex App DB / auth / conversations / sessions。
- 不 fetch / pull / push。
- 不呼叫 Wazuh / Kali / SOC runtime。
- 不修改 workflow、repo、host、backup、restore 或 migration。
"""
from __future__ import annotations
import argparse
import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
TARGET_ROUTE = "/workspace/status-cleanup"
def utc_now_iso() -> str:
return datetime.now(timezone.utc).replace(microsecond=0).isoformat()
def load_json(path: Path) -> dict[str, Any]:
return json.loads(path.read_text(encoding="utf-8"))
def workplan_completion(scorecard: dict[str, Any], item_id: str) -> int:
for item in scorecard.get("workplan_items", []):
if item.get("id") == item_id:
return int(item.get("completion_percent", 0))
return 0
def unique_strings(*groups: list[str]) -> list[str]:
seen: set[str] = set()
output: list[str] = []
for group in groups:
for item in group:
text = str(item)
if text and text not in seen:
seen.add(text)
output.append(text)
return output
def status_from_boolean(ok: bool) -> str:
return "green" if ok else "blocked"
def bool_token(value: Any) -> str:
return "true" if value is True else "false"
def append_boundary_tokens(boundary: str, tokens: list[str]) -> str:
parts = [boundary.strip()] if boundary.strip() else []
parts.extend(token for token in tokens if token and token not in boundary)
return " ".join(parts)
def section_value(owner_package: dict[str, Any], section_id: str) -> str:
for item in owner_package.get("required_update_sections", []):
if item.get("section_id") == section_id:
return str(item.get("value", ""))
return ""
def gate_cards(
preflight: dict[str, Any],
owner_package: dict[str, Any],
owner_response_preflight: dict[str, Any],
execution_plan: dict[str, Any],
apply_gate: dict[str, Any],
) -> list[dict[str, Any]]:
preflight_status = preflight["status"]
owner_summary = owner_package["summary"]
response_summary = owner_response_preflight["summary"]
plan_summary = execution_plan["summary"]
apply_summary = apply_gate["summary"]
return [
{
"gate_id": "status_cleanup_preflight",
"title": "狀態清理預檢",
"status": preflight_status,
"completion_label": (
f"age_days={preflight['project_current_status']['age_days']} "
f"stale_after={preflight['project_current_status']['stale_after_days']}"
),
"evidence_ref": "docs/operations/codex-status-cleanup-preflight.snapshot.json",
"blocked": preflight_status != "ready_status_current",
"memory_write_authorized": False,
"execution_authorized": False,
},
{
"gate_id": "owner_review_package",
"title": "Owner 審核包",
"status": owner_summary["review_status"],
"completion_label": (
f"{owner_summary['required_update_section_count']} sections / "
f"{owner_summary['required_owner_flag_count']} owner flags"
),
"evidence_ref": "docs/operations/codex-status-cleanup-owner-review-package.snapshot.json",
"blocked": owner_summary["ready_for_status_cleanup_apply_gate"] is not True,
"memory_write_authorized": False,
"execution_authorized": False,
},
{
"gate_id": "owner_response_preflight",
"title": "Owner 回覆預檢",
"status": response_summary["preflight_status"],
"completion_label": (
f"{response_summary['accepted_owner_flag_count']}/"
f"{response_summary['required_owner_flag_count']} flags, "
f"{response_summary['approved_update_section_count']}/"
f"{response_summary['required_update_section_count']} sections"
),
"evidence_ref": "docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json",
"blocked": response_summary["ready_for_status_cleanup_apply_gate"] is not True,
"memory_write_authorized": False,
"execution_authorized": False,
},
{
"gate_id": "execution_plan",
"title": "Dry-run 執行計畫",
"status": plan_summary["execution_status"],
"completion_label": (
f"{plan_summary['approved_update_section_count']}/"
f"{plan_summary['required_update_section_count']} sections, "
f"{plan_summary['approved_target_path_count']}/"
f"{plan_summary['target_path_count']} targets"
),
"evidence_ref": "docs/operations/codex-status-cleanup-execution-plan.snapshot.json",
"blocked": plan_summary["execution_status"] != "blocked_final_confirmation_required",
"memory_write_authorized": False,
"execution_authorized": False,
},
{
"gate_id": "apply_gate",
"title": "最終套用閘門",
"status": apply_summary["apply_gate_status"],
"completion_label": (
f"{apply_summary['confirmed_command_count']}/"
f"{apply_summary['planned_command_count']} commands, "
f"{apply_summary['confirmed_target_path_count']}/"
f"{apply_summary['target_path_count']} targets"
),
"evidence_ref": "docs/operations/codex-status-cleanup-apply-gate.snapshot.json",
"blocked": apply_summary["apply_allowed"] is not True,
"memory_write_authorized": False,
"execution_authorized": False,
},
]
def metric_cards(
preflight: dict[str, Any],
owner_response_preflight: dict[str, Any],
execution_plan: dict[str, Any],
apply_gate: dict[str, Any],
artifact_sync: dict[str, Any],
scorecard: dict[str, Any],
) -> list[dict[str, Any]]:
project_status = preflight["project_current_status"]
response_summary = owner_response_preflight["summary"]
plan_summary = execution_plan["summary"]
apply_summary = apply_gate["summary"]
artifact_summary = artifact_sync["summary"]
return [
{
"metric_id": "overall_completion",
"title": "整體治理完成度",
"value": f"{scorecard['overall_completion_percent']}%",
"status": scorecard.get("status", "orange"),
"caption": "產品 Runtime 治理完成度計分卡",
},
{
"metric_id": "project_status_age",
"title": "project_current_status 年齡",
"value": f"{project_status['age_days']} days",
"status": status_from_boolean(project_status["cleanup_required"] is False),
"caption": f"stale_after_days={project_status['stale_after_days']}",
},
{
"metric_id": "owner_flags",
"title": "Owner 旗標",
"value": f"{response_summary['accepted_owner_flag_count']}/{response_summary['required_owner_flag_count']}",
"status": status_from_boolean(response_summary["accepted_owner_flag_count"] == response_summary["required_owner_flag_count"]),
"caption": response_summary["owner_response_status"],
},
{
"metric_id": "approved_sections",
"title": "已批准章節",
"value": f"{response_summary['approved_update_section_count']}/{response_summary['required_update_section_count']}",
"status": status_from_boolean(response_summary["approved_update_section_count"] == response_summary["required_update_section_count"]),
"caption": f"targets={response_summary['approved_target_path_count']}/{response_summary['target_path_count']}",
},
{
"metric_id": "execution_preview",
"title": "執行預覽",
"value": plan_summary["execution_status"],
"status": status_from_boolean(plan_summary["preflight_ready"]),
"caption": "dry_run_only=true",
},
{
"metric_id": "apply_confirmation",
"title": "套用確認",
"value": f"{apply_summary['confirmed_command_count']}/{apply_summary['planned_command_count']}",
"status": status_from_boolean(apply_summary["apply_allowed"]),
"caption": apply_summary["final_confirmation_status"],
},
{
"metric_id": "artifact_sync",
"title": "安全交接 artifacts",
"value": f"{artifact_summary['synced_target_count']}/{artifact_summary['target_count']}",
"status": status_from_boolean(artifact_summary["blocked_target_count"] == 0),
"caption": f"artifacts={artifact_summary['artifact_count']}",
},
]
def workflow_rows(cards: list[dict[str, Any]]) -> list[dict[str, Any]]:
next_map = {
"status_cleanup_preflight": "owner_review_package",
"owner_review_package": "owner_response_preflight",
"owner_response_preflight": "execution_plan",
"execution_plan": "apply_gate",
"apply_gate": "manual_project_current_status_update_after_explicit_final_confirmation",
}
return [
{
"step_id": card["gate_id"],
"title": card["title"],
"status": card["status"],
"evidence_ref": card["evidence_ref"],
"next_step": next_map[card["gate_id"]],
"blocked": card["blocked"],
"memory_write_authorized": False,
"execution_authorized": False,
}
for card in cards
]
def risk_controls() -> list[dict[str, Any]]:
rows = [
("memory_write", "更新 project_current_status / memory", "blocked_final_apply_gate_required"),
("raw_codex_history", "同步 raw Codex App history", "blocked_raw_history_never_synced"),
("wazuh_runtime", "部署或查詢 live Wazuh runtime", "blocked_iwooos_runtime_lane_only"),
("workflow", "修改或觸發 CI/CD workflow", "blocked_workflow_authorization_required"),
("repo_refs", "建立 repo / branch / mirror refs", "blocked_source_control_approval_required"),
("host", "SSH / restart / firewall / Nginx / Docker / K8s", "blocked_host_maintenance_required"),
("backup_restore", "執行 backup / restore / migration", "blocked_data_owner_approval_required"),
("ui", "實作可見 AWOOOI UI", "blocked_apps_web_readiness_required"),
]
return [
{
"control_id": control_id,
"title": title,
"status": status,
"authorized": False,
}
for control_id, title, status in rows
]
def next_actions(owner_response_preflight: dict[str, Any], apply_gate: dict[str, Any]) -> list[str]:
response_summary = owner_response_preflight["summary"]
apply_summary = apply_gate["summary"]
return [
f"收齊 owner 旗標:{response_summary['accepted_owner_flag_count']}/{response_summary['required_owner_flag_count']}",
f"收齊已批准章節:{response_summary['approved_update_section_count']}/{response_summary['required_update_section_count']}",
f"確認目標路徑:{response_summary['approved_target_path_count']}/{response_summary['target_path_count']}",
f"確認邊界 acknowledgement{response_summary['boundary_ack_count']}/{response_summary['required_boundary_ack_count']}",
"owner response preflight ready 後,重新產生 dry-run execution plan。",
f"apply gate 目前 apply_allowed={apply_summary['apply_allowed']};未變 true 前不得寫 project_current_status。",
]
def hard_gates() -> list[str]:
return [
"本 dashboard 只整合 read-only snapshots不代表 project_current_status / memory 已更新。",
"memory_write_authorized=false 時不得修改 project_current_status 或任何 Memory 檔案。",
"不得同步 raw Codex App DB / auth / conversations / sessions。",
"不得把一般批准繼續視為 owner response 或 final apply confirmation。",
"不得新增 Wazuh / Kali / SOC runtime UI/API、live query、active response 或 host containment。",
"不得修改 Nginx / Docker / K8s / firewall / Wazuh secret也不得重啟 host。",
"不得修改 .gitea/workflows、workflow_dispatch、repo refs、GitHub mirror 或 Gitea environment。",
"不得執行 backup、restore、migration、kubectl、docker compose up 或資料庫寫入。",
"apps/web build/i18n 必要檔案未恢復前,本 dashboard 只可作 page model 資料,不代表 UI 實作授權。",
]
def build_payload(
preflight_path: Path,
owner_package_path: Path,
owner_response_preflight_path: Path,
execution_plan_path: Path,
apply_gate_path: Path,
artifact_sync_path: Path,
scorecard_path: Path,
wazuh_handoff_path: Path,
) -> dict[str, Any]:
preflight = load_json(preflight_path)
owner_package = load_json(owner_package_path)
owner_response_preflight = load_json(owner_response_preflight_path)
execution_plan = load_json(execution_plan_path)
apply_gate = load_json(apply_gate_path)
artifact_sync = load_json(artifact_sync_path)
scorecard = load_json(scorecard_path)
wazuh_handoff = load_json(wazuh_handoff_path)
cards = gate_cards(
preflight,
owner_package,
owner_response_preflight,
execution_plan,
apply_gate,
)
response_summary = owner_response_preflight["summary"]
plan_summary = execution_plan["summary"]
apply_summary = apply_gate["summary"]
project_status = preflight["project_current_status"]
artifact_summary = artifact_sync["summary"]
wazuh_release_lane = wazuh_handoff["release_lane"]
wazuh_incident = wazuh_handoff.get("incident_sync", {})
wazuh_visibility = wazuh_handoff.get("agent_visibility_runtime_gate", {})
wazuh_boundary = append_boundary_tokens(
section_value(owner_package, "iwooos_wazuh_boundary"),
[
"agent_visibility_status="
+ str(wazuh_visibility.get("status", "blocked_waiting_manager_agent_registry_readback")),
"manager_agent_registry_readback_passed="
+ bool_token(wazuh_visibility.get("manager_agent_registry_readback_passed", False)),
"iwooos_live_route_readback_passed="
+ bool_token(wazuh_visibility.get("iwooos_live_route_readback_passed", False)),
"dashboard_agent_list_recovered="
+ bool_token(wazuh_visibility.get("dashboard_agent_list_recovered", False)),
"agent_visibility_runtime_gate_count="
+ str(wazuh_visibility.get("runtime_gate_count", 0)),
],
)
blockers = unique_strings(
preflight.get("hard_gates", []),
[f"owner_response_preflight:{item}" for item in owner_response_preflight.get("blocking_reasons", [])],
[f"execution_plan_blocked_until:{item}" for item in execution_plan.get("blocked_until", [])],
[f"apply_gate:{item}" for item in apply_gate.get("blocking_reasons", [])],
[f"wazuh_boundary:{wazuh_boundary}"] if wazuh_boundary else [],
)
actions = next_actions(owner_response_preflight, apply_gate)
metrics = metric_cards(
preflight,
owner_response_preflight,
execution_plan,
apply_gate,
artifact_sync,
scorecard,
)
return {
"schema_version": "awoooi_status_cleanup_dashboard_v1",
"generated_at": utc_now_iso(),
"target_route": TARGET_ROUTE,
"source_reviews": {
"status_cleanup_preflight": str(preflight_path),
"owner_review_package": str(owner_package_path),
"owner_response_preflight": str(owner_response_preflight_path),
"execution_plan": str(execution_plan_path),
"apply_gate": str(apply_gate_path),
"artifact_sync_readback": str(artifact_sync_path),
"scorecard": str(scorecard_path),
"iwooos_wazuh_release_handoff": str(wazuh_handoff_path),
},
"summary": {
"dashboard_status": "blocked_status_cleanup_apply_not_authorized",
"overall_completion_percent": scorecard["overall_completion_percent"],
"p0_009_completion_percent": workplan_completion(scorecard, "P0-009"),
"p0_010_completion_percent": workplan_completion(scorecard, "P0-010"),
"p1_006_completion_percent": workplan_completion(scorecard, "P1-006"),
"p2_001_completion_percent": workplan_completion(scorecard, "P2-001"),
"p2_002_completion_percent": workplan_completion(scorecard, "P2-002"),
"gate_count": len(cards),
"blocked_gate_count": sum(1 for card in cards if card["blocked"]),
"project_current_status_age_days": project_status["age_days"],
"cleanup_required": project_status["cleanup_required"],
"accepted_owner_flag_count": response_summary["accepted_owner_flag_count"],
"required_owner_flag_count": response_summary["required_owner_flag_count"],
"approved_update_section_count": response_summary["approved_update_section_count"],
"required_update_section_count": response_summary["required_update_section_count"],
"approved_target_path_count": response_summary["approved_target_path_count"],
"target_path_count": response_summary["target_path_count"],
"boundary_ack_count": response_summary["boundary_ack_count"],
"required_boundary_ack_count": response_summary["required_boundary_ack_count"],
"execution_plan_status": plan_summary["execution_status"],
"apply_gate_status": apply_summary["apply_gate_status"],
"confirmed_command_count": apply_summary["confirmed_command_count"],
"planned_command_count": apply_summary["planned_command_count"],
"artifact_count": artifact_summary["artifact_count"],
"artifact_sync_blocked_count": artifact_summary["blocked_target_count"],
"wazuh_handoff_status": wazuh_handoff["status"],
"wazuh_handoff_base_commit": wazuh_handoff["base"]["commit"],
"wazuh_handoff_commit_count": len(wazuh_handoff["commits"]),
"wazuh_handoff_patch_count": len(wazuh_handoff["patch_set"]["patches"]),
"wazuh_release_owner_request_sent_count": wazuh_release_lane["release_owner_request_sent_count"],
"wazuh_release_owner_response_accepted_count": wazuh_release_lane["release_owner_response_accepted_count"],
"wazuh_acknowledged_release_owner_ack_count": wazuh_release_lane["acknowledged_release_owner_ack_count"],
"wazuh_required_release_owner_ack_count": wazuh_release_lane["required_release_owner_ack_count"],
"wazuh_accepted_evidence_count": wazuh_release_lane["accepted_evidence_count"],
"wazuh_required_evidence_count": wazuh_release_lane["required_evidence_count"],
"wazuh_live_metadata_owner_count": wazuh_release_lane["live_metadata_owner_count"],
"wazuh_secret_metadata_count": wazuh_release_lane["secret_metadata_count"],
"wazuh_live_agent_registry_readback": wazuh_incident.get("wazuh_live_agent_registry_readback", 0),
"iwooos_wazuh_runtime_gate": wazuh_incident.get("iwooos_wazuh_runtime_gate", 0),
"wazuh_active_response_count": wazuh_incident.get("active_response", 0),
"wazuh_agent_visibility_status": wazuh_visibility.get("status", "blocked_waiting_manager_agent_registry_readback"),
"wazuh_manager_agent_registry_readback_passed": wazuh_visibility.get("manager_agent_registry_readback_passed", False),
"wazuh_iwooos_live_route_readback_passed": wazuh_visibility.get("iwooos_live_route_readback_passed", False),
"wazuh_dashboard_agent_list_recovered": wazuh_visibility.get("dashboard_agent_list_recovered", False),
"wazuh_agent_visibility_runtime_gate_count": wazuh_visibility.get("runtime_gate_count", 0),
"wazuh_push_gate_count": wazuh_release_lane["push_gate_count"],
"wazuh_deploy_gate_count": wazuh_release_lane["deploy_gate_count"],
"wazuh_readback_gate_count": wazuh_release_lane["readback_gate_count"],
"wazuh_runtime_gate_count": wazuh_release_lane["runtime_gate_count"],
"blocking_reason_count": len(blockers),
"next_action_count": len(actions),
"apply_allowed": False,
"memory_write_authorized": False,
"wazuh_api_live_query_authorized": False,
"runtime_execution_authorized": False,
"ui_implementation_allowed": False,
},
"metric_cards": metrics,
"gate_cards": cards,
"workflow_rows": workflow_rows(cards),
"risk_controls": risk_controls(),
"blocking_reasons": blockers,
"next_actions": actions,
"wazuh_handoff": {
"status": wazuh_handoff["status"],
"source_ref": str(wazuh_handoff_path),
"branch": wazuh_handoff["branch"],
"base_commit": wazuh_handoff["base"]["commit"],
"commit_count": len(wazuh_handoff["commits"]),
"patch_count": len(wazuh_handoff["patch_set"]["patches"]),
"release_owner_request_sent_count": wazuh_release_lane["release_owner_request_sent_count"],
"release_owner_response_accepted_count": wazuh_release_lane["release_owner_response_accepted_count"],
"acknowledged_release_owner_ack_count": wazuh_release_lane["acknowledged_release_owner_ack_count"],
"required_release_owner_ack_count": wazuh_release_lane["required_release_owner_ack_count"],
"accepted_evidence_count": wazuh_release_lane["accepted_evidence_count"],
"required_evidence_count": wazuh_release_lane["required_evidence_count"],
"live_metadata_owner_count": wazuh_release_lane["live_metadata_owner_count"],
"secret_metadata_count": wazuh_release_lane["secret_metadata_count"],
"wazuh_live_agent_registry_readback": wazuh_incident.get("wazuh_live_agent_registry_readback", 0),
"iwooos_wazuh_runtime_gate": wazuh_incident.get("iwooos_wazuh_runtime_gate", 0),
"active_response": wazuh_incident.get("active_response", 0),
"stored_api_secret_metadata_changed": wazuh_incident.get("stored_api_secret_metadata_changed", False),
"agent_visibility_status": wazuh_visibility.get("status", "blocked_waiting_manager_agent_registry_readback"),
"manager_agent_registry_readback_passed": wazuh_visibility.get("manager_agent_registry_readback_passed", False),
"iwooos_live_route_readback_passed": wazuh_visibility.get("iwooos_live_route_readback_passed", False),
"dashboard_agent_list_recovered": wazuh_visibility.get("dashboard_agent_list_recovered", False),
"agent_visibility_runtime_gate_count": wazuh_visibility.get("runtime_gate_count", 0),
"push_gate_count": wazuh_release_lane["push_gate_count"],
"deploy_gate_count": wazuh_release_lane["deploy_gate_count"],
"readback_gate_count": wazuh_release_lane["readback_gate_count"],
"runtime_gate_count": wazuh_release_lane["runtime_gate_count"],
"production_readback_status": wazuh_handoff["production_readback"]["status"],
"boundary": wazuh_boundary,
"runtime_execution_authorized": False,
"wazuh_api_live_query_authorized": False,
},
"hard_gates": hard_gates(),
"operation_boundaries": preflight["operation_boundaries"],
"secret_values_collected": False,
"remote_write_performed": False,
"local_product_write_performed": False,
"execution_authorized": False,
"memory_write_authorized": False,
"wazuh_api_live_query_authorized": False,
"runtime_execution_authorized": False,
"ui_implementation_authorized": False,
}
def write_markdown(payload: dict[str, Any], path: Path) -> None:
summary = payload["summary"]
lines = [
"# AWOOOI 狀態清理儀表板",
"",
f"- generated_at: `{payload['generated_at']}`",
f"- dashboard_status: `{summary['dashboard_status']}`",
f"- overall_completion_percent: `{summary['overall_completion_percent']}%`",
f"- gates: `{summary['blocked_gate_count']}/{summary['gate_count']} blocked`",
f"- owner_flags: `{summary['accepted_owner_flag_count']}/{summary['required_owner_flag_count']}`",
f"- sections: `{summary['approved_update_section_count']}/{summary['required_update_section_count']}`",
f"- confirmed_commands: `{summary['confirmed_command_count']}/{summary['planned_command_count']}`",
f"- artifact_count: `{summary['artifact_count']}`",
f"- wazuh_handoff: `{summary['wazuh_handoff_status']} base={summary['wazuh_handoff_base_commit']} patches={summary['wazuh_handoff_patch_count']}`",
f"- wazuh_live_metadata: `owner={summary['wazuh_live_metadata_owner_count']} secret_metadata={summary['wazuh_secret_metadata_count']}`",
f"- wazuh_live_agent_registry_readback: `{summary['wazuh_live_agent_registry_readback']}`",
f"- iwooos_wazuh_runtime_gate: `{summary['iwooos_wazuh_runtime_gate']}`",
f"- wazuh_active_response_count: `{summary['wazuh_active_response_count']}`",
f"- wazuh_agent_visibility_status: `{summary['wazuh_agent_visibility_status']}`",
f"- memory_write_authorized: `{payload['memory_write_authorized']}`",
f"- runtime_execution_authorized: `{payload['runtime_execution_authorized']}`",
f"- wazuh_api_live_query_authorized: `{payload['wazuh_api_live_query_authorized']}`",
"",
"## 指標卡片",
"",
"| 指標 | 數值 | 狀態 | 說明 |",
"|--------|-------|--------|---------|",
]
for item in payload["metric_cards"]:
lines.append(
f"| `{item['metric_id']}` | `{item['value']}` | `{item['status']}` | {item['caption']} |"
)
lines.extend(["", "## 閘門卡片", "", "| 閘門 | 狀態 | 是否封鎖 | 證據 |", "|------|------|----------|------|"])
for item in payload["gate_cards"]:
lines.append(
f"| `{item['gate_id']}` | `{item['status']}` | `{item['blocked']}` | `{item['evidence_ref']}` |"
)
lines.extend(["", "## 風險控制", "", "| 控制項 | 狀態 | 已授權 |", "|--------|------|--------|"])
for item in payload["risk_controls"]:
lines.append(f"| `{item['control_id']}` | `{item['status']}` | `{item['authorized']}` |")
lines.extend(["", "## 下一步", ""])
lines.extend(f"- {item}" for item in payload["next_actions"])
lines.extend(["", "## 封鎖原因", ""])
lines.extend(f"- `{item}`" for item in payload["blocking_reasons"])
lines.extend(["", "## 強制閘門", ""])
lines.extend(f"- {item}" for item in payload["hard_gates"])
lines.append("")
path.write_text("\n".join(lines), encoding="utf-8")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--preflight",
default="docs/operations/codex-status-cleanup-preflight.snapshot.json",
)
parser.add_argument(
"--owner-package",
default="docs/operations/codex-status-cleanup-owner-review-package.snapshot.json",
)
parser.add_argument(
"--owner-response-preflight",
default="docs/operations/codex-status-cleanup-owner-response-preflight.snapshot.json",
)
parser.add_argument(
"--execution-plan",
default="docs/operations/codex-status-cleanup-execution-plan.snapshot.json",
)
parser.add_argument(
"--apply-gate",
default="docs/operations/codex-status-cleanup-apply-gate.snapshot.json",
)
parser.add_argument(
"--artifact-sync",
default="docs/operations/codex-workstation-artifact-sync-readback.snapshot.json",
)
parser.add_argument(
"--scorecard",
default="docs/operations/product-runtime-governance-completion-scorecard.snapshot.json",
)
parser.add_argument(
"--wazuh-handoff",
default="docs/operations/iwooos-wazuh-release-handoff.snapshot.json",
)
parser.add_argument("--output-json", required=True)
parser.add_argument("--output-md", required=True)
args = parser.parse_args()
payload = build_payload(
Path(args.preflight),
Path(args.owner_package),
Path(args.owner_response_preflight),
Path(args.execution_plan),
Path(args.apply_gate),
Path(args.artifact_sync),
Path(args.scorecard),
Path(args.wazuh_handoff),
)
Path(args.output_json).write_text(
json.dumps(payload, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
write_markdown(payload, Path(args.output_md))
summary = payload["summary"]
print(
"AWOOOI_STATUS_CLEANUP_DASHBOARD_OK"
+ f" status={summary['dashboard_status']}"
+ f" gates={summary['blocked_gate_count']}/{summary['gate_count']}"
+ f" owner_flags={summary['accepted_owner_flag_count']}/{summary['required_owner_flag_count']}"
+ f" apply_allowed={summary['apply_allowed']}"
+ f" memory_write={payload['memory_write_authorized']}"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())