Close PXX automation execution gate
This commit is contained in:
+17
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
## Current Goal
|
||||
|
||||
Automation execution-layer P24 is closed. Current `HEAD` was deployed to the remote host and P24 remote ops smoke passed across health, runtime status, review packet, alert quality, operator digest, runtime incidents, maintenance summary, visual-watch dry-run, and P23 unattended harness. The default next action is PXX `Automation Execution Closure Gate`.
|
||||
Automation execution-layer PXX is closed. P15-P24 are all closed, current `HEAD` was deployed to the remote host, P24 remote ops smoke passed, and the PXX closure gate froze the known execution-layer scope. The default state is long-running analysis-decision monitoring with ops rollup; new product phases require explicit user direction.
|
||||
|
||||
## Current Branch
|
||||
|
||||
@@ -14,8 +14,8 @@ Automation execution-layer P24 is closed. Current `HEAD` was deployed to the rem
|
||||
|
||||
## Automation Status
|
||||
|
||||
- state: automation_execution_layer_p24_remote_smoke_ops_closure_closed
|
||||
- current_phase: P24 Remote Smoke And Ops Closure
|
||||
- state: automation_execution_layer_pxx_known_scope_closed
|
||||
- current_phase: Long-running Analysis Decision Monitor With Ops Rollup
|
||||
- latest_p7_selector_choice: continue_periodic_analysis_decision_monitoring_with_maturity_rollup
|
||||
- latest_p14_slice: webhook_transport_retry
|
||||
- latest_p15_pxx_tasklist_status: ready
|
||||
@@ -65,7 +65,10 @@ Automation execution-layer P24 is closed. Current `HEAD` was deployed to the rem
|
||||
- latest_remote_deploy_status: deployed_current_head
|
||||
- latest_remote_ops_smoke_status: passed
|
||||
- latest_remote_ops_smoke_base_url: http://192.168.3.90:8000
|
||||
- next_execution_layer_phase: PXX Automation Execution Closure Gate
|
||||
- latest_pxx_slice: automation_execution_closure_gate
|
||||
- latest_pxx_closure_gate_status: passed
|
||||
- latest_pxx_new_phase_policy: require_explicit_user_product_decision
|
||||
- next_execution_layer_phase: Long-running Analysis Decision Monitor With Ops Rollup
|
||||
- latest_visual_review_script_status: idle
|
||||
- latest_runtime_visual_watch_task_status: ok
|
||||
- latest_visual_capture_cleanup_task_status: ok
|
||||
@@ -155,6 +158,8 @@ Automation execution-layer P24 is closed. Current `HEAD` was deployed to the rem
|
||||
- Added `scripts/run_remote_ops_smoke.py` for P24 remote API validation.
|
||||
- Extended password deploy smoke coverage to include alert quality, operator digest, runtime incidents, maintenance summary, and the P23 harness.
|
||||
- Deployed current `HEAD` to `http://192.168.3.90:8000` and confirmed P24 remote ops smoke passed without warnings or blockers.
|
||||
- Added `scripts/run_automation_execution_closure_gate.py` for the PXX finite-scope closure check.
|
||||
- Marked P15-P24 and PXX closed in the state anchors and froze automatic P25/P26 phase creation.
|
||||
|
||||
## Current Working State
|
||||
|
||||
@@ -188,6 +193,8 @@ Automation execution-layer P24 is closed. Current `HEAD` was deployed to the rem
|
||||
- P23 is analysis/decision-only: `external_channels_used=false` and `real_trade_required=false`.
|
||||
- P24 remote deployment is complete for current `HEAD`.
|
||||
- P24 remote smoke is implemented and passed: `/health`, `/trading/runtime-status`, `/trading/review-packet`, `/trading/alerts/quality-summary`, `/trading/alerts/operator-digest`, `/trading/runtime-incidents`, `/trading/maintenance-summary`, visual-watch cleanup dry-run, and `/trading/unattended-harness` all passed on `http://192.168.3.90:8000`.
|
||||
- PXX closure gate is implemented and passed: P15-P24 and PXX are checked in `TASKS.md`, PXX state is recorded in `SESSION.md`, final validation evidence is present, and no new Research Council phase was created.
|
||||
- PXX post-state is frozen: `Long-running Analysis Decision Monitor With Ops Rollup`; new product phases require explicit user direction.
|
||||
- Latest `scripts/run_visual_review.py` smoke found no pending reviews: attempted=0, reviewed=0, status=idle.
|
||||
- Latest capture smoke returned `status=ignored` when no watch run was supplied, which is the expected safe no-op.
|
||||
- Latest cleanup smoke deleted one expired temporary artifact through `scripts/run_visual_capture_cleanup.py`.
|
||||
@@ -197,7 +204,7 @@ Automation execution-layer P24 is closed. Current `HEAD` was deployed to the rem
|
||||
- Latest `scripts/run_trading_runtime.py` smoke returned blockers=none and includes a healthy `visual_watch` runtime task.
|
||||
- Latest local runtime smoke confirmed `runtime_status.tasks.alert_dispatch.details` now exposes retry and silent-window counters with blockers=none.
|
||||
|
||||
## P24 Blockers
|
||||
## PXX Blockers
|
||||
|
||||
- none
|
||||
|
||||
@@ -222,6 +229,7 @@ Automation execution-layer P24 is closed. Current `HEAD` was deployed to the rem
|
||||
- P22 maintenance summary remains read-only and uses visual capture retention dry-run statistics only; it must not delete business data or alter execution permission, live readiness, trust bucket, risk governor, or operator confirmation.
|
||||
- P23 unattended harness remains a local/remote smoke verifier only and must not use external channels, require real trades, or alter execution permission, live readiness, trust bucket, risk governor, or operator confirmation.
|
||||
- P24 remote ops smoke remains verification only: its visual-watch step uses dry-run cleanup and it must not use external channels, require real trades, or alter execution permission, live readiness, trust bucket, risk governor, or operator confirmation.
|
||||
- PXX closure gate is verification/state-freeze only and must not create a Research Council phase, alter execution permission, enable real-live readiness, change risk governor/trust bucket behavior, or weaken operator confirmation.
|
||||
- A final rerun of `scripts/run_alert_dispatcher.py` and `scripts/run_trading_runtime.py` hit local PostgreSQL connection timeout because nothing was listening on `127.0.0.1:5432`; the P14 code path is still covered by full unit tests and earlier successful smoke during implementation.
|
||||
- P15 dispatcher smoke succeeded with `suppressed_noise_policy`, `workbench_only`, and `policy_external_allowed` counters present. P15 runtime smoke reached `alert_dispatch` successfully, but the overall runtime returned external environment blockers for market stream disconnected and OKX read transport connection refused.
|
||||
- P16 direct browser smoke succeeded locally with `browser_capture_status=captured`. Script-level capture without a watch run still returns safe no-op `watch_run_missing`.
|
||||
@@ -246,11 +254,12 @@ Automation execution-layer P24 is closed. Current `HEAD` was deployed to the rem
|
||||
- P24 focused validation passed: remote ops smoke tests and deploy smoke coverage tests passed; script static checks passed across 72 scripts.
|
||||
- P24 deploy passed through `scripts/deploy_with_password.py` with 11 HTTP smoke endpoints.
|
||||
- P24 remote ops smoke passed on `http://192.168.3.90:8000` with 9 passed checks, warnings=[], blockers=[].
|
||||
- PXX final validation passed: 709 unit tests, 73 script static checks, `node --check src/web/app.js`, P24 remote ops smoke passed, and closure gate passed.
|
||||
- Real-live order submission remains intentionally disabled because the OKX order adapter is still not a real-live submitter.
|
||||
|
||||
## Exact Next Step
|
||||
|
||||
P24 is closed. Default next action is PXX `Automation Execution Closure Gate`: verify P15-P24 are all closed, rerun final quality gates, freeze known automation execution-layer scope, and write the final closure status.
|
||||
PXX is closed. Default next action is long-running analysis-decision monitoring with ops rollup; do not create P25/P26 automatically. Any new real-trading closure, real external media channel, or product capability must be opened as an explicit new user-directed phase.
|
||||
|
||||
## Validation Commands Used Recently
|
||||
|
||||
@@ -282,4 +291,6 @@ D:\ai-exchange\.venv\Scripts\python.exe -m unittest tests.unit.test_unattended_h
|
||||
D:\ai-exchange\.venv\Scripts\python.exe scripts\run_unattended_harness.py
|
||||
D:\ai-exchange\.venv\Scripts\python.exe -m unittest tests.unit.test_run_remote_ops_smoke tests.unit.test_deploy_with_password
|
||||
D:\ai-exchange\.venv\Scripts\python.exe scripts\run_remote_ops_smoke.py --base-url http://192.168.3.90:8000 --attempts 2 --timeout-seconds 20
|
||||
D:\ai-exchange\.venv\Scripts\python.exe -m unittest tests.unit.test_run_automation_execution_closure_gate
|
||||
D:\ai-exchange\.venv\Scripts\python.exe scripts\run_automation_execution_closure_gate.py
|
||||
```
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
## In Progress
|
||||
|
||||
- [x] P24 Remote Smoke And Ops Closure complete
|
||||
- [x] PXX Automation Execution Closure Gate complete
|
||||
|
||||
## Next Up
|
||||
|
||||
@@ -35,14 +35,14 @@
|
||||
- [x] P22 local closure complete
|
||||
- [x] P23 local closure complete
|
||||
- [x] P24 remote smoke closure complete
|
||||
- [ ] Start PXX Automation Execution Closure Gate
|
||||
- [ ] Continue periodic analysis-decision monitoring with maturity rollup in parallel
|
||||
- [ ] Treat browser screenshot capture and additional external media adapters as future enhancements
|
||||
- [x] PXX closure gate complete
|
||||
- [x] Continue periodic analysis-decision monitoring with maturity rollup in parallel
|
||||
- [x] Treat browser screenshot capture and additional external media adapters as future enhancements
|
||||
|
||||
## Automation Status
|
||||
|
||||
- [x] state: automation_execution_layer_p24_remote_smoke_ops_closure_closed
|
||||
- [x] current_phase: P24 Remote Smoke And Ops Closure
|
||||
- [x] state: automation_execution_layer_pxx_known_scope_closed
|
||||
- [x] current_phase: Long-running Analysis Decision Monitor With Ops Rollup
|
||||
- [x] latest_p7_selector_choice: continue_periodic_analysis_decision_monitoring_with_maturity_rollup
|
||||
- [x] latest_p14_slice: webhook_transport_retry
|
||||
- [x] latest_p15_pxx_tasklist_status: ready
|
||||
@@ -92,7 +92,10 @@
|
||||
- [x] latest_remote_deploy_status: deployed_current_head
|
||||
- [x] latest_remote_ops_smoke_status: passed
|
||||
- [x] latest_remote_ops_smoke_base_url: http://192.168.3.90:8000
|
||||
- [x] next_execution_layer_phase: PXX Automation Execution Closure Gate
|
||||
- [x] latest_pxx_slice: automation_execution_closure_gate
|
||||
- [x] latest_pxx_closure_gate_status: passed
|
||||
- [x] latest_pxx_new_phase_policy: require_explicit_user_product_decision
|
||||
- [x] next_execution_layer_phase: Long-running Analysis Decision Monitor With Ops Rollup
|
||||
- [x] latest_visual_review_script_status: idle
|
||||
- [x] latest_runtime_visual_watch_task_status: ok
|
||||
- [x] latest_visual_capture_cleanup_task_status: ok
|
||||
@@ -207,6 +210,8 @@
|
||||
- [x] Added `scripts/run_remote_ops_smoke.py`
|
||||
- [x] Extended deploy smoke to include P20-P23 execution-layer routes
|
||||
- [x] Added focused P24 remote ops smoke and deploy coverage tests
|
||||
- [x] Added `scripts/run_automation_execution_closure_gate.py`
|
||||
- [x] Added focused PXX closure gate tests
|
||||
- [x] Added runtime `visual_watch` task
|
||||
- [x] Added focused service, script, API, and runtime tests
|
||||
- [x] Smoked the visual review script with no pending reviews
|
||||
@@ -241,6 +246,7 @@
|
||||
- [x] Deployed current `HEAD` to `http://192.168.3.90:8000`
|
||||
- [x] Completed P24 remote deploy smoke through `scripts/deploy_with_password.py` with 11 HTTP endpoints
|
||||
- [x] Completed P24 remote ops smoke with 9 passed checks, no warnings, and no blockers
|
||||
- [x] Completed PXX closure gate with finite-scope freeze and no new Research Council phase creation
|
||||
|
||||
## Blocked
|
||||
|
||||
@@ -296,6 +302,7 @@
|
||||
- [x] `automation_execution_layer_p22_maintenance_retention_rollup`
|
||||
- [x] `automation_execution_layer_p23_end_to_end_unattended_harness`
|
||||
- [x] `automation_execution_layer_p24_remote_smoke_ops_closure`
|
||||
- [x] `automation_execution_layer_pxx_known_scope_closed`
|
||||
|
||||
## P15-PXX Finite Queue
|
||||
|
||||
@@ -309,7 +316,7 @@
|
||||
- [x] `P22` Maintenance And Retention Rollup
|
||||
- [x] `P23` End-To-End Unattended Harness
|
||||
- [x] `P24` Remote Smoke And Ops Closure
|
||||
- [ ] `PXX` Automation Execution Closure Gate
|
||||
- [x] `PXX` Automation Execution Closure Gate
|
||||
|
||||
## Backlog
|
||||
|
||||
|
||||
@@ -414,6 +414,7 @@ candidate -> decision alert -> dispatcher -> 外部消息 -> delivery record
|
||||
- 2026-05-12 P22 已完成 `maintenance / retention rollup` 本地闭环:maintenance summary 以只读方式聚合 visual capture retention dry-run、delivery/feedback、runtime watchdog 与 incident journal,输出 P23 harness 可复用的 checks/blockers/warnings/p23_assertions,不执行未纳入 retention policy 的业务数据删除。
|
||||
- 2026-05-12 P23 已完成 `end-to-end unattended harness` 本地闭环:`UnattendedHarnessService`、脚本与 API 会在 analysis/decision-only 模式下一次性验证 P15-P22 关键路径,输出单一 JSON blockers/warnings/passed-checks 报告,不使用外部通道、不要求真实成交。
|
||||
- 2026-05-12 P24 已完成 `remote smoke / ops closure` 闭环:当前 `HEAD` 已部署到远端,部署后 11 个 HTTP smoke endpoint 通过,`scripts/run_remote_ops_smoke.py` 对 P15-P23 关键远端能力返回 9 个 passed checks、无 warnings、无 blockers。
|
||||
- 2026-05-12 PXX 已完成 `automation execution closure gate` 闭环:P15-P24 已冻结,`SESSION.md` / `TASKS.md` / `docs` 已回写,后续默认进入长期 monitor + ops rollup,不再自动发明 P25/P26。
|
||||
|
||||
### 验收
|
||||
- 非重大错误不打断主循环
|
||||
|
||||
@@ -134,6 +134,11 @@
|
||||
|
||||
2026-05-12 P24 已落地:remote ops smoke 覆盖 health、runtime status、review packet、alert quality、operator digest、runtime incidents、maintenance summary、visual-watch cleanup dry-run 与 P23 unattended harness。该脚本只做远端可用性验证,visual-watch 步骤使用 dry-run,不触发外部通道、不要求真实成交,也不改变任何交易权限或 operator confirmation protocol。
|
||||
|
||||
#### `scripts/run_automation_execution_closure_gate.py`
|
||||
职责:验证 P15-P24 与 PXX finite-scope closure 是否已经完成,并冻结自动扩阶段的默认后续状态。
|
||||
|
||||
2026-05-12 PXX 已落地:closure gate 只读取 `SESSION.md`、`TASKS.md` 与 P15-PXX 任务清单,确认 P15-P24 已 closed、PXX 后默认状态已冻结、`new_phase_policy` 要求用户显式打开新阶段。该脚本只做状态校验,不改变任何执行权限、交易权限或 operator confirmation protocol。
|
||||
|
||||
#### `src/services/alerts/delivery_policy_service.py`
|
||||
职责:
|
||||
|
||||
|
||||
@@ -323,6 +323,8 @@
|
||||
- 2026-05-12 P24 已新增 `scripts/run_remote_ops_smoke.py`,覆盖 `/health`、`/trading/runtime-status`、`/trading/review-packet`、`/trading/alerts/quality-summary`、`/trading/alerts/operator-digest`、`/trading/runtime-incidents`、`/trading/maintenance-summary`、visual-watch cleanup dry-run 与 `/trading/unattended-harness`。
|
||||
- 2026-05-12 P24 已扩展 `scripts/deploy_with_password.py` 的部署后 HTTP smoke,使远端版本漂移会在 P20-P23 新入口缺失时失败。
|
||||
- 2026-05-12 P24 已将当前 `HEAD` 部署到 `http://192.168.3.90:8000`;部署脚本 11 个 HTTP smoke endpoint 通过,P24 remote ops smoke 返回 `status=passed`、passed_checks=9、warnings=[]、blockers=[]。
|
||||
- 2026-05-12 PXX 已新增 `scripts/run_automation_execution_closure_gate.py`,以 finite-scope gate 校验 P15-P24 已闭环、`SESSION.md` / `TASKS.md` 已回写、PXX 后默认状态已冻结。
|
||||
- 2026-05-12 PXX closure gate 已通过:P15-P24 均为 closed,`SESSION.md` / `TASKS.md` / 本文档均已回写,当前执行层不再自动发明 P25/P26。
|
||||
|
||||
---
|
||||
|
||||
@@ -357,15 +359,17 @@ PXX 之后,系统默认进入长期 monitor + ops rollup,不再自动发明
|
||||
|
||||
## 16. 推荐连续执行入口
|
||||
|
||||
默认下一步:
|
||||
PXX 关闭后默认状态:
|
||||
|
||||
```text
|
||||
P15 Alert Noise Policy Matrix
|
||||
state: automation_execution_layer_pxx_known_scope_closed
|
||||
current_phase: Long-running Analysis Decision Monitor With Ops Rollup
|
||||
next_action: continue_periodic_analysis_decision_monitoring_with_maturity_rollup
|
||||
new_phase_policy: require_explicit_user_product_decision
|
||||
```
|
||||
|
||||
执行方式:
|
||||
|
||||
1. 打开 P15 最小闭环。
|
||||
2. 完成代码、验证、状态回写、commit。
|
||||
3. 自动进入 P16。
|
||||
4. 重复直到 PXX closure gate 或真实 blocker。
|
||||
1. 保持长期 monitor + ops rollup。
|
||||
2. 不再自动发明 P25/P26。
|
||||
3. 若未来需要真实成交闭环、真实外部媒体发送、或新的产品能力,必须由用户明确打开新阶段。
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
TASKS_PATH = Path("TASKS.md")
|
||||
SESSION_PATH = Path("SESSION.md")
|
||||
TASKLIST_PATH = Path("docs/AI_ICT_自动化执行层_P15-PXX闭环任务清单_v1.md")
|
||||
|
||||
REQUIRED_QUEUE_ITEMS = (
|
||||
"`P15` Alert Noise Policy Matrix",
|
||||
"`P16` Browser Screenshot Capture Adapter",
|
||||
"`P17` Visual Trigger ROI Router",
|
||||
"`P18` Visual Evidence Media Dispatch",
|
||||
"`P19` Multi-Channel Alert Routing",
|
||||
"`P20` Operator Digest And Review Queue",
|
||||
"`P21` Runtime Incident Journal",
|
||||
"`P22` Maintenance And Retention Rollup",
|
||||
"`P23` End-To-End Unattended Harness",
|
||||
"`P24` Remote Smoke And Ops Closure",
|
||||
"`PXX` Automation Execution Closure Gate",
|
||||
)
|
||||
|
||||
REQUIRED_GUARDS = (
|
||||
"execution_allowed",
|
||||
"real_live_ready",
|
||||
"risk_governor",
|
||||
"trust_bucket",
|
||||
"operator_confirmation_protocol",
|
||||
)
|
||||
|
||||
|
||||
def run_closure_gate(root: Path = ROOT) -> dict:
|
||||
tasks = _read_text(root / TASKS_PATH)
|
||||
session = _read_text(root / SESSION_PATH)
|
||||
tasklist = _read_text(root / TASKLIST_PATH)
|
||||
checks = [
|
||||
_check_queue_closed(tasks),
|
||||
_check_session_pxx_state(session),
|
||||
_check_scope_freeze_policy(tasklist),
|
||||
_check_validation_evidence(session),
|
||||
_check_guardrails(session),
|
||||
]
|
||||
blockers = [check["name"] for check in checks if check["status"] == "blocked"]
|
||||
return {
|
||||
"status": "blocked" if blockers else "passed",
|
||||
"mode": "automation_execution_closure_gate",
|
||||
"generated_ts": datetime.now(timezone.utc).isoformat(),
|
||||
"checks": checks,
|
||||
"passed_checks": [check["name"] for check in checks if check["status"] == "passed"],
|
||||
"blockers": blockers,
|
||||
"post_pxx_state": {
|
||||
"state": "automation_execution_layer_pxx_known_scope_closed",
|
||||
"current_phase": "Long-running Analysis Decision Monitor With Ops Rollup",
|
||||
"next_action": "continue_periodic_analysis_decision_monitoring_with_maturity_rollup",
|
||||
"new_phase_policy": "require_explicit_user_product_decision",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _check_queue_closed(tasks: str) -> dict:
|
||||
missing = []
|
||||
for item in REQUIRED_QUEUE_ITEMS:
|
||||
if f"- [x] {item}" not in tasks:
|
||||
missing.append(item)
|
||||
if missing:
|
||||
return _blocked("p15_pxx_queue_closed", f"unchecked queue items: {missing}")
|
||||
return _passed("p15_pxx_queue_closed", "P15-P24 and PXX are checked in TASKS.md")
|
||||
|
||||
|
||||
def _check_session_pxx_state(session: str) -> dict:
|
||||
required = (
|
||||
"state: automation_execution_layer_pxx_known_scope_closed",
|
||||
"current_phase: Long-running Analysis Decision Monitor With Ops Rollup",
|
||||
"next_execution_layer_phase: Long-running Analysis Decision Monitor With Ops Rollup",
|
||||
)
|
||||
missing = [item for item in required if item not in session]
|
||||
if missing:
|
||||
return _blocked("session_pxx_state", f"SESSION.md missing {missing}")
|
||||
return _passed("session_pxx_state", "SESSION.md records the PXX frozen state")
|
||||
|
||||
|
||||
def _check_scope_freeze_policy(tasklist: str) -> dict:
|
||||
required = (
|
||||
"new_phase_policy: require_explicit_user_product_decision",
|
||||
"不再自动发明 P25/P26",
|
||||
)
|
||||
missing = [item for item in required if item not in tasklist]
|
||||
if missing:
|
||||
return _blocked("scope_freeze_policy", f"tasklist missing {missing}")
|
||||
return _passed("scope_freeze_policy", "PXX tasklist freezes automatic phase creation")
|
||||
|
||||
|
||||
def _check_validation_evidence(session: str) -> dict:
|
||||
required = (
|
||||
"PXX final validation passed",
|
||||
"unit tests",
|
||||
"script static checks",
|
||||
"P24 remote ops smoke passed",
|
||||
)
|
||||
missing = [item for item in required if item not in session]
|
||||
if missing:
|
||||
return _blocked("validation_evidence", f"SESSION.md missing {missing}")
|
||||
return _passed("validation_evidence", "SESSION.md records final quality and remote smoke evidence")
|
||||
|
||||
|
||||
def _check_guardrails(session: str) -> dict:
|
||||
missing = [guard for guard in REQUIRED_GUARDS if guard not in session]
|
||||
if missing:
|
||||
return _blocked("guardrails_unchanged", f"SESSION.md missing guards {missing}")
|
||||
return _passed("guardrails_unchanged", "guardrail names remain recorded as unchanged")
|
||||
|
||||
|
||||
def _read_text(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _passed(name: str, detail: str) -> dict:
|
||||
return {"name": name, "status": "passed", "detail": detail}
|
||||
|
||||
|
||||
def _blocked(name: str, detail: str) -> dict:
|
||||
return {"name": name, "status": "blocked", "detail": detail}
|
||||
|
||||
|
||||
def _get_bool(env, key: str, default: bool) -> bool:
|
||||
value = env.get(key)
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return str(value).strip().lower() in {"1", "true", "yes", "on"}
|
||||
|
||||
|
||||
def _parse_args(argv: Optional[list[str]]) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Run the PXX automation execution closure gate.")
|
||||
parser.add_argument("--root", default=str(ROOT))
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
def main(argv: Optional[list[str]] = None, env=None) -> int:
|
||||
env = os.environ if env is None else env
|
||||
args = _parse_args(argv)
|
||||
payload = run_closure_gate(root=Path(args.root))
|
||||
if _get_bool(env, "CLOSURE_GATE_OUTPUT_JSON", False):
|
||||
print(json.dumps(payload, ensure_ascii=False, sort_keys=True))
|
||||
else:
|
||||
print(f"Closure gate status: {payload['status']}")
|
||||
print(f"Passed checks: {', '.join(payload['passed_checks']) or 'none'}")
|
||||
print(f"Blockers: {', '.join(payload['blockers']) or 'none'}")
|
||||
return 0 if payload["status"] == "passed" else 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,78 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from scripts.run_automation_execution_closure_gate import REQUIRED_QUEUE_ITEMS, run_closure_gate
|
||||
|
||||
|
||||
class AutomationExecutionClosureGateTests(unittest.TestCase):
|
||||
def test_passes_when_queue_state_and_evidence_are_closed(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
root = Path(tmp_dir)
|
||||
_write_closure_files(root)
|
||||
|
||||
payload = run_closure_gate(root=root)
|
||||
|
||||
self.assertEqual(payload["status"], "passed")
|
||||
self.assertEqual(payload["blockers"], [])
|
||||
self.assertIn("p15_pxx_queue_closed", payload["passed_checks"])
|
||||
self.assertEqual(payload["post_pxx_state"]["new_phase_policy"], "require_explicit_user_product_decision")
|
||||
|
||||
def test_blocks_when_a_queue_item_is_not_checked(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
root = Path(tmp_dir)
|
||||
_write_closure_files(root, unchecked_item="`P24` Remote Smoke And Ops Closure")
|
||||
|
||||
payload = run_closure_gate(root=root)
|
||||
|
||||
self.assertEqual(payload["status"], "blocked")
|
||||
self.assertIn("p15_pxx_queue_closed", payload["blockers"])
|
||||
|
||||
def test_blocks_when_validation_evidence_is_missing(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
root = Path(tmp_dir)
|
||||
_write_closure_files(root, include_validation=False)
|
||||
|
||||
payload = run_closure_gate(root=root)
|
||||
|
||||
self.assertEqual(payload["status"], "blocked")
|
||||
self.assertIn("validation_evidence", payload["blockers"])
|
||||
|
||||
|
||||
def _write_closure_files(root: Path, unchecked_item=None, include_validation: bool = True) -> None:
|
||||
docs = root / "docs"
|
||||
docs.mkdir(parents=True)
|
||||
task_lines = ["## P15-PXX Finite Queue"]
|
||||
for item in REQUIRED_QUEUE_ITEMS:
|
||||
checkbox = "[ ]" if item == unchecked_item else "[x]"
|
||||
task_lines.append(f"- {checkbox} {item}")
|
||||
(root / "TASKS.md").write_text("\n".join(task_lines), encoding="utf-8")
|
||||
|
||||
validation = ""
|
||||
if include_validation:
|
||||
validation = "PXX final validation passed: unit tests, script static checks. P24 remote ops smoke passed."
|
||||
(root / "SESSION.md").write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"state: automation_execution_layer_pxx_known_scope_closed",
|
||||
"current_phase: Long-running Analysis Decision Monitor With Ops Rollup",
|
||||
"next_execution_layer_phase: Long-running Analysis Decision Monitor With Ops Rollup",
|
||||
"guards_unchanged: execution_allowed, real_live_ready, risk_governor, trust_bucket, operator_confirmation_protocol",
|
||||
validation,
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(docs / "AI_ICT_自动化执行层_P15-PXX闭环任务清单_v1.md").write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"new_phase_policy: require_explicit_user_product_decision",
|
||||
"PXX 之后不再自动发明 P25/P26。",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user