Some checks failed
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / tests (push) Has been cancelled
124 lines
5.8 KiB
YAML
124 lines
5.8 KiB
YAML
# =============================================================================
|
|
# AWOOOI Agent Version Lifecycle Watch (Gitea Actions)
|
|
# =============================================================================
|
|
# Weekly no-write AI Agent / SDK / framework version lifecycle readback. This
|
|
# workflow validates the committed proposal queue only; it does not install SDKs,
|
|
# call model APIs, write lockfiles, change workflows, send Telegram, switch
|
|
# providers, replace OpenClaw, or mutate production.
|
|
|
|
name: Agent Version Lifecycle Watch
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
schedule:
|
|
- cron: '0 1 * * 2' # 每週二 09:00 台北 (UTC+8)
|
|
|
|
jobs:
|
|
version-lifecycle-watch:
|
|
runs-on: awoooi-non110-ubuntu
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Checkout source from Gitea
|
|
env:
|
|
GITEA_SOURCE_URL: http://192.168.0.110:3001/wooo/awoooi.git
|
|
run: |
|
|
set -euo pipefail
|
|
git init .
|
|
git remote remove origin 2>/dev/null || true
|
|
git remote add origin "$GITEA_SOURCE_URL"
|
|
git fetch --no-tags --prune --depth=1 origin "$GITHUB_SHA"
|
|
git checkout --force --detach FETCH_HEAD
|
|
|
|
- name: Validate no-write version lifecycle proposal
|
|
id: lifecycle
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
candidates = sorted(
|
|
Path("docs/evaluations").glob("ai_agent_version_lifecycle_update_proposal_*.json")
|
|
)
|
|
if not candidates:
|
|
raise SystemExit("no version lifecycle proposal snapshots found")
|
|
latest = candidates[-1]
|
|
with latest.open(encoding="utf-8") as handle:
|
|
data = json.load(handle)
|
|
if data.get("schema_version") != "ai_agent_version_lifecycle_update_proposal_v1":
|
|
raise SystemExit("unexpected version lifecycle schema_version")
|
|
if (data.get("program_status") or {}).get("read_only_mode") is not True:
|
|
raise SystemExit("version lifecycle proposal must stay read_only")
|
|
|
|
boundaries = data.get("runtime_boundaries") or {}
|
|
forbidden = [
|
|
"schedule_activation_allowed",
|
|
"external_market_lookup_allowed",
|
|
"external_registry_lookup_allowed",
|
|
"external_cve_lookup_allowed",
|
|
"package_upgrade_allowed",
|
|
"lockfile_write_allowed",
|
|
"workflow_write_allowed",
|
|
"provider_route_switch_allowed",
|
|
"openclaw_replacement_allowed",
|
|
"paid_api_call_allowed",
|
|
"telegram_direct_send_allowed",
|
|
"telegram_gateway_queue_write_allowed",
|
|
"production_write_allowed",
|
|
]
|
|
unsafe = [key for key in forbidden if boundaries.get(key) is not False]
|
|
if unsafe:
|
|
raise SystemExit(f"version lifecycle runtime boundary must stay false: {unsafe}")
|
|
|
|
rollups = data.get("rollups") or {}
|
|
if rollups.get("proposal_count") != len(data.get("update_proposals") or []):
|
|
raise SystemExit("proposal_count rollup mismatch")
|
|
if rollups.get("cadence_count") != len(data.get("cadence_matrix") or []):
|
|
raise SystemExit("cadence_count rollup mismatch")
|
|
required_proposals = {
|
|
"ai_agent_market_primary_source_radar",
|
|
"openclaw_challenger_replay_bench",
|
|
"mainstream_agent_framework_version_lifecycle_review",
|
|
}
|
|
proposal_ids = set(rollups.get("proposal_ids") or [])
|
|
missing = sorted(required_proposals - proposal_ids)
|
|
if missing:
|
|
raise SystemExit(f"missing required AI Agent version lifecycle proposals: {missing}")
|
|
|
|
summary = {
|
|
"snapshot": str(latest),
|
|
"current_task_id": (data.get("program_status") or {}).get("current_task_id"),
|
|
"domain_count": rollups.get("domain_count"),
|
|
"proposal_count": rollups.get("proposal_count"),
|
|
"cadence_count": rollups.get("cadence_count"),
|
|
"approval_required_count": rollups.get("approval_required_count"),
|
|
"auto_execution_allowed_count": rollups.get("auto_execution_allowed_count"),
|
|
"production_write_count": rollups.get("production_write_count"),
|
|
"openclaw_replacement_allowed": boundaries.get("openclaw_replacement_allowed"),
|
|
}
|
|
|
|
output_path = os.environ.get("GITHUB_OUTPUT")
|
|
if output_path:
|
|
with open(output_path, "a", encoding="utf-8") as handle:
|
|
for key, value in summary.items():
|
|
handle.write(f"{key}={value}\n")
|
|
|
|
step_summary_path = os.environ.get("GITHUB_STEP_SUMMARY")
|
|
if step_summary_path:
|
|
with open(step_summary_path, "a", encoding="utf-8") as handle:
|
|
handle.write("## Agent Version Lifecycle Watch\n\n")
|
|
handle.write(f"- Snapshot: {summary['snapshot']}\n")
|
|
handle.write(f"- Current task: {summary['current_task_id']}\n")
|
|
handle.write(f"- Domains: {summary['domain_count']}\n")
|
|
handle.write(f"- Proposals: {summary['proposal_count']}\n")
|
|
handle.write(f"- Cadences: {summary['cadence_count']}\n")
|
|
handle.write(f"- Approval-required proposals: {summary['approval_required_count']}\n")
|
|
handle.write(f"- Auto executions approved: {summary['auto_execution_allowed_count']}\n")
|
|
handle.write(f"- Production writes approved: {summary['production_write_count']}\n")
|
|
handle.write(f"- OpenClaw replacement allowed: {summary['openclaw_replacement_allowed']}\n")
|
|
handle.write("\nPolicy: no-write proposal validation only.\n")
|
|
|
|
print(json.dumps(summary, ensure_ascii=False, sort_keys=True))
|
|
PY
|