fix(awooop): open live copy to controlled automation
Some checks failed
Ansible / Reboot Recovery Contract / validate (push) Waiting to run
CD Pipeline / build-and-deploy (push) Blocked by required conditions
Code Review / ai-code-review (push) Waiting to run
CD Pipeline / tests (push) Successful in 1m39s
CD Pipeline / post-deploy-checks (push) Has been cancelled
Some checks failed
Ansible / Reboot Recovery Contract / validate (push) Waiting to run
CD Pipeline / build-and-deploy (push) Blocked by required conditions
Code Review / ai-code-review (push) Waiting to run
CD Pipeline / tests (push) Successful in 1m39s
CD Pipeline / post-deploy-checks (push) Has been cancelled
This commit is contained in:
@@ -9,7 +9,9 @@ state for low / medium / high controlled automation.
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
TEXT_FILES = [
|
||||
@@ -44,6 +46,37 @@ REQUIRED_FRAGMENTS = [
|
||||
"受控授權閘門",
|
||||
"controlled gate",
|
||||
"controlled review",
|
||||
"AI 受控 Gate",
|
||||
"AI 受控補齊:NO_ACTION",
|
||||
"等待 AI 受控補齊",
|
||||
"受控驗收流程",
|
||||
"負責人脫敏證據收件",
|
||||
"Controlled Review",
|
||||
"AI 受控 review",
|
||||
]
|
||||
|
||||
AWOOOP_LIVE_FORBIDDEN_FRAGMENTS = [
|
||||
"人工 Gate",
|
||||
"人工介入",
|
||||
"待人工",
|
||||
"等待人工",
|
||||
"人工回覆",
|
||||
"人工收件",
|
||||
"人工判斷",
|
||||
"人工交接",
|
||||
"人工方案",
|
||||
"人工確認無需動作",
|
||||
"人工:{human}",
|
||||
"需要人工={human}",
|
||||
"人工覆核",
|
||||
"人工檢查",
|
||||
"Owner review",
|
||||
"Owner Review",
|
||||
"負責人審查",
|
||||
]
|
||||
|
||||
AWOOOP_ALLOWED_LEGACY_PATH_PREFIXES = [
|
||||
"awooop.approvals.legacyHitl.",
|
||||
]
|
||||
|
||||
|
||||
@@ -54,6 +87,38 @@ def _iter_guarded_files(root: Path) -> list[Path]:
|
||||
return files
|
||||
|
||||
|
||||
def _collect_awooop_message_violations(path: Path, root: Path) -> list[str]:
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
awooop = data.get("awooop")
|
||||
if not isinstance(awooop, dict):
|
||||
return [f"{path.relative_to(root)}: missing awooop namespace"]
|
||||
|
||||
violations: list[str] = []
|
||||
|
||||
def walk(value: Any, parts: list[str]) -> None:
|
||||
if isinstance(value, dict):
|
||||
for key, child in value.items():
|
||||
walk(child, [*parts, key])
|
||||
return
|
||||
if isinstance(value, list):
|
||||
for index, child in enumerate(value):
|
||||
walk(child, [*parts, str(index)])
|
||||
return
|
||||
if not isinstance(value, str):
|
||||
return
|
||||
|
||||
dotted = ".".join(parts)
|
||||
if any(dotted.startswith(prefix) for prefix in AWOOOP_ALLOWED_LEGACY_PATH_PREFIXES):
|
||||
return
|
||||
for fragment in AWOOOP_LIVE_FORBIDDEN_FRAGMENTS:
|
||||
if fragment in value:
|
||||
relative = path.relative_to(root)
|
||||
violations.append(f"{relative}:{dotted}: forbidden live AwoooP copy {fragment!r}")
|
||||
|
||||
walk(awooop, ["awooop"])
|
||||
return violations
|
||||
|
||||
|
||||
def validate(root: Path) -> None:
|
||||
root = root.resolve()
|
||||
violations: list[str] = []
|
||||
@@ -65,6 +130,8 @@ def validate(root: Path) -> None:
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8")
|
||||
guarded_text.append(text)
|
||||
if path.name.endswith(".json"):
|
||||
violations.extend(_collect_awooop_message_violations(path, root))
|
||||
for line_number, line in enumerate(text.splitlines(), start=1):
|
||||
for fragment in FORBIDDEN_FRAGMENTS:
|
||||
if fragment in line:
|
||||
|
||||
Reference in New Issue
Block a user