feat(governance): 新增 Agent Gitea PR 草案 lane
All checks were successful
CD Pipeline / tests (push) Successful in 1m32s
Code Review / ai-code-review (push) Successful in 14s
CD Pipeline / build-and-deploy (push) Successful in 6m10s
CD Pipeline / post-deploy-checks (push) Successful in 1m38s

This commit is contained in:
Your Name
2026-06-11 15:09:39 +08:00
parent cd92885277
commit 4da7f2c506
16 changed files with 1779 additions and 27 deletions

View File

@@ -55,6 +55,9 @@ from src.services.ai_agent_communication_learning_contract import (
from src.services.ai_agent_deployment_layout import (
load_latest_ai_agent_deployment_layout,
)
from src.services.ai_agent_gitea_pr_draft_lane import (
load_latest_ai_agent_gitea_pr_draft_lane,
)
from src.services.ai_agent_proactive_operations_contract import (
load_latest_ai_agent_proactive_operations_contract,
)
@@ -677,6 +680,35 @@ async def get_agent_telegram_action_required_digest_policy() -> dict[str, Any]:
) from exc
@router.get(
"/agent-gitea-pr-draft-lane",
response_model=dict[str, Any],
summary="取得 AI Agent Gitea PR 草案 lane",
description=(
"讀取最新已提交的 AI Agent Gitea PR 草案 lane"
"此端點只回傳 grouping、automerge=false、測試證據、rollback、owner response 與 redaction 邊界,"
"不 push branch、不建立或更新 Gitea PR、不留言、不 auto merge、不觸發 workflow、不改 CI、"
"不寫 lockfile、不升級套件、不 build/pull image、不改 production route、不發 Telegram、"
"不讀取 secret、不回傳工作視窗對話內容。"
),
)
async def get_agent_gitea_pr_draft_lane() -> dict[str, Any]:
"""Return the latest read-only AI Agent Gitea PR draft lane policy."""
try:
return await asyncio.to_thread(load_latest_ai_agent_gitea_pr_draft_lane)
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("ai_agent_gitea_pr_draft_lane_invalid", error=str(exc))
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="AI Agent Gitea PR 草案 lane 無效",
) from exc
@router.get(
"/runtime-surface-inventory",
response_model=dict[str, Any],

View File

@@ -0,0 +1,300 @@
"""
AI Agent Gitea PR draft lane snapshot.
Loads the latest committed, read-only policy for AI Agent generated Gitea PR
draft plans. This module never pushes branches, creates PRs, edits workflows,
writes lockfiles, upgrades packages, triggers CI, sends Telegram messages, or
exposes work-window transcripts.
"""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
from src.services.snapshot_paths import default_evaluations_dir
_DEFAULT_EVALUATIONS_DIR = default_evaluations_dir(Path(__file__))
_SNAPSHOT_PATTERN = "ai_agent_gitea_pr_draft_lane_*.json"
_SCHEMA_VERSION = "ai_agent_gitea_pr_draft_lane_v1"
_RUNTIME_AUTHORITY = "draft_lane_only_no_pr_creation_or_branch_push"
_TRANSCRIPT_MARKERS = {
"# In app browser",
"My request for Codex",
"Current URL:",
"AGENTS.md instructions",
"<environment_context>",
"批准!繼續",
}
def load_latest_ai_agent_gitea_pr_draft_lane(
evaluations_dir: Path | None = None,
) -> dict[str, Any]:
"""Load the newest committed AI Agent Gitea PR draft lane policy."""
directory = evaluations_dir or _DEFAULT_EVALUATIONS_DIR
candidates = sorted(directory.glob(_SNAPSHOT_PATTERN))
if not candidates:
raise FileNotFoundError(f"no AI Agent Gitea PR draft lane snapshots 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_rollup_consistency(payload, str(latest))
_require_grouping_and_checks(payload, str(latest))
_require_owner_and_rollback_contracts(payload, str(latest))
_require_template_redaction(payload, str(latest))
_require_no_plaintext_secret_payload_keys(payload, str(latest))
_require_no_conversation_transcript_content(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:
program_status = payload.get("program_status") or {}
if program_status.get("read_only_mode") is not True:
raise ValueError(f"{label}: program_status.read_only_mode must be true")
if program_status.get("runtime_authority") != _RUNTIME_AUTHORITY:
raise ValueError(f"{label}: runtime_authority must stay {_RUNTIME_AUTHORITY}")
operation_boundaries = payload.get("operation_boundaries") or {}
if operation_boundaries.get("read_only_lane_allowed") is not True:
raise ValueError(f"{label}: read_only_lane_allowed must be true")
blocked_operation_flags = {
"gitea_branch_push_allowed",
"gitea_pr_creation_allowed",
"gitea_pr_update_allowed",
"gitea_pr_comment_allowed",
"auto_merge_allowed",
"workflow_trigger_allowed",
"ci_workflow_change_allowed",
"lockfile_write_allowed",
"package_upgrade_allowed",
"file_mutation_allowed",
"external_registry_lookup_allowed",
"vulnerability_database_download_allowed",
"docker_build_allowed",
"image_pull_allowed",
"production_route_change_allowed",
"telegram_direct_send_allowed",
"telegram_gateway_queue_write_allowed",
"secret_plaintext_allowed",
"conversation_transcript_allowed",
}
allowed_operation_flags = sorted(
flag
for flag in blocked_operation_flags
if operation_boundaries.get(flag) is not False
)
if allowed_operation_flags:
raise ValueError(
f"{label}: operation boundaries must remain false: {allowed_operation_flags}"
)
approval_boundaries = payload.get("approval_boundaries") or {}
allowed_approval_flags = sorted(
flag for flag, value in approval_boundaries.items() if value is not False
)
if allowed_approval_flags:
raise ValueError(
f"{label}: approval boundaries must remain false: {allowed_approval_flags}"
)
def _require_rollup_consistency(payload: dict[str, Any], label: str) -> None:
grouping_rules = payload.get("grouping_rules") or []
lane_steps = payload.get("lane_steps") or []
required_checks = payload.get("required_checks") or []
owner_requirements = payload.get("owner_response_requirements") or []
rollback_requirements = payload.get("rollback_requirements") or []
templates = payload.get("draft_templates") or []
rollups = payload.get("rollups") or {}
expected_counts = {
"grouping_rule_count": len(grouping_rules),
"lane_step_count": len(lane_steps),
"required_check_count": len(required_checks),
"owner_response_requirement_count": len(owner_requirements),
"rollback_requirement_count": len(rollback_requirements),
"draft_template_count": len(templates),
}
mismatched = {
key: {"expected": expected, "actual": rollups.get(key)}
for key, expected in expected_counts.items()
if rollups.get(key) != expected
}
if mismatched:
raise ValueError(f"{label}: rollup counts must match payload sections: {mismatched}")
expected_group_ids = sorted(rule.get("group_id") for rule in grouping_rules)
if sorted(rollups.get("draft_group_ids") or []) != expected_group_ids:
raise ValueError(f"{label}: rollups.draft_group_ids mismatch")
expected_owner_ids = sorted(
requirement.get("requirement_id") for requirement in owner_requirements
)
if sorted(rollups.get("owner_response_requirement_ids") or []) != expected_owner_ids:
raise ValueError(f"{label}: rollups.owner_response_requirement_ids mismatch")
zero_rollups = {
"gitea_branch_push_allowed_count",
"gitea_pr_creation_allowed_count",
"auto_merge_allowed_count",
"workflow_trigger_allowed_count",
"lockfile_write_allowed_count",
"telegram_direct_send_allowed_count",
"conversation_transcript_allowed_count",
}
nonzero = sorted(key for key in zero_rollups if rollups.get(key) != 0)
if nonzero:
raise ValueError(f"{label}: draft lane safety counters must remain 0: {nonzero}")
def _require_grouping_and_checks(payload: dict[str, Any], label: str) -> None:
unsafe_groups = [
rule.get("group_id")
for rule in payload.get("grouping_rules") or []
if rule.get("draft_only") is not True
or rule.get("automerge") is not False
or rule.get("requires_openclaw_review") is not True
or rule.get("rollback_required") is not True
or not rule.get("required_check_ids")
or not isinstance(rule.get("max_batch_size"), int)
or rule.get("max_batch_size", 0) < 1
]
if unsafe_groups:
raise ValueError(f"{label}: grouping rules must stay draft-only and gated: {unsafe_groups}")
check_ids = {check.get("check_id") for check in payload.get("required_checks") or []}
unknown_check_refs = sorted(
{
check_id
for rule in payload.get("grouping_rules") or []
for check_id in rule.get("required_check_ids") or []
if check_id not in check_ids
}
)
if unknown_check_refs:
raise ValueError(f"{label}: grouping rules reference unknown checks: {unknown_check_refs}")
unsafe_checks = [
check.get("check_id")
for check in payload.get("required_checks") or []
if check.get("blocking") is not True
or check.get("evidence_required") is not True
or check.get("run_now_allowed") is not False
]
if unsafe_checks:
raise ValueError(f"{label}: required checks must be blocking evidence-only: {unsafe_checks}")
unsafe_steps = [
step.get("step_id")
for step in payload.get("lane_steps") or []
if step.get("runtime_execution_allowed") is not False
or step.get("repo_write_allowed") is not False
or not step.get("planned_output")
]
if unsafe_steps:
raise ValueError(f"{label}: lane steps must remain read-only plans: {unsafe_steps}")
def _require_owner_and_rollback_contracts(payload: dict[str, Any], label: str) -> None:
required_owner_fields = {
"owner",
"decision",
"business_impact",
"risk_acceptance",
"rollback_acceptance",
"maintenance_window",
"evidence_ref",
}
actual_owner_fields = {
field
for requirement in payload.get("owner_response_requirements") or []
for field in requirement.get("required_fields") or []
}
if not required_owner_fields.issubset(actual_owner_fields):
raise ValueError(f"{label}: owner response requirements missing required fields")
unsafe_rollback = [
item.get("requirement_id")
for item in payload.get("rollback_requirements") or []
if item.get("required") is not True
or item.get("must_be_attached_before_pr_creation") is not True
]
if unsafe_rollback:
raise ValueError(f"{label}: rollback requirements must be attached before PR: {unsafe_rollback}")
def _require_template_redaction(payload: dict[str, Any], label: str) -> None:
forbidden_fields = {
"secret_value",
"token",
"authorization_header",
"work_window_transcript",
"codex_user_message",
"prompt_text",
"chain_of_thought",
"session_id",
"browser_context",
}
for template in payload.get("draft_templates") or []:
template_id = template.get("template_id")
if template.get("automerge") is not False:
raise ValueError(f"{label}: draft template must keep automerge=false: {template_id}")
if template.get("branch_push_allowed") is not False:
raise ValueError(f"{label}: draft template must not allow branch push: {template_id}")
if not forbidden_fields.issubset(set(template.get("forbidden_fields") or [])):
raise ValueError(f"{label}: draft template missing redaction fields: {template_id}")
display = payload.get("display_redaction_contract") or {}
if display.get("conversation_transcript_display_allowed") is not False:
raise ValueError(f"{label}: conversation transcript display must remain false")
if display.get("redaction_required") is not True:
raise ValueError(f"{label}: display redaction must be required")
def _require_no_plaintext_secret_payload_keys(value: Any, label: str, path: str = "$") -> None:
if isinstance(value, dict):
forbidden_key_fragments = {
"secret_value",
"token_plaintext",
"authorization_header",
"private_key",
"credential_value",
}
for key, nested in value.items():
normalized_key = str(key).lower()
if any(fragment in normalized_key for fragment in forbidden_key_fragments):
raise ValueError(f"{label}: forbidden plaintext secret key at {path}.{key}")
_require_no_plaintext_secret_payload_keys(nested, label, f"{path}.{key}")
elif isinstance(value, list):
for index, nested in enumerate(value):
_require_no_plaintext_secret_payload_keys(nested, label, f"{path}[{index}]")
def _require_no_conversation_transcript_content(value: Any, label: str, path: str = "$") -> None:
if isinstance(value, str):
for marker in _TRANSCRIPT_MARKERS:
if marker in value:
raise ValueError(
f"{label}: forbidden work-window conversation content at {path}: {marker}"
)
elif isinstance(value, dict):
for key, nested in value.items():
_require_no_conversation_transcript_content(nested, label, f"{path}.{key}")
elif isinstance(value, list):
for index, nested in enumerate(value):
_require_no_conversation_transcript_content(nested, label, f"{path}[{index}]")

View File

@@ -0,0 +1,113 @@
from __future__ import annotations
import json
import pytest
from src.services.ai_agent_gitea_pr_draft_lane import (
load_latest_ai_agent_gitea_pr_draft_lane,
)
def test_load_latest_ai_agent_gitea_pr_draft_lane_reads_committed_snapshot():
data = load_latest_ai_agent_gitea_pr_draft_lane()
assert data["schema_version"] == "ai_agent_gitea_pr_draft_lane_v1"
assert data["program_status"]["overall_completion_percent"] == 78
assert data["program_status"]["current_task_id"] == "P2-402E"
assert data["program_status"]["next_task_id"] == "P2-402F"
assert data["program_status"]["read_only_mode"] is True
assert data["program_status"]["runtime_authority"] == (
"draft_lane_only_no_pr_creation_or_branch_push"
)
assert data["branch_strategy"]["branch_push_allowed"] is False
assert data["branch_strategy"]["pr_creation_allowed"] is False
assert data["branch_strategy"]["automerge"] is False
assert data["operation_boundaries"]["gitea_branch_push_allowed"] is False
assert data["operation_boundaries"]["gitea_pr_creation_allowed"] is False
assert data["operation_boundaries"]["workflow_trigger_allowed"] is False
assert data["operation_boundaries"]["lockfile_write_allowed"] is False
assert data["operation_boundaries"]["telegram_direct_send_allowed"] is False
assert data["operation_boundaries"]["conversation_transcript_allowed"] is False
assert data["approval_boundaries"]["gitea_pr_creation_approved"] is False
assert data["rollups"]["grouping_rule_count"] == len(data["grouping_rules"]) == 6
assert data["rollups"]["lane_step_count"] == len(data["lane_steps"]) == 7
assert data["rollups"]["required_check_count"] == len(data["required_checks"]) == 9
assert data["rollups"]["draft_template_count"] == len(data["draft_templates"]) == 4
assert data["rollups"]["gitea_branch_push_allowed_count"] == 0
assert data["rollups"]["gitea_pr_creation_allowed_count"] == 0
assert data["rollups"]["auto_merge_allowed_count"] == 0
assert data["rollups"]["workflow_trigger_allowed_count"] == 0
assert data["rollups"]["lockfile_write_allowed_count"] == 0
assert data["rollups"]["telegram_direct_send_allowed_count"] == 0
assert data["rollups"]["conversation_transcript_allowed_count"] == 0
assert all(rule["automerge"] is False for rule in data["grouping_rules"])
assert all(template["branch_push_allowed"] is False for template in data["draft_templates"])
def test_ai_agent_gitea_pr_draft_lane_blocks_pr_creation(tmp_path):
snapshot = _snapshot()
snapshot["operation_boundaries"]["gitea_pr_creation_allowed"] = True
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="operation boundaries"):
load_latest_ai_agent_gitea_pr_draft_lane(tmp_path)
def test_ai_agent_gitea_pr_draft_lane_rejects_rollup_mismatch(tmp_path):
snapshot = _snapshot()
snapshot["rollups"]["grouping_rule_count"] = 99
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="rollup counts"):
load_latest_ai_agent_gitea_pr_draft_lane(tmp_path)
def test_ai_agent_gitea_pr_draft_lane_rejects_automerge(tmp_path):
snapshot = _snapshot()
snapshot["grouping_rules"][0]["automerge"] = True
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="draft-only"):
load_latest_ai_agent_gitea_pr_draft_lane(tmp_path)
def test_ai_agent_gitea_pr_draft_lane_rejects_non_blocking_check(tmp_path):
snapshot = _snapshot()
snapshot["required_checks"][0]["blocking"] = False
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="blocking evidence-only"):
load_latest_ai_agent_gitea_pr_draft_lane(tmp_path)
def test_ai_agent_gitea_pr_draft_lane_requires_owner_response_fields(tmp_path):
snapshot = _snapshot()
snapshot["owner_response_requirements"][0]["required_fields"] = ["owner"]
snapshot["owner_response_requirements"][1]["required_fields"] = ["owner"]
snapshot["owner_response_requirements"][2]["required_fields"] = ["owner"]
snapshot["owner_response_requirements"][3]["required_fields"] = ["owner"]
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="owner response requirements"):
load_latest_ai_agent_gitea_pr_draft_lane(tmp_path)
def test_ai_agent_gitea_pr_draft_lane_rejects_transcript_markers(tmp_path):
snapshot = _snapshot()
snapshot["lane_intent"]["purpose"] = "禁止放入 My request for Codex"
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="forbidden work-window conversation content"):
load_latest_ai_agent_gitea_pr_draft_lane(tmp_path)
def _write_snapshot(tmp_path, snapshot: dict) -> None:
(tmp_path / "ai_agent_gitea_pr_draft_lane_2026-06-11.json").write_text(
json.dumps(snapshot),
encoding="utf-8",
)
def _snapshot() -> dict:
return json.loads(json.dumps(load_latest_ai_agent_gitea_pr_draft_lane()))

View File

@@ -0,0 +1,51 @@
from __future__ import annotations
import json
from fastapi import FastAPI
from fastapi.testclient import TestClient
from src.api.v1.agents import router
def test_agent_gitea_pr_draft_lane_endpoint_returns_committed_snapshot():
app = FastAPI()
app.include_router(router, prefix="/api/v1")
client = TestClient(app)
response = client.get("/api/v1/agents/agent-gitea-pr-draft-lane")
assert response.status_code == 200
data = response.json()
assert data["schema_version"] == "ai_agent_gitea_pr_draft_lane_v1"
assert data["program_status"]["overall_completion_percent"] == 78
assert data["program_status"]["current_task_id"] == "P2-402E"
assert data["program_status"]["next_task_id"] == "P2-402F"
assert data["program_status"]["read_only_mode"] is True
assert data["branch_strategy"]["branch_push_allowed"] is False
assert data["branch_strategy"]["pr_creation_allowed"] is False
assert data["branch_strategy"]["automerge"] is False
assert data["operation_boundaries"]["gitea_branch_push_allowed"] is False
assert data["operation_boundaries"]["gitea_pr_creation_allowed"] is False
assert data["operation_boundaries"]["workflow_trigger_allowed"] is False
assert data["operation_boundaries"]["lockfile_write_allowed"] is False
assert data["operation_boundaries"]["telegram_direct_send_allowed"] is False
assert data["operation_boundaries"]["conversation_transcript_allowed"] is False
assert data["approval_boundaries"]["gitea_pr_creation_approved"] is False
assert data["rollups"]["grouping_rule_count"] == 6
assert data["rollups"]["lane_step_count"] == 7
assert data["rollups"]["required_check_count"] == 9
assert data["rollups"]["draft_template_count"] == 4
assert data["rollups"]["gitea_pr_creation_allowed_count"] == 0
assert data["rollups"]["auto_merge_allowed_count"] == 0
assert data["rollups"]["workflow_trigger_allowed_count"] == 0
serialized = json.dumps(data, ensure_ascii=False)
for marker in [
"批准!繼續",
"My request for Codex",
"Current URL:",
"# In app browser",
"AGENTS.md instructions",
]:
assert marker not in serialized

View File

@@ -13,9 +13,9 @@ def test_load_latest_ai_agent_proactive_operations_contract_reads_committed_snap
data = load_latest_ai_agent_proactive_operations_contract()
assert data["schema_version"] == "ai_agent_proactive_operations_contract_v1"
assert data["program_status"]["overall_completion_percent"] == 68
assert data["program_status"]["current_task_id"] == "P2-402D"
assert data["program_status"]["next_task_id"] == "P2-402E"
assert data["program_status"]["overall_completion_percent"] == 78
assert data["program_status"]["current_task_id"] == "P2-402E"
assert data["program_status"]["next_task_id"] == "P2-402F"
assert data["program_status"]["read_only_mode"] is True
assert data["program_status"]["runtime_authority"] == "contract_only_no_version_or_runtime_update"
assert data["approval_boundaries"]["runtime_version_update_allowed"] is False

View File

@@ -16,9 +16,9 @@ def test_ai_agent_proactive_operations_contract_endpoint_returns_committed_snaps
assert response.status_code == 200
data = response.json()
assert data["schema_version"] == "ai_agent_proactive_operations_contract_v1"
assert data["program_status"]["overall_completion_percent"] == 68
assert data["program_status"]["current_task_id"] == "P2-402D"
assert data["program_status"]["next_task_id"] == "P2-402E"
assert data["program_status"]["overall_completion_percent"] == 78
assert data["program_status"]["current_task_id"] == "P2-402E"
assert data["program_status"]["next_task_id"] == "P2-402F"
assert data["program_status"]["read_only_mode"] is True
assert data["approval_boundaries"]["runtime_version_update_allowed"] is False
assert data["approval_boundaries"]["package_upgrade_allowed"] is False

View File

@@ -1,3 +1,28 @@
## 2026-06-11P2-402E AI Agent Gitea PR 草案 lane
**背景**P2-402D 已把 Telegram action-required digest policy 固定成只讀資料契約;下一步需要讓 AI Agent 可以主動整理版本更新、工具採用、CVE / OSV、container image、AI Agent contract、host / K3s / stateful maintenance 與 docs / KM 的 Gitea PR 草案,但仍不可直接 push branch、建立 PR 或觸發 workflow。
**本輪完成**
- 新增 `docs/schemas/ai_agent_gitea_pr_draft_lane_v1.schema.json`
- 新增 `docs/evaluations/ai_agent_gitea_pr_draft_lane_2026-06-11.json`6 條 grouping rule、7 個 lane step、9 個 required check、4 個 owner response requirement、6 條 rollback requirement、4 個 draft template。
- 新增 `apps/api/src/services/ai_agent_gitea_pr_draft_lane.py`,強制驗證 read-only mode、branch push / PR creation / workflow trigger / lockfile / package upgrade / auto merge / Telegram direct send 全部 false。
- 新增 `GET /api/v1/agents/agent-gitea-pr-draft-lane`
- 新增 loader / API 測試,覆蓋 PR creation boundary、automerge boundary、required check、owner response、rollup consistency、工作視窗內容 redaction。
- 更新 `ai_agent_proactive_operations_contract_2026-06-11.json`:整體完成度 `78%`current task `P2-402E`next task `P2-402F`
- 同步 `AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md``AI_AGENT_PROACTIVE_OPERATIONS_2026-06-11.md``AI_AGENT_TOOL_ADOPTION_APPROVAL_PACKAGE_2026-06-11.md``AI_AGENT_TELEGRAM_ACTION_REQUIRED_DIGEST_POLICY_2026-06-11.md` 與 MASTER §3.2.1c / §5 / changelog。
**完成度同步**
- P2-402E`100%`
- AI Agent 主動營運委派與版本生命週期:`78%`
- Current task`P2-402E`
- Next task`P2-402F` host OS / K3s / stateful services 版本只讀盤點。
**邊界**
- 本波仍不 push branch、不建立或更新 Gitea PR、不留言、不 auto merge、不觸發 workflow、不改 CI、不寫 lockfile、不升級套件、不 build / pull image、不改 production route、不發 Telegram、不讀取或輸出 secret、不回傳工作視窗對話內容。
## 2026-06-11IwoooS 高價值配置 Owner Packet 接入 AwoooP 首頁
**背景**P0.4 已把高價值配置 owner packet 草案接到 `/zh-TW/iwooos`。本階段把同一個只讀狀態鏡像到 `/zh-TW/awooop` 首頁,讓 AwoooP 工作視窗能看到 IwoooS 產生的配置 owner packet 草案,但仍不得把「可見」解讀成 request 已送出、owner 已回覆、owner 已接受或 runtime 已開。

View File

@@ -13,7 +13,7 @@
| 工具 / 服務 / 套件 AI 自動化 | 92% | P0 已完成P1 服務 / runtime / 監控 / provider / service health / 備份 / DR / 套件與供應鏈只讀基線已完成P1-007 失敗限定通知合約與前端 redaction 合約已完成;下一主線是 P2-004 依賴 / 供應鏈漂移監控 | 狀態分類、盤點 schema、權限矩陣、靜態盤點種子、只讀 API、UI 骨架、驗證、自動化待辦 schema / 快照 / API / 分組 UI、Backup / DR 目標盤點、準備度矩陣、備份通知政策、Backup / DR 證據 UI、復原演練批准包模板、異地 / escrow 準備度狀態、任務批准邊界、確定性進度彙總、Python 套件 / 供應鏈只讀基線、JS pnpm/npm 只讀基線、Docker build surface 只讀基線、CVE / license / drift 嚴重度政策、定期依賴漂移與外部資料來源檢查設計、依賴升級批准包模板、runtime_surface_inventory_v1 schema / snapshot / API / UI、gitea_workflow_runner_health_v1 schema / snapshot / API / UI、observability_contract_matrix_v1 schema / snapshot / API / UI、ai_provider_route_matrix_v1 schema / snapshot / API / UI、service_health_gap_matrix_v1 schema / snapshot / API / UI、service health evidence cards UI、service_health_failure_notification_policy_v1 schema / snapshot / API / UI 已完成 |
| OpenClaw / Hermes / NemoTron 佈建布局 | 45% | P1-401 / P1-402 已完成;仍是只讀 layout 與治理頁顯示,不是 runtime deploy | `ai_agent_deployment_layout_v1` schema、`ai_agent_deployment_layout_2026-06-11.json``GET /api/v1/agents/agent-deployment-layout`、治理頁自動化盤點 UI、`AI_AGENT_DEPLOYMENT_LAYOUT_2026-06-11.md` |
| OpenClaw / Hermes / NemoTron 主動溝通與學習契約 | 35% | P2-401A 已完成只讀 contractruntime worker、DB migration、Telegram 實發、SDK / 付費服務仍未開 gate | `ai_agent_communication_learning_contract_v1` schema、`ai_agent_communication_learning_contract_2026-06-11.json``GET /api/v1/agents/agent-communication-learning-contract`、MASTER §3.2.1b / §3.4.3 |
| AI Agent 主動營運委派與版本生命週期 | 68% | P2-402A / P2-402B / P2-402C / P2-402D 已完成;已建立 repo-only 版本新鮮度快照、工具採用批准包、Telegram action-required digest policy 與 API。定期排程、外部版本查詢、工具安裝、CI 變更、套件升級、主機更新、container pull、auto merge、Telegram 實發仍未開 gate | `ai_agent_proactive_operations_contract_v1``ai_agent_version_freshness_snapshot_v1``ai_agent_tool_adoption_approval_package_v1``ai_agent_telegram_action_required_digest_policy_v1``GET /api/v1/agents/agent-proactive-operations-contract``GET /api/v1/agents/agent-version-freshness-snapshot``GET /api/v1/agents/agent-tool-adoption-approval-package``GET /api/v1/agents/agent-telegram-action-required-digest-policy`、MASTER §3.2.1c |
| AI Agent 主動營運委派與版本生命週期 | 78% | P2-402A / P2-402B / P2-402C / P2-402D / P2-402E 已完成;已建立 repo-only 版本新鮮度快照、工具採用批准包、Telegram action-required digest policy、Gitea PR 草案 lane 與 API。定期排程、外部版本查詢、工具安裝、CI 變更、套件升級、主機更新、container pull、實際 PR creation、auto merge、Telegram 實發仍未開 gate | `ai_agent_proactive_operations_contract_v1``ai_agent_version_freshness_snapshot_v1``ai_agent_tool_adoption_approval_package_v1``ai_agent_telegram_action_required_digest_policy_v1``ai_agent_gitea_pr_draft_lane_v1``GET /api/v1/agents/agent-proactive-operations-contract``GET /api/v1/agents/agent-version-freshness-snapshot``GET /api/v1/agents/agent-tool-adoption-approval-package``GET /api/v1/agents/agent-telegram-action-required-digest-policy``GET /api/v1/agents/agent-gitea-pr-draft-lane`MASTER §3.2.1c |
| 本工作清單與分析報告 | 100% | 已完成 | 本 MD 文件 |
AI Agent 自動化工作包目前完成度:**92%**。本工作清單文件本身完成度:**100%**。
@@ -22,7 +22,7 @@ AI Agent 自動化工作包目前完成度:**92%**。本工作清單文件本
三 Agent 主動溝通與學習契約目前完成度:**35%**。已完成只讀 schema / snapshot / API / 測試與 MASTER 同步;下一步依優先順序推 `P2-401B` AgentSession / Redis Streams migration 與 worker gate但在批准前仍不得啟動 runtime loop。
AI Agent 主動營運委派與版本生命週期目前完成度:**68%**。已完成 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory、只讀 API、`P2-402B` repo-only daily version freshness snapshot、`P2-402C` Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包,以及 `P2-402D` Telegram action-required digest policy;下一步是 `P2-402E` Gitea PR 草案 lane外部 registry / package source / host probe / 工具安裝 / CI 變更 / Telegram 實發仍需 gate。
AI Agent 主動營運委派與版本生命週期目前完成度:**78%**。已完成 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory、只讀 API、`P2-402B` repo-only daily version freshness snapshot、`P2-402C` Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包`P2-402D` Telegram action-required digest policy,以及 `P2-402E` Gitea PR 草案 lane;下一步是 `P2-402F` host OS / K3s / stateful services 版本只讀盤點,外部 registry / package source / host probe / 工具安裝 / CI 變更 / 實際 PR creation / Telegram 實發仍需 gate。
完成度計算模型:
@@ -955,7 +955,7 @@ UI
| P2-402B | 完成 | 100 | Hermes | 建立 repo-only daily version freshness snapshot | `ai_agent_version_freshness_snapshot_v1` / snapshot / 只讀 API / 測試12 類 repo-only source、5 個 daily step、3 Agent role | 只讀workflow schedule 未啟用、外部 lookup 未開、不得升級或發 Telegram |
| P2-402C | 完成 | 100 | OpenClaw | 建立 Renovate / OSV-Scanner / Trivy / Syft / Grype 工具採用批准包 | `ai_agent_tool_adoption_approval_package_v1` / snapshot / 只讀 API / 測試5 工具、5 官方來源、4 採用 lane、6 批准欄位 | 只讀tool install、CI change、external lookup、vulnerability DB、PR、Telegram 全部未啟用 |
| P2-402D | 完成 | 100 | OpenClaw | 建立 Telegram action-required digest policy | `ai_agent_telegram_action_required_digest_policy_v1` / snapshot / 只讀 API / 測試8 條 digest rule、3 個 channel 草案、5 類 trigger category、成功降噪與 redaction policy | 只讀Telegram send、Gateway queue write、route / receiver change、workflow、runtime 全部未啟用 |
| P2-402E | 待辦 | 0 | Hermes | 設計 Gitea PR 草案 lane | grouping、automerge=false、tests、rollback、owner response | bot / branch policy approval |
| P2-402E | 完成 | 100 | Hermes | 設計 Gitea PR 草案 lane | `ai_agent_gitea_pr_draft_lane_v1` / snapshot / 只讀 API / 測試6 條 grouping rule、7 個 lane step、9 個 required check、6 條 rollback requirement、4 個 draft template | 只讀branch push、PR creation、workflow trigger、lockfile、package upgrade、auto merge、Telegram 全部未啟用 |
| P2-402F | 待辦 | 0 | OpenClaw | 建立 host OS / K3s / stateful services 版本只讀盤點 | host / K3s / DB / Redis / MinIO / Gitea 版本矩陣 | host readonly probe + maintenance window approval |
| P2-402G | 待辦 | 0 | Hermes | 接入 governance UI 顯示可委派能力 | 自主等級、gate、owner、Telegram policy | frontend UI change approval |
| P2-101 | 待辦 | 0 | OpenClaw | 定義操作類別權限模型 | 操作政策 schema | HITL 關卡 |

View File

@@ -0,0 +1,72 @@
# AI Agent Gitea PR 草案 Lane 工作報告
> 日期2026-06-11台北時間
> 狀態P2-402E 已完成;整體 AI Agent 主動營運與版本生命週期完成度 78%。
> 邊界:本文件與對應 API 只提供 Gitea PR 草案 lane不 push branch、不建立或更新 Gitea PR、不留言、不 auto merge、不觸發 workflow、不改 CI、不寫 lockfile、不升級套件、不 build / pull image、不發 Telegram、不顯示工作視窗對話內容。
## 1. 本波完成項目
| 項目 | 狀態 | 產出 |
|---|---|---|
| Gitea PR 草案 lane schema | 完成 | `docs/schemas/ai_agent_gitea_pr_draft_lane_v1.schema.json` |
| Gitea PR 草案 lane snapshot | 完成 | `docs/evaluations/ai_agent_gitea_pr_draft_lane_2026-06-11.json` |
| API loader | 完成 | `apps/api/src/services/ai_agent_gitea_pr_draft_lane.py` |
| 只讀 API | 完成 | `GET /api/v1/agents/agent-gitea-pr-draft-lane` |
| 測試 | 完成 | loader / API / PR creation boundary / automerge boundary / blocking checks / owner response / transcript redaction |
| 主契約同步 | 完成 | `ai_agent_proactive_operations_contract_v1` 完成度 78%current `P2-402E`next `P2-402F` |
## 2. Grouping 規則摘要
| Group | 主責 Agent | 風險 | Max batch | 邊界 |
|---|---|---:|---:|---|
| 低風險依賴 patch 草案 | Hermes | medium | 5 | draft-only、automerge=false、需 OpenClaw review |
| CVE / OSV 修補草案 | OpenClaw | high | 2 | 不查外部 DB、不升級套件、不 hot patch |
| Container image digest / base image 草案 | Hermes | high | 2 | 不 build、不 pull、不改 kustomization image tag |
| AI Agent / model / tool contract 草案 | NemoTron + OpenClaw | critical | 1 | 需 sanitized replay gate不開 shadow / canary |
| Host / K3s / stateful maintenance 草案 | OpenClaw | critical | 1 | 不 host upgrade、不 reboot、不 restart stateful service |
| 文件 / runbook / KM 草案 | Hermes | low | 8 | 不發布 canonical KM、不放 secret 或工作視窗內容 |
## 3. PR 前必備證據
| 類別 | 必備內容 |
|---|---|
| 測試 | schema / JSON、targeted tests、secret 與 transcript redaction |
| 風險 | blast radius、OpenClaw review、是否拆分 PR |
| Rollback | git revert、config recovery、runtime disable switch、smoke 失敗回退 |
| Owner response | owner、decision、business impact、risk acceptance、rollback acceptance、maintenance window、evidence ref |
| AI / model | sanitized replay gate、hidden-label grading、不得自行批准上線 |
## 4. Agent 分工
| Agent | 本波可做 | 本波不可做 |
|---|---|---|
| Hermes | 彙整 committed evidence、分組、release note、test plan、draft PR packet | push branch、建立 PR、觸發 workflow、寫 lockfile |
| OpenClaw | 仲裁風險、rollback、owner response、HITL、是否拆 PR | 自行批准、merge PR、runtime execution、production route change |
| NemoTron | 對 AI Agent / model / prompt / tool contract 變更提出 sanitized replay gate | 呼叫付費 API、外部 replay、shadow / canary、生產路由 |
## 5. 仍維持 false 的邊界
- `gitea_branch_push_allowed=false`
- `gitea_pr_creation_allowed=false`
- `gitea_pr_update_allowed=false`
- `gitea_pr_comment_allowed=false`
- `auto_merge_allowed=false`
- `workflow_trigger_allowed=false`
- `ci_workflow_change_allowed=false`
- `lockfile_write_allowed=false`
- `package_upgrade_allowed=false`
- `docker_build_allowed=false`
- `image_pull_allowed=false`
- `telegram_direct_send_allowed=false`
- `telegram_gateway_queue_write_allowed=false`
- `secret_plaintext_allowed=false`
- `conversation_transcript_allowed=false`
## 6. 下一步代辦
| 優先 | ID | 工作 | 完成標準 |
|---:|---|---|---|
| 1 | P2-402F | host OS / K3s / stateful services 版本只讀盤點 | 主機、K3s、PostgreSQL、Redis、MinIO、Harbor、Gitea 版本矩陣;只讀 probe / maintenance approval |
| 2 | P2-402G | Governance UI 顯示可委派能力 | 前端顯示 autonomy level、gate、owner、Telegram policy無執行按鈕 |
| 3 | 候選池 | Gitea bot / branch policy approval package | bot account、branch naming、PR permission、rollback、audit trail |
| 4 | 候選池 | Draft PR packet renderer | 把 grouping / test / rollback / owner response 轉為可審核 PR 草案,不呼叫 Gitea API |

View File

@@ -1,7 +1,7 @@
# AI Agent 主動營運委派與版本生命週期分析報告
> 日期2026-06-11台北時間
> 文件定位P2-402A / P2-402B / P2-402C / P2-402D 只讀契約摘要。權威細節以 MASTER §3.2.1c、`ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`ai_agent_tool_adoption_approval_package_v1``ai_agent_telegram_action_required_digest_policy_v1` 為準。
> 文件定位P2-402A / P2-402B / P2-402C / P2-402D / P2-402E 只讀契約摘要。權威細節以 MASTER §3.2.1c、`ai_agent_proactive_operations_contract_v1`、`ai_agent_version_freshness_snapshot_v1`、`ai_agent_tool_adoption_approval_package_v1``ai_agent_telegram_action_required_digest_policy_v1` 與 `ai_agent_gitea_pr_draft_lane_v1` 為準。
## 1. 本波完成度
@@ -11,7 +11,8 @@
| Repo-only 版本新鮮度快照 | 100% | P2-402B 已完成 schema / committed snapshot / API / 測試 |
| 工具採用批准包 | 100% | P2-402C 已完成 Renovate / OSV-Scanner / Trivy / Syft / Grype schema / committed snapshot / API / 測試 |
| Telegram action-required digest policy | 100% | P2-402D 已完成 critical / action-required / failure-only digest schema / committed snapshot / API / 測試 |
| 整體主動營運與版本生命週期 | 68% | 已完成架構、repo-only freshness、工具採用批准包與 Telegram digest policyruntime 排程、工具安裝、CI 變更與更新仍未開 gate |
| Gitea PR 草案 lane | 100% | P2-402E 已完成 grouping、automerge=false、測試證據、rollback、owner response schema / committed snapshot / API / 測試 |
| 整體主動營運與版本生命週期 | 78% | 已完成架構、repo-only freshness、工具採用批准包、Telegram digest policy 與 Gitea PR 草案 laneruntime 排程、工具安裝、CI 變更、實際 PR 建立與更新仍未開 gate |
## 2. 可交給 AI Agent 的工作分類
@@ -42,6 +43,9 @@
| `docs/schemas/ai_agent_telegram_action_required_digest_policy_v1.schema.json` | Telegram action-required digest policy schemadirect send、queue write、route / receiver change、workflow、transcript 全部預設 false |
| `docs/evaluations/ai_agent_telegram_action_required_digest_policy_2026-06-11.json` | 8 條 digest rule、3 個 channel 草案、5 類 trigger category、成功降噪、redaction、fallback policy |
| `GET /api/v1/agents/agent-telegram-action-required-digest-policy` | 只讀 API不送 Telegram、不寫 queue、不改 route / receiver、不觸發 workflow |
| `docs/schemas/ai_agent_gitea_pr_draft_lane_v1.schema.json` | Gitea PR 草案 lane schemabranch push、PR creation、workflow trigger、lockfile、automerge、Telegram 全部預設 false |
| `docs/evaluations/ai_agent_gitea_pr_draft_lane_2026-06-11.json` | 6 條 grouping rule、7 個 lane step、9 個 required check、6 條 rollback requirement、4 個 draft template |
| `GET /api/v1/agents/agent-gitea-pr-draft-lane` | 只讀 API不 push branch、不建立 PR、不觸發 workflow、不改 CI、不升級套件、不發 Telegram |
## 4. P2-402B Repo-only 版本新鮮度快照
@@ -78,12 +82,24 @@ P2-402C 的重點是把「哪些工具可被採用、採用前要填哪些批准
本波把「哪些事情值得通知」和「哪些成功訊息必須壓掉」固定成資料契約。Telegram Gateway queue write、direct send、route / receiver change、AwoooP event write、workflow trigger、runtime execution 仍全部為 false。
## 7. 下一步優先順序
## 7. P2-402E Gitea PR 草案 Lane
| 類別 | 本波定義 | 仍禁止 |
|---|---|---|
| Grouping | 6 條低風險依賴、CVE / OSV、container image、AI Agent contract、host / K3s / stateful、docs / KM | 不混入無關風險,不把 critical 變更和低風險 patch 同 PR |
| PR policy | `automerge=false`、draft-only、需 OpenClaw review、需 rollback | 不 push branch、不建立 / 更新 PR、不留言、不 merge |
| Tests | schema / JSON、targeted tests、secret / transcript redaction、vulnerability / image / replay / deployment evidence | 不觸發 workflow、不改 CI、不 build / pull image |
| Owner response | owner、decision、business impact、risk acceptance、rollback acceptance、maintenance window、evidence ref | 不用 Agent 自我批准取代 owner response |
| Redaction | 不顯示 secret、prompt、chain-of-thought、browser context、工作視窗對話內容 | 不把工作視窗對話放到前端或文件 |
P2-402E 的重點是先把「PR 草案要長什麼樣、要有哪些證據、誰要回覆、怎麼 rollback」固定成契約。它不是 Gitea bot 啟用bot account、branch policy、實際 PR creation、workflow trigger、lockfile write、package upgrade、Telegram 實發全部維持 blocked。
## 8. 下一步優先順序
| ID | 優先 | 任務 | 關卡 |
|---|---|---|---|
| P2-402D | 0 | Telegram action-required digest policy | 已完成只讀Telegram send / queue write 未啟用 |
| P2-402E | 1 | Gitea PR 草案 lane | bot / branch policy approval |
| P2-402E | 1 | Gitea PR 草案 lane | 已完成只讀branch push / PR creation / workflow trigger 未啟用 |
| P2-402F | 2 | host OS / K3s / stateful services 版本只讀盤點 | host probe / maintenance approval |
| P2-402G | 3 | governance UI 顯示可委派能力 | frontend UI approval |
@@ -95,6 +111,7 @@ P2-402C 的重點是把「哪些工具可被採用、採用前要填哪些批准
- `container_pull_allowed=false`
- `workflow_schedule_enabled=false`
- `auto_merge_allowed=false`
- `gitea_pr_creation_allowed=false`
- `telegram_direct_send_allowed=false`
- `secret_plaintext_allowed=false`
- `paid_external_service_allowed=false`

View File

@@ -49,7 +49,7 @@
| 優先 | ID | 工作 | 完成標準 |
|---:|---|---|---|
| 1 | P2-402E | Gitea PR 草案 lane | Renovate grouping、automerge=false、測試要求、rollback、owner responsebot / branch policy approval |
| 1 | P2-402E | Gitea PR 草案 lane | 已完成:Renovate grouping、automerge=false、測試要求、rollback、owner responsebot / branch policy 仍未批准 |
| 2 | P2-402F | host OS / K3s / stateful services 版本只讀盤點 | 主機、K3s、PostgreSQL、Redis、MinIO、Harbor、Gitea 只讀版本矩陣 |
| 3 | P2-402G | Governance UI 顯示可委派能力 | 前端顯示 autonomy level、gate、owner、Telegram policy無執行按鈕 |
| 4 | 候選池 | Telegram Gateway E2E 批准包 | queue write / send / callback / fallback path 的測試與 rollout gate |

View File

@@ -38,7 +38,7 @@
| 優先 | ID | 工作 | 完成標準 | 目前狀態 |
|---:|---|---|---|---|
| 1 | P2-402D | Telegram action-required digest policy | 定義 critical / action-required / failure-only禁止成功洗版接 Telegram Gateway E2E gate | 完成 |
| 2 | P2-402E | Gitea PR 草案 lane | Renovate grouping、automerge=false、測試要求、rollback、owner response | 待辦 |
| 2 | P2-402E | Gitea PR 草案 lane | Renovate grouping、automerge=false、測試要求、rollback、owner response | 完成 |
| 3 | P2-402F | host OS / K3s / stateful services 版本只讀盤點 | 主機、K3s、PostgreSQL、Redis、MinIO、Harbor、Gitea 只讀版本矩陣 | 待辦 |
| 4 | P2-402G | Governance UI 顯示可委派能力 | 前端顯示 autonomy level、gate、owner、Telegram policy無執行按鈕 | 待辦 |
| 5 | 候選池 | SBOM artifact policy | Syft / Trivy artifact 格式、保存、redaction、消費者規則 | 未排正式編號 |

View File

@@ -0,0 +1,694 @@
{
"schema_version": "ai_agent_gitea_pr_draft_lane_v1",
"generated_at": "2026-06-11T23:59:40+08:00",
"program_status": {
"overall_completion_percent": 78,
"current_priority": "P2",
"current_task_id": "P2-402E",
"next_task_id": "P2-402F",
"read_only_mode": true,
"runtime_authority": "draft_lane_only_no_pr_creation_or_branch_push",
"status_note": "P2-402E 已建立 Gitea PR 草案 lane本波只定義 grouping、automerge=false、測試證據、rollback、owner response不 push branch、不建立 PR、不觸發 workflow、不升級套件、不發 Telegram。"
},
"source_refs": [
"docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json",
"docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json",
"docs/evaluations/ai_agent_telegram_action_required_digest_policy_2026-06-11.json",
"docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md#321c-2026-06-11-ai-agent-主動營運委派與版本生命週期契約",
"docs/ai/AI_AGENT_AUTOMATION_WORKLIST_2026-06-04.md"
],
"lane_intent": {
"purpose": "讓 Hermes / OpenClaw / NemoTron 先產生可審核的 Gitea PR 草案計畫包含分組、風險、測試、rollback 與 owner response真正 branch push / PR creation 必須等 bot、branch policy 與人工批准。",
"non_goals": [
"不建立 Gitea branch",
"不建立或更新 Gitea PR",
"不修改 workflow",
"不升級 package 或 lockfile",
"不 build / pull container image",
"不觸發 CI workflow",
"不 auto merge",
"不送 Telegram"
],
"human_approval_gate": "gitea_bot_and_branch_policy_approval_required"
},
"branch_strategy": {
"draft_branch_prefix": "agents/proposal/",
"branch_name_pattern": "agents/proposal/{lane_id}/{yyyyMMdd}-{short_target}",
"branch_push_allowed": false,
"pr_creation_allowed": false,
"automerge": false,
"required_prefix_after_approval": "codex/"
},
"grouping_rules": [
{
"group_id": "dependency_patch_low_risk",
"display_name": "低風險依賴 patch 草案",
"owner_agent": "Hermes",
"risk_tier": "medium",
"max_batch_size": 5,
"draft_only": true,
"automerge": false,
"requires_openclaw_review": true,
"rollback_required": true,
"required_check_ids": [
"schema_and_json_validation",
"targeted_tests_plan",
"secret_and_transcript_redaction"
],
"allowed_change_kinds": [
"manifest proposal",
"lockfile proposal after approval",
"release note summary"
],
"blocked_change_kinds": [
"major version bump",
"security critical package",
"runtime config mutation"
]
},
{
"group_id": "security_cve_advisory",
"display_name": "CVE / OSV 修補草案",
"owner_agent": "OpenClaw",
"risk_tier": "high",
"max_batch_size": 2,
"draft_only": true,
"automerge": false,
"requires_openclaw_review": true,
"rollback_required": true,
"required_check_ids": [
"vulnerability_evidence_ref",
"targeted_tests_plan",
"rollback_plan_attached",
"owner_response_required"
],
"allowed_change_kinds": [
"security advisory summary",
"patch proposal",
"blast radius matrix"
],
"blocked_change_kinds": [
"external vulnerability DB download",
"package upgrade without owner approval",
"production hot patch"
]
},
{
"group_id": "container_image_digest_proposal",
"display_name": "Container image digest / base image 草案",
"owner_agent": "Hermes",
"risk_tier": "high",
"max_batch_size": 2,
"draft_only": true,
"automerge": false,
"requires_openclaw_review": true,
"rollback_required": true,
"required_check_ids": [
"image_digest_evidence",
"targeted_tests_plan",
"rollback_plan_attached",
"maintenance_window_required"
],
"allowed_change_kinds": [
"Dockerfile proposal",
"image digest pin proposal",
"smoke plan"
],
"blocked_change_kinds": [
"docker build",
"image pull",
"kustomization image tag mutation"
]
},
{
"group_id": "ai_agent_model_tool_contract_change",
"display_name": "AI Agent / model / tool contract 草案",
"owner_agent": "NemoTron + OpenClaw",
"risk_tier": "critical",
"max_batch_size": 1,
"draft_only": true,
"automerge": false,
"requires_openclaw_review": true,
"rollback_required": true,
"required_check_ids": [
"sanitized_replay_gate",
"targeted_tests_plan",
"owner_response_required",
"rollback_plan_attached"
],
"allowed_change_kinds": [
"offline replay plan",
"model route proposal",
"tool contract proposal"
],
"blocked_change_kinds": [
"production route change",
"paid API enablement",
"shadow or canary without gate"
]
},
{
"group_id": "host_k3s_stateful_maintenance_plan",
"display_name": "Host / K3s / stateful maintenance 草案",
"owner_agent": "OpenClaw",
"risk_tier": "critical",
"max_batch_size": 1,
"draft_only": true,
"automerge": false,
"requires_openclaw_review": true,
"rollback_required": true,
"required_check_ids": [
"maintenance_window_required",
"rollback_plan_attached",
"owner_response_required",
"targeted_tests_plan"
],
"allowed_change_kinds": [
"maintenance window proposal",
"version skew report",
"stateful backup readiness note"
],
"blocked_change_kinds": [
"host upgrade",
"reboot",
"stateful service restart"
]
},
{
"group_id": "docs_runbook_km_update",
"display_name": "文件 / runbook / KM 草案",
"owner_agent": "Hermes",
"risk_tier": "low",
"max_batch_size": 8,
"draft_only": true,
"automerge": false,
"requires_openclaw_review": true,
"rollback_required": true,
"required_check_ids": [
"schema_and_json_validation",
"secret_and_transcript_redaction",
"owner_response_required"
],
"allowed_change_kinds": [
"runbook proposal",
"LOGBOOK summary",
"KM draft"
],
"blocked_change_kinds": [
"canonical KM publish without owner response",
"secret-bearing evidence",
"work-window transcript"
]
}
],
"lane_steps": [
{
"step_id": "collect_committed_evidence",
"owner_agent": "Hermes",
"purpose": "讀取已提交 snapshot、LOGBOOK 與批准包,整理 PR 草案候選來源。",
"planned_output": "evidence_ref_list",
"runtime_execution_allowed": false,
"repo_write_allowed": false,
"approval_gate": "read_only_allowed"
},
{
"step_id": "group_and_dedupe_candidates",
"owner_agent": "Hermes",
"purpose": "依變更類型、風險與 owner 分組,避免單 PR 混入無關風險。",
"planned_output": "grouping_decision",
"runtime_execution_allowed": false,
"repo_write_allowed": false,
"approval_gate": "draft_lane_policy_only"
},
{
"step_id": "openclaw_risk_arbitration",
"owner_agent": "OpenClaw",
"purpose": "審核 blast radius、rollback、HITL 與是否需拆 PR。",
"planned_output": "risk_verdict",
"runtime_execution_allowed": false,
"repo_write_allowed": false,
"approval_gate": "openclaw_review_required"
},
{
"step_id": "nemotron_replay_requirement_check",
"owner_agent": "NemoTron",
"purpose": "只對 AI Agent / model / prompt / tool contract 類變更提出 sanitized replay 需求。",
"planned_output": "replay_gate_requirement",
"runtime_execution_allowed": false,
"repo_write_allowed": false,
"approval_gate": "offline_replay_approval_required"
},
{
"step_id": "attach_test_and_smoke_plan",
"owner_agent": "Hermes",
"purpose": "列出 PR 前必備測試、schema、secret/redaction 與 production smoke 證據。",
"planned_output": "test_plan",
"runtime_execution_allowed": false,
"repo_write_allowed": false,
"approval_gate": "test_plan_required"
},
{
"step_id": "attach_rollback_and_owner_response",
"owner_agent": "OpenClaw",
"purpose": "要求 rollback、owner response、maintenance window 與風險接受欄位齊全。",
"planned_output": "rollback_owner_packet",
"runtime_execution_allowed": false,
"repo_write_allowed": false,
"approval_gate": "owner_response_required"
},
{
"step_id": "emit_draft_pr_packet",
"owner_agent": "Hermes",
"purpose": "只產出 PR 草案封包;不 push branch、不呼叫 Gitea API、不觸發 workflow。",
"planned_output": "draft_pr_packet",
"runtime_execution_allowed": false,
"repo_write_allowed": false,
"approval_gate": "gitea_bot_and_branch_policy_approval_required"
}
],
"required_checks": [
{
"check_id": "schema_and_json_validation",
"display_name": "Schema / JSON 驗證",
"owner_agent": "Hermes",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "python3 -m json.tool 與 targeted schema validation evidence"
},
{
"check_id": "targeted_tests_plan",
"display_name": "Targeted tests plan",
"owner_agent": "Hermes",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "pytest / ruff / frontend smoke plan依變更範圍列出"
},
{
"check_id": "secret_and_transcript_redaction",
"display_name": "Secret 與工作視窗內容遮蔽",
"owner_agent": "OpenClaw",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "doc secrets sanity check + forbidden transcript marker scan"
},
{
"check_id": "rollback_plan_attached",
"display_name": "Rollback plan attached",
"owner_agent": "OpenClaw",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "回滾 commit / config revert / deployment rollback plan"
},
{
"check_id": "owner_response_required",
"display_name": "Owner response required",
"owner_agent": "OpenClaw",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "owner 接受、拒絕或要求拆分的結構化回覆"
},
{
"check_id": "vulnerability_evidence_ref",
"display_name": "Vulnerability evidence ref",
"owner_agent": "OpenClaw",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "OSV / CVE / scanner report ref本波不查外部 DB"
},
{
"check_id": "image_digest_evidence",
"display_name": "Image digest evidence",
"owner_agent": "Hermes",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "image digest / base image release evidence本波不 pull image"
},
{
"check_id": "sanitized_replay_gate",
"display_name": "Sanitized replay gate",
"owner_agent": "NemoTron",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "AI Agent / model / prompt 變更需 sanitized replay plan 與 hidden-label gate"
},
{
"check_id": "maintenance_window_required",
"display_name": "Deployment / maintenance window required",
"owner_agent": "OpenClaw",
"blocking": true,
"evidence_required": true,
"run_now_allowed": false,
"planned_command_or_evidence": "變更需列 deployment 或 maintenance window本波不部署"
}
],
"owner_response_requirements": [
{
"requirement_id": "business_owner_verdict",
"owner_agent": "OpenClaw",
"required_fields": [
"owner",
"decision",
"business_impact",
"risk_acceptance",
"evidence_ref"
],
"required_before_pr_creation": true
},
{
"requirement_id": "sre_owner_readiness",
"owner_agent": "OpenClaw",
"required_fields": [
"owner",
"decision",
"rollback_acceptance",
"maintenance_window",
"evidence_ref"
],
"required_before_pr_creation": true
},
{
"requirement_id": "security_owner_review",
"owner_agent": "OpenClaw",
"required_fields": [
"owner",
"decision",
"risk_acceptance",
"business_impact",
"evidence_ref"
],
"required_before_pr_creation": true
},
{
"requirement_id": "product_owner_scope_response",
"owner_agent": "Hermes",
"required_fields": [
"owner",
"decision",
"business_impact",
"maintenance_window",
"evidence_ref"
],
"required_before_pr_creation": true
}
],
"rollback_requirements": [
{
"requirement_id": "git_revert_plan",
"description": "必須列出可回退 commit 或檔案層 revert 計畫。",
"required": true,
"must_be_attached_before_pr_creation": true
},
{
"requirement_id": "config_recovery_plan",
"description": "涉及 config / K8s / workflow 時必須列出原值與回復步驟。",
"required": true,
"must_be_attached_before_pr_creation": true
},
{
"requirement_id": "data_migration_rollback",
"description": "涉及 schema / migration 時必須列出 forward-only 或 rollback policy。",
"required": true,
"must_be_attached_before_pr_creation": true
},
{
"requirement_id": "runtime_disable_switch",
"description": "涉及 runtime gate 時必須列出 disable switch 與監控證據。",
"required": true,
"must_be_attached_before_pr_creation": true
},
{
"requirement_id": "telegram_noise_rollback",
"description": "涉及告警或通知時必須列出降噪、停發與 fallback 策略。",
"required": true,
"must_be_attached_before_pr_creation": true
},
{
"requirement_id": "production_smoke_revert_gate",
"description": "正式部署前必須定義 smoke 失敗時的停止與回退條件。",
"required": true,
"must_be_attached_before_pr_creation": true
}
],
"draft_templates": [
{
"template_id": "dependency_update_draft",
"display_name": "Dependency update draft PR template",
"applies_to_group_ids": [
"dependency_patch_low_risk",
"security_cve_advisory"
],
"required_sections": [
"變更摘要",
"版本差異",
"測試計畫",
"Rollback",
"Owner response"
],
"forbidden_fields": [
"secret_value",
"token",
"authorization_header",
"work_window_transcript",
"codex_user_message",
"prompt_text",
"chain_of_thought",
"session_id",
"browser_context"
],
"automerge": false,
"branch_push_allowed": false
},
{
"template_id": "runtime_infra_draft",
"display_name": "Runtime / infrastructure draft PR template",
"applies_to_group_ids": [
"container_image_digest_proposal",
"host_k3s_stateful_maintenance_plan"
],
"required_sections": [
"影響範圍",
"部署或維護窗口",
"監控與 smoke",
"Rollback",
"Owner response"
],
"forbidden_fields": [
"secret_value",
"token",
"authorization_header",
"work_window_transcript",
"codex_user_message",
"prompt_text",
"chain_of_thought",
"session_id",
"browser_context"
],
"automerge": false,
"branch_push_allowed": false
},
{
"template_id": "ai_agent_contract_draft",
"display_name": "AI Agent / model / tool contract draft template",
"applies_to_group_ids": [
"ai_agent_model_tool_contract_change"
],
"required_sections": [
"候選 Agent 或模型",
"Replay / shadow gate",
"安全邊界",
"Rollback",
"Owner response"
],
"forbidden_fields": [
"secret_value",
"token",
"authorization_header",
"work_window_transcript",
"codex_user_message",
"prompt_text",
"chain_of_thought",
"session_id",
"browser_context"
],
"automerge": false,
"branch_push_allowed": false
},
{
"template_id": "docs_runbook_km_draft",
"display_name": "Docs / runbook / KM draft template",
"applies_to_group_ids": [
"docs_runbook_km_update"
],
"required_sections": [
"文件目的",
"證據來源",
"使用者影響",
"Rollback",
"Owner response"
],
"forbidden_fields": [
"secret_value",
"token",
"authorization_header",
"work_window_transcript",
"codex_user_message",
"prompt_text",
"chain_of_thought",
"session_id",
"browser_context"
],
"automerge": false,
"branch_push_allowed": false
}
],
"agent_roles": [
{
"agent_id": "hermes",
"role": "建立 PR 草案封包、分組、release note、test plan 與 docs / KM 草稿。",
"allowed_now": [
"讀取 committed evidence",
"產出 draft_pr_packet",
"產出 grouping_decision"
],
"blocked_until_approval": [
"push branch",
"create Gitea PR",
"trigger workflow",
"modify lockfile"
]
},
{
"agent_id": "openclaw",
"role": "仲裁風險、rollback、owner response、HITL 與是否拆分 PR。",
"allowed_now": [
"審核 draft packet",
"標註 blocker",
"要求 owner response"
],
"blocked_until_approval": [
"approve itself",
"merge PR",
"runtime execution",
"production route change"
]
},
{
"agent_id": "nemotron",
"role": "針對 AI Agent / model / prompt / tool contract 類變更提出 sanitized replay gate。",
"allowed_now": [
"定義 replay requirement",
"檢查 output contract",
"標記 model/tool risk"
],
"blocked_until_approval": [
"call paid API",
"run external replay",
"shadow/canary",
"production route"
]
}
],
"display_redaction_contract": {
"conversation_transcript_display_allowed": false,
"redaction_required": true,
"allowed_frontend_fields": [
"整體完成度",
"目前任務",
"下一任務",
"grouping rule 摘要",
"required checks 摘要",
"rollback / owner response 邊界"
],
"forbidden_frontend_content": [
"工作視窗對話內容",
"secret 明文",
"prompt 全文",
"chain-of-thought",
"browser session context"
]
},
"operation_boundaries": {
"read_only_lane_allowed": true,
"gitea_branch_push_allowed": false,
"gitea_pr_creation_allowed": false,
"gitea_pr_update_allowed": false,
"gitea_pr_comment_allowed": false,
"auto_merge_allowed": false,
"workflow_trigger_allowed": false,
"ci_workflow_change_allowed": false,
"lockfile_write_allowed": false,
"package_upgrade_allowed": false,
"file_mutation_allowed": false,
"external_registry_lookup_allowed": false,
"vulnerability_database_download_allowed": false,
"docker_build_allowed": false,
"image_pull_allowed": false,
"production_route_change_allowed": false,
"telegram_direct_send_allowed": false,
"telegram_gateway_queue_write_allowed": false,
"secret_plaintext_allowed": false,
"conversation_transcript_allowed": false
},
"approval_boundaries": {
"gitea_bot_account_approved": false,
"gitea_branch_policy_approved": false,
"gitea_pr_creation_approved": false,
"gitea_pr_update_approved": false,
"workflow_trigger_approved": false,
"ci_workflow_change_approved": false,
"lockfile_write_approved": false,
"package_upgrade_approved": false,
"docker_build_approved": false,
"image_pull_approved": false,
"auto_merge_approved": false,
"telegram_digest_send_approved": false,
"runtime_execution_approved": false,
"production_route_change_approved": false,
"secret_plaintext_approved": false
},
"rollups": {
"grouping_rule_count": 6,
"lane_step_count": 7,
"required_check_count": 9,
"owner_response_requirement_count": 4,
"rollback_requirement_count": 6,
"draft_template_count": 4,
"draft_group_ids": [
"dependency_patch_low_risk",
"security_cve_advisory",
"container_image_digest_proposal",
"ai_agent_model_tool_contract_change",
"host_k3s_stateful_maintenance_plan",
"docs_runbook_km_update"
],
"owner_response_requirement_ids": [
"business_owner_verdict",
"sre_owner_readiness",
"security_owner_review",
"product_owner_scope_response"
],
"critical_risk_group_ids": [
"ai_agent_model_tool_contract_change",
"host_k3s_stateful_maintenance_plan"
],
"gitea_branch_push_allowed_count": 0,
"gitea_pr_creation_allowed_count": 0,
"auto_merge_allowed_count": 0,
"workflow_trigger_allowed_count": 0,
"lockfile_write_allowed_count": 0,
"telegram_direct_send_allowed_count": 0,
"conversation_transcript_allowed_count": 0,
"next_approval_task_ids": [
"P2-402F",
"P2-402G"
]
}
}

View File

@@ -2,13 +2,13 @@
"schema_version": "ai_agent_proactive_operations_contract_v1",
"generated_at": "2026-06-11T21:30:00+08:00",
"program_status": {
"overall_completion_percent": 68,
"overall_completion_percent": 78,
"current_priority": "P2",
"current_task_id": "P2-402D",
"next_task_id": "P2-402E",
"current_task_id": "P2-402E",
"next_task_id": "P2-402F",
"read_only_mode": true,
"runtime_authority": "contract_only_no_version_or_runtime_update",
"status_note": "P2-402D 已建立 Telegram action-required digest policy、schema、snapshot、只讀 API 與測試;本波仍不送 Telegram、不寫 Gateway queue、不改 Alertmanager route / receiver、不觸發 workflow、不執行 runtime。"
"status_note": "P2-402E 已建立 Gitea PR 草案 lane、schema、snapshot、只讀 API 與測試;本波仍不 push branch、不建立或更新 Gitea PR、不觸發 workflow、不改 CI、不寫 lockfile、不升級套件、不發 Telegram。"
},
"external_source_evidence": [
{
@@ -637,16 +637,16 @@
"completion_percent": 100,
"owner_agent": "OpenClaw",
"summary": "建立 Telegram action-required digest policy、schema、snapshot、只讀 API 與測試;定義 critical / action-required / failure-only digest 草案、成功降噪、redaction 與 fallback gap 邊界。",
"next_gate": "P2-402E_gitea_pr_draft_lane"
"next_gate": "P2-402E_completed"
},
{
"task_id": "P2-402E",
"priority": "P2",
"status": "planned",
"completion_percent": 0,
"status": "done",
"completion_percent": 100,
"owner_agent": "Hermes",
"summary": "設計 Gitea PR 草案 lanegrouping、automerge=false、tests、rollback、owner response。",
"next_gate": "gitea_bot_and_branch_policy_approval_required"
"summary": "建立 Gitea PR 草案 lane、schema、snapshot、只讀 API 與測試;定義 grouping、automerge=false、測試證據、rollback、owner response 與 redaction policy。",
"next_gate": "P2-402F_host_stateful_version_inventory"
},
{
"task_id": "P2-402F",

View File

@@ -0,0 +1,438 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://awoooi.wooo.work/schemas/ai_agent_gitea_pr_draft_lane_v1.schema.json",
"title": "AI Agent Gitea PR Draft Lane v1",
"type": "object",
"additionalProperties": false,
"required": [
"schema_version",
"generated_at",
"program_status",
"source_refs",
"lane_intent",
"branch_strategy",
"grouping_rules",
"lane_steps",
"required_checks",
"owner_response_requirements",
"rollback_requirements",
"draft_templates",
"agent_roles",
"display_redaction_contract",
"operation_boundaries",
"approval_boundaries",
"rollups"
],
"properties": {
"schema_version": {
"const": "ai_agent_gitea_pr_draft_lane_v1"
},
"generated_at": {
"type": "string"
},
"program_status": {
"type": "object",
"additionalProperties": false,
"required": [
"overall_completion_percent",
"current_priority",
"current_task_id",
"next_task_id",
"read_only_mode",
"runtime_authority",
"status_note"
],
"properties": {
"overall_completion_percent": {
"type": "integer",
"minimum": 0,
"maximum": 100
},
"current_priority": {
"type": "string"
},
"current_task_id": {
"type": "string"
},
"next_task_id": {
"type": "string"
},
"read_only_mode": {
"const": true
},
"runtime_authority": {
"const": "draft_lane_only_no_pr_creation_or_branch_push"
},
"status_note": {
"type": "string"
}
}
},
"source_refs": {
"type": "array",
"items": {
"type": "string"
}
},
"lane_intent": {
"type": "object",
"additionalProperties": false,
"required": [
"purpose",
"non_goals",
"human_approval_gate"
],
"properties": {
"purpose": {
"type": "string"
},
"non_goals": {
"type": "array",
"items": {
"type": "string"
}
},
"human_approval_gate": {
"type": "string"
}
}
},
"branch_strategy": {
"type": "object",
"additionalProperties": false,
"required": [
"draft_branch_prefix",
"branch_name_pattern",
"branch_push_allowed",
"pr_creation_allowed",
"automerge",
"required_prefix_after_approval"
],
"properties": {
"draft_branch_prefix": {
"type": "string"
},
"branch_name_pattern": {
"type": "string"
},
"branch_push_allowed": {
"const": false
},
"pr_creation_allowed": {
"const": false
},
"automerge": {
"const": false
},
"required_prefix_after_approval": {
"type": "string"
}
}
},
"grouping_rules": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"group_id",
"display_name",
"owner_agent",
"risk_tier",
"max_batch_size",
"draft_only",
"automerge",
"requires_openclaw_review",
"rollback_required",
"required_check_ids",
"allowed_change_kinds",
"blocked_change_kinds"
],
"properties": {
"group_id": {
"type": "string"
},
"display_name": {
"type": "string"
},
"owner_agent": {
"type": "string"
},
"risk_tier": {
"type": "string"
},
"max_batch_size": {
"type": "integer",
"minimum": 1
},
"draft_only": {
"const": true
},
"automerge": {
"const": false
},
"requires_openclaw_review": {
"const": true
},
"rollback_required": {
"const": true
},
"required_check_ids": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"allowed_change_kinds": {
"type": "array",
"items": {
"type": "string"
}
},
"blocked_change_kinds": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"lane_steps": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"step_id",
"owner_agent",
"purpose",
"planned_output",
"runtime_execution_allowed",
"repo_write_allowed",
"approval_gate"
],
"properties": {
"step_id": {
"type": "string"
},
"owner_agent": {
"type": "string"
},
"purpose": {
"type": "string"
},
"planned_output": {
"type": "string"
},
"runtime_execution_allowed": {
"const": false
},
"repo_write_allowed": {
"const": false
},
"approval_gate": {
"type": "string"
}
}
}
},
"required_checks": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"check_id",
"display_name",
"owner_agent",
"blocking",
"evidence_required",
"run_now_allowed",
"planned_command_or_evidence"
],
"properties": {
"check_id": {
"type": "string"
},
"display_name": {
"type": "string"
},
"owner_agent": {
"type": "string"
},
"blocking": {
"const": true
},
"evidence_required": {
"const": true
},
"run_now_allowed": {
"const": false
},
"planned_command_or_evidence": {
"type": "string"
}
}
}
},
"owner_response_requirements": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"requirement_id",
"owner_agent",
"required_fields",
"required_before_pr_creation"
],
"properties": {
"requirement_id": {
"type": "string"
},
"owner_agent": {
"type": "string"
},
"required_fields": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"required_before_pr_creation": {
"const": true
}
}
}
},
"rollback_requirements": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"requirement_id",
"description",
"required",
"must_be_attached_before_pr_creation"
],
"properties": {
"requirement_id": {
"type": "string"
},
"description": {
"type": "string"
},
"required": {
"const": true
},
"must_be_attached_before_pr_creation": {
"const": true
}
}
}
},
"draft_templates": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"template_id",
"display_name",
"applies_to_group_ids",
"required_sections",
"forbidden_fields",
"automerge",
"branch_push_allowed"
],
"properties": {
"template_id": {
"type": "string"
},
"display_name": {
"type": "string"
},
"applies_to_group_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"required_sections": {
"type": "array",
"items": {
"type": "string"
}
},
"forbidden_fields": {
"type": "array",
"items": {
"type": "string"
}
},
"automerge": {
"const": false
},
"branch_push_allowed": {
"const": false
}
}
}
},
"agent_roles": {
"type": "array",
"items": {
"type": "object"
}
},
"display_redaction_contract": {
"type": "object",
"additionalProperties": false,
"required": [
"conversation_transcript_display_allowed",
"redaction_required",
"allowed_frontend_fields",
"forbidden_frontend_content"
],
"properties": {
"conversation_transcript_display_allowed": {
"const": false
},
"redaction_required": {
"const": true
},
"allowed_frontend_fields": {
"type": "array",
"items": {
"type": "string"
}
},
"forbidden_frontend_content": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"operation_boundaries": {
"type": "object"
},
"approval_boundaries": {
"type": "object"
},
"rollups": {
"type": "object"
}
}
}

View File

@@ -670,7 +670,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence
| 檔案 / API | 用途 |
|---|---|
| `docs/schemas/ai_agent_proactive_operations_contract_v1.schema.json` | 主動營運委派、版本生命週期、MCP、RAG、Telegram policy、approval boundary 契約 |
| `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` | 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory完成度 `68%` |
| `docs/evaluations/ai_agent_proactive_operations_contract_2026-06-11.json` | 12 類版本 domain、24 類可委派能力、5 種 cadence、8 類 MCP、4 類 RAG memory完成度 `78%` |
| `apps/api/src/services/ai_agent_proactive_operations_contract.py` | 只讀 loader強制 runtime update / package upgrade / host upgrade / workflow schedule / auto merge / Telegram direct send 全部 false |
| `GET /api/v1/agents/agent-proactive-operations-contract` | 治理 API只回傳 committed snapshot不啟用排程、不升級、不呼叫付費服務 |
| `docs/schemas/ai_agent_version_freshness_snapshot_v1.schema.json` | P2-402B repo-only 版本新鮮度 schema鎖定 schedule / external lookup / upgrade / Telegram / PR / host probe 全部 false |
@@ -682,14 +682,17 @@ Repo / registry / release notes / K8s / host / observability / backup evidence
| `docs/schemas/ai_agent_telegram_action_required_digest_policy_v1.schema.json` | P2-402D Telegram action-required digest policy schema鎖定 direct send / Gateway queue write / route change / receiver change / workflow / transcript 全部 false |
| `docs/evaluations/ai_agent_telegram_action_required_digest_policy_2026-06-11.json` | P2-402D committed snapshot8 條 digest rule、3 個 channel 草案、5 類 trigger category、成功降噪、failure-only 與 redaction policy |
| `GET /api/v1/agents/agent-telegram-action-required-digest-policy` | 只讀 API只回傳 digest policy不送 Telegram、不寫 queue、不改 route / receiver、不觸發 workflow |
| `docs/schemas/ai_agent_gitea_pr_draft_lane_v1.schema.json` | P2-402E Gitea PR 草案 lane schema鎖定 branch push / PR creation / workflow trigger / lockfile / automerge / Telegram 全部 false |
| `docs/evaluations/ai_agent_gitea_pr_draft_lane_2026-06-11.json` | P2-402E committed snapshot6 條 grouping rule、7 個 lane step、9 個 required check、6 條 rollback requirement、4 個 draft template |
| `GET /api/v1/agents/agent-gitea-pr-draft-lane` | 只讀 API只回傳 PR 草案 lane不 push branch、不建立 PR、不觸發 workflow、不改 CI、不升級套件、不發 Telegram |
**採用順序:**
1. 先做 repo-only daily freshnessmanifest / lockfile / Dockerfile / K8s YAML / runbook / snapshot。✅ P2-402B 已建立 committed snapshot/API每日排程仍未授權。
2. 再評估 external primary source weekly watchRenovate、OSV-Scanner、Trivy、Syft、Grype、Kubernetes skew policy、Docker Scout。✅ P2-402C 已建立工具採用批准包工具安裝、CI 變更、外部查詢仍未授權。
3. 建立 Telegram action-required digest policy先定義 critical / action-required / failure-only 通知門檻,禁止成功洗版。✅ P2-402D 已建立 policy snapshot/APITelegram 實發與 queue write 仍未授權。
4. 再進 Gitea PR 草案 lanegrouping、automerge=false、tests、rollback、owner response。下一步 P2-402E。
5. 最後才進人工批准後的 dry-run / smoke / canary / production rollout。
4. 再進 Gitea PR 草案 lanegrouping、automerge=false、tests、rollback、owner response。 P2-402E 已建立 draft lane snapshot/APIbranch push、PR creation、workflow trigger、lockfile、package upgrade、auto merge 仍未授權
5. 最後才進人工批准後的 dry-run / smoke / canary / production rollout。下一步 P2-402F host OS / K3s / stateful services 版本只讀盤點。
#### 3.2.2 核心缺口與災難場景
@@ -1327,6 +1330,7 @@ Repo / registry / release notes / K8s / host / observability / backup evidence
| Repo-only 版本新鮮度快照 | `docs/evaluations/ai_agent_version_freshness_snapshot_2026-06-11.json` + `GET /api/v1/agents/agent-version-freshness-snapshot` | P2-402B讓 Hermes 可每日產生 repo-only freshness evidence packet目前只讀 API不啟用 schedule、不查外部、不升級 | L4×D2 / L7×D4 / L6×D6 |
| 工具採用批准包 | `docs/evaluations/ai_agent_tool_adoption_approval_package_2026-06-11.json` + `GET /api/v1/agents/agent-tool-adoption-approval-package` | P2-402C讓 OpenClaw / Hermes / NemoTron 用官方來源評估 Renovate / OSV-Scanner / Trivy / Syft / Grype目前只讀 API不安裝工具、不改 CI、不查外部、不建 PR、不發 Telegram | L4×D2 / L7×D4 / L6×D6 |
| Telegram action-required digest policy | `docs/evaluations/ai_agent_telegram_action_required_digest_policy_2026-06-11.json` + `GET /api/v1/agents/agent-telegram-action-required-digest-policy` | P2-402D讓 OpenClaw / Hermes / NemoTron 先定義 critical / action-required / failure-only digest 與成功降噪;目前只讀 API不送 Telegram、不寫 queue、不改 route / receiver | L4×D2 / L7×D4 / L6×D6 |
| Gitea PR 草案 lane | `docs/evaluations/ai_agent_gitea_pr_draft_lane_2026-06-11.json` + `GET /api/v1/agents/agent-gitea-pr-draft-lane` | P2-402E讓 Hermes / OpenClaw / NemoTron 先定義 grouping、automerge=false、測試證據、rollback 與 owner response目前只讀 API不 push branch、不建立 PR、不觸發 workflow | L4×D2 / L7×D4 / L6×D6 |
**退出條件(量化)**
@@ -1716,6 +1720,12 @@ Phase 6 完成後
- 更新 `ai_agent_proactive_operations_contract_2026-06-11.json`:整體完成度 `68%`current task `P2-402D`next task `P2-402E`
- 本波仍不送 Telegram、不寫 Telegram Gateway queue、不改 Alertmanager route / receiver、不寫 AwoooP event、不觸發 workflow、不查外部掃描、不執行 runtime、不讀取或輸出 secret、不回傳工作視窗對話內容P2-402E 才設計 Gitea PR 草案 lane。
### 2026-06-11 23:59 (台北) — §3.2 / §5 — 完成 P2-402E Gitea PR 草案 lane — 回應統帥要求讓 Agent 主動產生版本更新與工具採用 PR 草案但先走批准制
- 新增 `ai_agent_gitea_pr_draft_lane_v1` schema / committed snapshot / loader / API / 測試,定義 6 條 grouping rule、7 個 lane step、9 個 required check、6 條 rollback requirement、4 個 draft template、owner response 與 redaction policy。
- 更新 `ai_agent_proactive_operations_contract_2026-06-11.json`:整體完成度 `78%`current task `P2-402E`next task `P2-402F`
- 本波仍不 push branch、不建立或更新 Gitea PR、不留言、不 auto merge、不觸發 workflow、不改 CI、不寫 lockfile、不升級套件、不 build / pull image、不發 Telegram、不讀取或輸出 secret、不回傳工作視窗對話內容P2-402F 才建立 host OS / K3s / stateful services 版本只讀盤點。
### 2026-04-15 (台北) — 全檔 — 建立 v2 骨架§0/§1 完成 — 統帥批准「單 MASTER + 4 道閘門」結構
- 從 v1plans/2026-04-15-MASTER-ai-autonomous-flywheel.md繼承核心發現