fix(reboot): preserve ai triage blocker signal
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m17s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
ogt
2026-07-09 16:26:01 +08:00
parent 4481f18aa1
commit 6d2d59c027
5 changed files with 34 additions and 4 deletions

View File

@@ -1,3 +1,25 @@
## 2026-07-09 — P0-006 AI log triage controlled auto-recovery package
**完成內容**
- 新增 `scripts/reboot-recovery/ai-log-triage-auto-recovery.sh`,把 110 Docker / containerd / Harbor / Nginx、120 / 121 K3s events、188 edge Nginx / Docker / systemd、99 VMware no-secret readback 與 public route status 收斂成 `findings.tsv``actions.tsv``summary.txt`
- `reboot-auto-recovery-slo-exporter.sh` 會在 host probe / readiness summary / scorecard 前先跑 AI log triage`awoooi-reboot-auto-recovery-slo.service` 設定 `AI_LOG_TRIAGE_AUTO_RECOVERY_MODE=apply`,但 allowlist 僅限 start inactive docker/nginx、Harbor watchdog log-first repair、registry ready 後刪 ImagePullBackOff / ErrImagePull pods。
- 新增 full-host reboot orchestrator 與 systemd unit / installerinstaller 預設 `--dry-run`,必須明確 `--apply --enable-now` 才會啟用 timerunit 使用 `/opt/awoooi/reboot-recovery` portable path避免 Mac local path 進 production。
- 修正 orchestrator`ai-log-triage-auto-recovery.sh` 以 exit `2` 表示 P0 findings 時不再被誤判成 `AI_LOG_TRIAGE_FAILED`,會正確 merge findings 到 orchestrator summary。
- 新增 Windows99 source scriptsVMware autostart 與 Windows Update surprise reboot prevention兩者保留 `WhatIfOnly` / source contract不在本輪執行 Windows write。
**已跑驗證**
- `PYTHONPATH=apps/api python3.11 -m pytest scripts/reboot-recovery/tests/test_reboot_p0_operational_contract.py -q -p no:cacheprovider``10 passed`
- `bash -n scripts/reboot-recovery/ai-log-triage-auto-recovery.sh scripts/reboot-recovery/full-host-reboot-orchestrator.sh scripts/reboot-recovery/install-full-host-reboot-orchestrator.sh scripts/reboot-recovery/awoooi-telegram-notify.sh scripts/reboot-recovery/reboot-auto-recovery-slo-exporter.sh`:通過。
- `python3.11 -m py_compile scripts/reboot-recovery/reboot-auto-recovery-slo-scorecard.py scripts/reboot-recovery/tests/test_reboot_p0_operational_contract.py``git diff --check`:通過。
- Live `--check` artifact `/tmp/awoooi-full-host-reboot-orchestrator-codex/20260709T082305Z``RECOVERY_BLOCKED_P0``FINDING_COUNT=3``FINDING_P0_COUNT=2`P0 為 `STOCK_UPSTREAM_NOT_READY``EDGE_502_UPSTREAM_REFUSED`public route readback 為 AWOOOI health `200`、AWOOOI web `307`、Stock freshness `200`、Gitea `200`、registry `/v2/` `401`、Harbor `200`
**仍維持**
- Production P0-006 尚未完成:`/api/v1/agents/reboot-auto-recovery-slo-scorecard` 仍為 `blocked_reboot_auto_recovery_slo_not_ready`,最新讀回 `active_blocker_count=16`、primary `reboot_event_required_host_unreachable`next safe action 仍是 `restore_windows99_missing_vmx_source_for_aliases_then_rerun_no_secret_collector_and_scorecard_no_vm_power_change`
- 本輪未執行 `--apply`、未啟用 timer、未重啟 host / Docker / Nginx / K3s / DB / firewall、未 VM power change、未讀 secret / token / `.env` / raw sessions / SQLite / auth、未使用 GitHub / gh、未 DROP / TRUNCATE / restore / prune / delete / force push。
**下一步**
- 跑完整 focused verifier / runner pressure guardcommit / normal push Gitea mainCD 後讀回 production SLO / priority work order確認 AI log triage source controls 與 orchestrator evidence 上線。P0-006 下一個 runtime 收斂仍要先取得 verified 111 VMX source / backup path 或授權 console source path再進 scoped dry-run不能猜路徑或直接 power on VM。
## 2026-07-03 — 21:21 全站 UI/UX 專業化重構 — 面板與頁面 Tailwind 化
**完成內容**

View File

@@ -10,7 +10,7 @@
本節是每次接手、開機、關機、重啟後的第一個判定錨點。若日期不是今天,必須先重跑 live check再更新本節與 `docs/workplans/2026-06-04-reboot-cold-start-backup-recovery-workplan.md`
v1.131 AI log triage controlled auto-recovery rule每次全主機重啟後10 分鐘 SLO verifier 不得只跑 read-only summary。`awoooi-reboot-auto-recovery-slo.service` 必須以 `AI_LOG_TRIAGE_AUTO_RECOVERY_MODE=apply` 先執行 `scripts/reboot-recovery/ai-log-triage-auto-recovery.sh`bounded 收集 99 / 110 / 120 / 121 / 188 logs、K3s events、VMware no-secret readback 與 public route status自動輸出 findings / actions / summary再接 host probe、post-reboot summary、scorecard 與 textfile metrics。2026-07-09 16:17 live check artifact `/tmp/awoooi-ai-log-triage-codex-20260709-161759` 的目前 truth 是 `FINDING_COUNT=4``FINDING_P0_COUNT=3``TOO_MANY_OPEN_FILES host=110_or_188``STOCK_UPSTREAM_NOT_READY host=110_188``EDGE_502_UPSTREAM_REFUSED host=188_edge`,另有 `HOST188_POSTGRES_SYSTEMD_FAILED` P2 hygienepublic route readback 為 AWOOOI health `200`、AWOOOI web `307`、Stock freshness `200`、Gitea `200`、registry `/v2/` `401`、Harbor `200`。這些不得再被當成噪音或人工 SOP必須進 AI findings、Prometheus/Telegram blocker 與下一步 action matrix。允許的 `--apply` 只限低風險 allowliststart inactive docker/nginx、Harbor watchdog log-first repair、registry ready 後刪 failed-pull pods 讓 K3s 重建。仍禁止 reboot、node drain、firewall cutover、DB destructive action、Docker prune、secret/session/.env/raw-volume reads。
v1.131 AI log triage controlled auto-recovery rule每次全主機重啟後10 分鐘 SLO verifier 不得只跑 read-only summary。`awoooi-reboot-auto-recovery-slo.service` 必須以 `AI_LOG_TRIAGE_AUTO_RECOVERY_MODE=apply` 先執行 `scripts/reboot-recovery/ai-log-triage-auto-recovery.sh`bounded 收集 99 / 110 / 120 / 121 / 188 logs、K3s events、VMware no-secret readback 與 public route status自動輸出 findings / actions / summary再接 host probe、post-reboot summary、scorecard 與 textfile metrics。2026-07-09 16:23 orchestrator check artifact `/tmp/awoooi-full-host-reboot-orchestrator-codex/20260709T082305Z` 的目前 truth 是 `RECOVERY_BLOCKED_P0``FINDING_COUNT=3``FINDING_P0_COUNT=2``STOCK_UPSTREAM_NOT_READY host=110_188``EDGE_502_UPSTREAM_REFUSED host=188_edge`,另有 `HOST188_POSTGRES_SYSTEMD_FAILED` P2 hygienepublic route readback 為 AWOOOI health `200`、AWOOOI web `307`、Stock freshness `200`、Gitea `200`、registry `/v2/` `401`、Harbor `200`。這些不得再被當成噪音或人工 SOP必須進 AI findings、Prometheus/Telegram blocker 與下一步 action matrix。允許的 `--apply` 只限低風險 allowliststart inactive docker/nginx、Harbor watchdog log-first repair、registry ready 後刪 failed-pull pods 讓 K3s 重建。仍禁止 reboot、node drain、firewall cutover、DB destructive action、Docker prune、secret/session/.env/raw-volume reads。
v1.130 Windows99 VMX backup/source search package rule2026-07-03 18:19 最新 via-110 no-secret locator 已把目前 truth 從早先 `candidate_source_count=6` 修正為 `candidate_source_count=0``source_locator_status=blocked_missing_expected_vmx_source_no_candidate_found`,且 `raw_path_output=false``path_fingerprint_only=true``secret_value_read=false``remote_write_performed=false``vm_power_change_performed=false`。因此 P0-4 下一步不得再引用 generic Ubuntu candidate必須讀 `/api/v1/agents/windows99-vmx-source-backup-search-package` 與 priority readback 的 `windows99_vmx_source_backup_search_*` 欄位。當前 backup/source search receipt 顯示 120 / 121 / local 均未找到 verified 111 source99 alias 無 Linux backup host mapping110 / 188 / 112 SSH BatchMode 不可用,`candidate_source_count=0``blocked_host_count=4``apply_allowed_by_this_package=false`。固定下一步是離線備份 inventory 或授權 console source path再取得 verified source path 後建立 scoped relink dry-run仍不得 power on VM、restore、讀 VMX 內容、讀 secret、重啟 Windows / VMware service / host / Docker / Nginx / K3s / DB / firewall。

View File

@@ -25,7 +25,7 @@
主機重啟後不得再靠人工逐台看 log 才判斷異常。固定第一步改為執行 `scripts/reboot-recovery/ai-log-triage-auto-recovery.sh --apply`;若只允許讀取,則用 `--check`,但 scorecard / 告警仍必須吃同一份 artifact。此 runner 會 bounded 收集 110 Docker / containerd / Harbor / Nginx、120 / 121 K3s events、188 edge Nginx / Docker / systemd、99 VMware no-secret readback 與 public route HTTP status然後輸出 `findings.tsv``actions.tsv``summary.txt`
本輪 2026-07-09 16:17 live evidence `/tmp/awoooi-ai-log-triage-codex-20260709-161759` 顯示 `FINDING_COUNT=4``FINDING_P0_COUNT=3`P0 依序為 `TOO_MANY_OPEN_FILES host=110_or_188``STOCK_UPSTREAM_NOT_READY host=110_188``EDGE_502_UPSTREAM_REFUSED host=188_edge`,另有 `HOST188_POSTGRES_SYSTEMD_FAILED` P2 hygiene。public route readback 為 AWOOOI health `200`、AWOOOI web `307`、Stock freshness `200`、Gitea `200`、registry `/v2/` `401`、Harbor `200`;因此不得沿用稍早 Harbor 5000 refused / K3s ImagePullBackOff 舊 artifact 當作目前 truth。若後續 registry 再度不 readyK3s pod delete 只能被自動化標為 `skipped_registry_not_ready`,不得宣稱 502 已修復。
本輪 2026-07-09 16:23 orchestrator check evidence `/tmp/awoooi-full-host-reboot-orchestrator-codex/20260709T082305Z` 顯示 `RECOVERY_BLOCKED_P0``FINDING_COUNT=3``FINDING_P0_COUNT=2`P0 依序為 `STOCK_UPSTREAM_NOT_READY host=110_188``EDGE_502_UPSTREAM_REFUSED host=188_edge`,另有 `HOST188_POSTGRES_SYSTEMD_FAILED` P2 hygiene。public route readback 為 AWOOOI health `200`、AWOOOI web `307`、Stock freshness `200`、Gitea `200`、registry `/v2/` `401`、Harbor `200`;因此不得沿用稍早 Harbor 5000 refused / K3s ImagePullBackOff 舊 artifact 當作目前 truth。若後續 registry 再度不 readyK3s pod delete 只能被自動化標為 `skipped_registry_not_ready`,不得宣稱 502 已修復。
`awoooi-reboot-auto-recovery-slo.service` 必須設定 `AI_LOG_TRIAGE_AUTO_RECOVERY_MODE=apply`,並由 `reboot-auto-recovery-slo-exporter.sh` 在 host probe / readiness summary 前先跑 AI log triage。允許的 controlled apply 僅限110 Docker inactive 時 start、Harbor watchdog `--repair-once` / harbor-log-first recovery、registry ready 後只刪 `ImagePullBackOff` / `ErrImagePull` pods 讓 Kubernetes 重建、188 nginx/docker inactive 時 start。仍禁止 reboot、node drain、firewall cutover、DB restore/drop/truncate、Docker prune、secret/session/.env/raw-volume reads。

View File

@@ -202,15 +202,20 @@ probe_public_routes() {
run_ai_log_triage() {
local triage_dir="${ARTIFACT_DIR}/ai-log-triage"
local rc=0
if [[ ! -x "${SCRIPT_DIR}/ai-log-triage-auto-recovery.sh" ]]; then
finding "P0" "recovery" "AI_LOG_TRIAGE_SCRIPT_MISSING" "${SCRIPT_DIR}/ai-log-triage-auto-recovery.sh"
return 1
fi
action "$MODE" "ai-log-triage" "RUN_AI_LOG_TRIAGE" "artifact_dir=${triage_dir}"
"${SCRIPT_DIR}/ai-log-triage-auto-recovery.sh" "--${MODE}" --artifact-dir "$triage_dir" || {
"${SCRIPT_DIR}/ai-log-triage-auto-recovery.sh" "--${MODE}" --artifact-dir "$triage_dir" || rc=$?
if [[ "$rc" -ne 0 && "$rc" -ne 2 ]]; then
finding "P0" "ai-log-triage" "AI_LOG_TRIAGE_FAILED" "see ${triage_dir}"
return 1
}
fi
if [[ "$rc" -eq 2 ]]; then
event "INFO" "ai-log-triage" "AI_LOG_TRIAGE_REPORTED_FINDINGS rc=2"
fi
if [[ -s "${triage_dir}/findings.tsv" ]]; then
awk -v now="$(date -u +%Y-%m-%dT%H:%M:%SZ)" -F '\t' \
'{print now "\t" $2 "\tai-log-triage\t" $1 "\thost=" $3 " evidence=" $4 " next_action=" $5}' \

View File

@@ -194,6 +194,9 @@ def test_reboot_p0_contract_has_ai_log_triage_controlled_apply() -> None:
assert "run_scorecard" in full_host_orchestrator
assert "run_stock_upstream_gate_hint" in full_host_orchestrator
assert "TELEGRAM_NOTIFY_SCRIPT" in full_host_orchestrator
assert 'rc=$?' in full_host_orchestrator
assert '"$rc" -ne 2' in full_host_orchestrator
assert "AI_LOG_TRIAGE_REPORTED_FINDINGS" in full_host_orchestrator
assert 'host=" $3 " evidence=" $4 " next_action=" $5' in full_host_orchestrator
assert "/Users/ogt/" not in full_host_service
assert "WorkingDirectory=/opt/awoooi/reboot-recovery" in full_host_service