Files
awoooi/.gitea/workflows/agent-version-lifecycle-watch.yaml
ogt d41a1d37fe
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
fix(ci): keep workflows on Gitea supply chain
2026-07-11 00:35:10 +08:00

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