Compare commits
10
Commits
1791c91c5b
..
V2R1C1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e0e6dcb90 | ||
|
|
0778a31ec0 | ||
|
|
80c4cbde03 | ||
|
|
fb739f6e8f | ||
|
|
e6da39a3cd | ||
|
|
95d2e52cb5 | ||
|
|
283dec58ab | ||
|
|
7de1fe80ac | ||
|
|
89a502b39b | ||
|
|
61bec280e2 |
@@ -0,0 +1,3 @@
|
||||
d23bb1ec24a7f49359314e04cd2c04c8f38876e45f25a701506499d1b34f270f MANIFEST-AIOS-V2R1-HERMES-LIFECYCLE-20260721.json
|
||||
5ce2894fdf8a22622954a1a10fb09fbab74af04f0260b249615c70236ff31731 RESULT-AIOS-V2R1-HERMES-LIFECYCLE-20260721.md
|
||||
ca2ab3c22c2b2b33bbc03e59f1206b999ad1271de3e1938fd3a0b4234c613eef ../../../docs/aios-v2/AIOS-V2R1-HARDENING-GATE-A-REPORT.md
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"schema_version": "aios.evidence.manifest.v1",
|
||||
"generated_at": "2026-07-21T05:50:00Z",
|
||||
"branch": "patch/chatgpt/AIOS-V2R1-HERMES-LIFECYCLE-20260721",
|
||||
"validated_oid": "95d2e52cb55c7b913e89bc6bed2bcdacf67512d4",
|
||||
"evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1-hermes-lifecycle-20260721T054205Z",
|
||||
"evidence_hashes": {
|
||||
"steps.tsv": "b2ad20585ba7f576e85657827a0b1db6f252887bbd73bcd718df38623e9d95cf",
|
||||
"final-live-gate.log": "82040c674759dacf587658c5e936c313a1f50e8e2425be48ad891927befdf4fa",
|
||||
"16R.log": "641246927a372ebaa9e6dde8b018b88275b2ba15a442473759b23fb1f215d9cf",
|
||||
"15.log": "b0a474e2a74164f560c4f7572091911f32011c75faccd37a3c7315046275011e",
|
||||
"13.log": "b9f637cca6e97ed893bf38530e05cd33b78e324c5e8865d4c602dfeac22a7710",
|
||||
"12R2.log": "0c431f5f5f1c1b17acda160c917b08c7f4036485016c23e1236b9b6f4a78de67"
|
||||
},
|
||||
"validation": {
|
||||
"candidate_tests": {"passed": 49, "failed": 0},
|
||||
"hermes_lifecycle": {"passed": 17, "failed": 0},
|
||||
"gate_b": {"passed": 10, "failed": 0},
|
||||
"offline_acceptance": {"passed": 8, "failed": 0, "expected_warnings": 1},
|
||||
"openclaw_real_http": "PASS",
|
||||
"restart_recovery": "PASS",
|
||||
"rollback_forward": "PASS",
|
||||
"state_preservation": "PASS",
|
||||
"final_health_corrected_16R": "PASS"
|
||||
},
|
||||
"git_gate": {
|
||||
"oid_match": true,
|
||||
"candidate_clean": true,
|
||||
"active_controller_clean": true,
|
||||
"locked": 0,
|
||||
"prunable": 0,
|
||||
"worktree_total": 88,
|
||||
"worktree_dirty": 10,
|
||||
"global_worktree_clean": false
|
||||
},
|
||||
"resolved_blockers": [],
|
||||
"active_blockers": [
|
||||
"BLK-LIVE-HERMES-FULL-LIFECYCLE-EVIDENCE-MISSING",
|
||||
"BLK-GLOBAL-WORKTREE-CLEANLINESS"
|
||||
],
|
||||
"overall": "PARTIAL / BLOCKED_GLOBAL_WORKTREE_CLEANLINESS",
|
||||
"release_decision": "STOP_PREPRODUCTION",
|
||||
"secrets_recorded": false
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# AIOS V2R1 Hermes Lifecycle Result
|
||||
|
||||
- Branch: `patch/chatgpt/AIOS-V2R1-HERMES-LIFECYCLE-20260721`
|
||||
- Validated OID: `95d2e52cb55c7b913e89bc6bed2bcdacf67512d4`
|
||||
- Evidence root: `/var/lib/aios-gitops/acceptance/aios-v2r1-hermes-lifecycle-20260721T054205Z`
|
||||
- Hermes blocker: `EVIDENCE_COMPLETE / FORMAL_CLOSURE_BLOCKED`
|
||||
- Overall: `PARTIAL / BLOCKED_GLOBAL_WORKTREE_CLEANLINESS`
|
||||
- Release decision: `STOP_PREPRODUCTION`
|
||||
|
||||
Hermes lifecycle `17/17`, candidate `49/49`, Gate B `10/10`, offline acceptance `8/0/1`, OpenClaw real HTTP, restart recovery, rollback/forward, state preservation and corrected final health all passed at the validated OID. The Owner acceptance contract nevertheless forbids formally closing the Hermes blocker until every global gate also passes.
|
||||
|
||||
The candidate worktree and active Controller worktree are clean; local, worktree and Gitea OIDs match; locked/prunable are zero. The global authority currently has 10 dirty worktrees out of 88, so the Owner hard gate requiring every worktree to be clean fails.
|
||||
|
||||
No RC, Tag Approval Request, Tag, main mutation, force push, production traffic switch or secret disclosure was performed.
|
||||
|
||||
See `MANIFEST-AIOS-V2R1-HERMES-LIFECYCLE-20260721.json` and `docs/aios-v2/AIOS-V2R1-HARDENING-GATE-A-REPORT.md`.
|
||||
@@ -0,0 +1,12 @@
|
||||
# V2R1C1 Cleanup Closure
|
||||
|
||||
- `CLEANUP_REVIEW=PASS`
|
||||
- `ARCHIVE_VALIDATION=PASS`
|
||||
- `GLOBAL_WORKTREE_CLEAN=true`
|
||||
- `global_dirty_count=0`
|
||||
- `locked=0`
|
||||
- `prunable=0`
|
||||
- Portal Archive OID: `99671cc14d2631f989e0763dc882e4001c50a1ea`
|
||||
- Spark Archive OID: `d97cd3642528bd3373fe4cf5161a5d99c0b9285f`
|
||||
|
||||
Closure evidence: `/var/lib/aios-gitops/acceptance/aios-v2r1c1-blocker-clear-20260721T075647Z`.
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"schema_version": "aios.v2r1c1.deployment-manifest.v1",
|
||||
"vrc": "V2R1C1",
|
||||
"release_branch": "release/AIOS-V2R1C1-20260721",
|
||||
"old_release_oid": "80c4cbde03a82c30648a09b817bc2f03d5402936",
|
||||
"validated_release_parent_oid": "0778a31ec073e7c90003ef091f1d093c16bf22e5",
|
||||
"product_baseline_oid": "fb739f6e8ff9c031d319221ace68dce157694086",
|
||||
"companion": {
|
||||
"branch": "patch/openclaw/AIOS-V2R1C1-COMMAND-V2-COMPANION-20260721",
|
||||
"source_oid": "83f8f878c7da5dd8263f2af2efa80750492e5cb3",
|
||||
"oid": "12d1c13170e0c5a691d67a9408e739e7a17064a3",
|
||||
"plugin_version": "2.1.0-rc.4",
|
||||
"contract_version": "aios.openclaw.command.v2",
|
||||
"signature_algorithm": "Ed25519",
|
||||
"verification_key_id": "openclaw-v2r1-candidate-ed25519",
|
||||
"artifact_sha256": "aadd5f3cfa0d8e796a21f6368f5c95e8c60e9063d6e9fcd9c4947cfa0c013671"
|
||||
},
|
||||
"isolated_validation": {
|
||||
"service": "aios-v2r1c1-openclaw-companion.service",
|
||||
"account": "aios-v2r1c1-openclaw",
|
||||
"listen": "127.0.0.1:28789",
|
||||
"accept_v2": true,
|
||||
"accept_v1": false,
|
||||
"public_key_only": true,
|
||||
"production_traffic_switched": false,
|
||||
"result": "PASS"
|
||||
},
|
||||
"previous_plugin": {
|
||||
"source_oid": "83f8f878c7da5dd8263f2af2efa80750492e5cb3",
|
||||
"plugin_version": "2.1.0-rc.3",
|
||||
"artifact_sha256": "d0fd11be4aec03eee9ca24bf1585d9ef3597254ad4b1db0d0137eab4456b5737"
|
||||
},
|
||||
"rollback": {
|
||||
"production_plugin_unchanged": true,
|
||||
"failed_isolated_attempts_rolled_back": true,
|
||||
"previous_plugin_evidence": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-openclaw-v2-companion-20260721T094442Z/00-baseline",
|
||||
"previous_oid": "b158041b8633e658c34ce182f3c8aa97b4bf5f9a",
|
||||
"isolated_rollback_forward": "PASS",
|
||||
"production_symlink_modified": false
|
||||
},
|
||||
"release_validation": {
|
||||
"gate_a": "PASS",
|
||||
"gate_b": "PASS",
|
||||
"openclaw_v2_live": "PASS",
|
||||
"openclaw_negative_live": "PASS",
|
||||
"hermes_live": "PASS",
|
||||
"restart_recovery": "PASS",
|
||||
"rollback_forward": "PASS",
|
||||
"final_health": "PASS",
|
||||
"secret_violations": 0,
|
||||
"global_dirty_count": 0,
|
||||
"sync_status": "fully_synced"
|
||||
},
|
||||
"tag_status": "ABSENT",
|
||||
"preproduction_status": "NOT_STARTED",
|
||||
"production_status": "NOT_STARTED"
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"schema_version": "aios.v2r1c1.release-evidence.v2",
|
||||
"vrc": "V2R1C1",
|
||||
"semver": "2.1.0-rc.1",
|
||||
"product_baseline_oid": "fb739f6e8ff9c031d319221ace68dce157694086",
|
||||
"old_release_oid": "80c4cbde03a82c30648a09b817bc2f03d5402936",
|
||||
"validated_release_parent_oid": "0778a31ec073e7c90003ef091f1d093c16bf22e5",
|
||||
"release_branch": "release/AIOS-V2R1C1-20260721",
|
||||
"release_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-release-20260721",
|
||||
"companion_evidence_root": "/var/lib/aios-gitops/acceptance/aios-v2r1c1-openclaw-v2-companion-20260721T094442Z",
|
||||
"openclaw_companion": {
|
||||
"branch": "patch/openclaw/AIOS-V2R1C1-COMMAND-V2-COMPANION-20260721",
|
||||
"source_oid": "83f8f878c7da5dd8263f2af2efa80750492e5cb3",
|
||||
"companion_oid": "12d1c13170e0c5a691d67a9408e739e7a17064a3",
|
||||
"plugin_version": "2.1.0-rc.4",
|
||||
"contract_version": "aios.openclaw.command.v2",
|
||||
"signature_algorithm": "Ed25519",
|
||||
"verification_key_id": "openclaw-v2r1-candidate-ed25519",
|
||||
"artifact_sha256": "aadd5f3cfa0d8e796a21f6368f5c95e8c60e9063d6e9fcd9c4947cfa0c013671"
|
||||
},
|
||||
"step13": {
|
||||
"original_result": "FAIL_HTTP_401",
|
||||
"original_diagnosis_manifest_sha256": "320017cbfc0f31392b4d0fb5996d0e32709982a967d102592ac45efdbdaad91f",
|
||||
"remediated_result": "PASS",
|
||||
"online_negative_evidence_sha256": "57ab8efd19d3bf659a65cbeda830785f6cea9172925a3cac9e027b9b842e644f",
|
||||
"remediated_evidence_sha256": "5db59096c0586fcc0a51851d9a25d0a0b94f2bade45063fab16cc2a729f23130",
|
||||
"task_state": "COMPLETED",
|
||||
"dispatch_state": "COMPLETED",
|
||||
"task_dispatch_audit_consistency": "PASS"
|
||||
},
|
||||
"release_validation": {
|
||||
"static_revalidation": "PASS",
|
||||
"static_evidence_sha256": "c33ffaf9a0f509d6e78bdfdc0848940c166b8a800940e259b7196adab04ec604",
|
||||
"gate_a": "PASS",
|
||||
"gate_b": "PASS",
|
||||
"documentation_sync": "PASS",
|
||||
"secret_scan_violations": 0,
|
||||
"release_metadata": "PASS",
|
||||
"hermes_live": "PASS",
|
||||
"hermes_evidence_sha256": "e6553c99db55c3cdf9e16a4c1e6712064e00c41dc9965d0d179b6b1a2a1ad3ac",
|
||||
"restart_recovery": "PASS",
|
||||
"restart_evidence_sha256": "6031c92cd890dffd1de28ba75d81bed908e7da11a24aa129bcfde8efb23f0149",
|
||||
"rollback_forward": "PASS",
|
||||
"rollback_evidence_sha256": "f3d49c54e3f722facf68df2da3d82a9c82eb576f2c7c8dacb0f62c424d25737c",
|
||||
"final_health": "PASS",
|
||||
"final_health_evidence_sha256": "121cd52c0a4852b818e06be69211ae18b9fcccf976fa064e2a09c54eb8a01300",
|
||||
"global_dirty_count": 0,
|
||||
"sync_status": "fully_synced"
|
||||
},
|
||||
"validation_status": "PASS",
|
||||
"tag_status": "ABSENT",
|
||||
"preproduction_status": "NOT_STARTED",
|
||||
"production_status": "NOT_STARTED",
|
||||
"secrets_recorded": false
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# V2R1C1 Validation Result
|
||||
|
||||
Status: `RELEASE_VALIDATION_PASS / FINAL_METADATA_COMMIT_REVALIDATION_REQUIRED`
|
||||
|
||||
Release decision: `STOP_PREPRODUCTION`
|
||||
|
||||
## OpenClaw Command v2 Companion
|
||||
|
||||
- Source OID: `83f8f878c7da5dd8263f2af2efa80750492e5cb3`
|
||||
- Companion OID: `12d1c13170e0c5a691d67a9408e739e7a17064a3`
|
||||
- Plugin version: `2.1.0-rc.4`
|
||||
- Contract: `aios.openclaw.command.v2`
|
||||
- Signature: `Ed25519`
|
||||
- Artifact SHA256: `aadd5f3cfa0d8e796a21f6368f5c95e8c60e9063d6e9fcd9c4947cfa0c013671`
|
||||
- Companion unit/contract tests: `PASS`
|
||||
- V1 fallback: `REJECTED`
|
||||
- Isolated Gateway health: `PASS`
|
||||
- Online positive/negative contract: `PASS`
|
||||
- AIOS -> OpenClaw real HTTP: `PASS`
|
||||
- Task state: `COMPLETED`
|
||||
- Dispatch state: `COMPLETED`
|
||||
- Task/Dispatch/Audit consistency: `PASS`
|
||||
|
||||
## Evidence linkage
|
||||
|
||||
- Original failed Release OID: `80c4cbde03a82c30648a09b817bc2f03d5402936`
|
||||
- Original HTTP 401 diagnosis: `/var/lib/aios-gitops/acceptance/aios-v2r1c1-release-20260721/pass1-80c4cbde/13-diagnosis`
|
||||
- Original manifest SHA256: `320017cbfc0f31392b4d0fb5996d0e32709982a967d102592ac45efdbdaad91f`
|
||||
- Companion evidence root: `/var/lib/aios-gitops/acceptance/aios-v2r1c1-openclaw-v2-companion-20260721T094442Z`
|
||||
- Validated Release parent OID: `0778a31ec073e7c90003ef091f1d093c16bf22e5`
|
||||
- Online negative evidence SHA256: `57ab8efd19d3bf659a65cbeda830785f6cea9172925a3cac9e027b9b842e644f`
|
||||
- Remediated Step 13 evidence SHA256: `5db59096c0586fcc0a51851d9a25d0a0b94f2bade45063fab16cc2a729f23130`
|
||||
|
||||
## Release validation closure
|
||||
|
||||
- Gate A: `PASS`
|
||||
- Gate B: `PASS`
|
||||
- Documentation sync: `PASS`
|
||||
- Secret violations: `0`
|
||||
- Release Metadata: `PASS`
|
||||
- Hermes live: `PASS`
|
||||
- Restart recovery: `PASS`
|
||||
- Previous ↔ V2R1C1 isolated rollback/forward: `PASS`
|
||||
- Final health: `PASS`
|
||||
- Global dirty / locked / prunable: `0 / 0 / 0`
|
||||
- OID sync: `fully_synced`
|
||||
- Production traffic switched: `false`
|
||||
- Tag: `ABSENT`
|
||||
|
||||
## Remaining mandatory validation
|
||||
|
||||
本次最终元数据闭环提交将形成新的 Release OID。必须针对该最终 OID 再次复验 Gate A、Gate B、文档同步、Secret Scan、Release Metadata 和 OpenClaw 第 13 步正向/负向验证。复验通过前不得创建 Tag 或部署预生产/生产。
|
||||
@@ -0,0 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
## V2R1C1 - 2.1.0-rc.1
|
||||
|
||||
- 固定发布基线为 `fb739f6e8ff9c031d319221ace68dce157694086`。
|
||||
- 收口 Hermes 生命周期、Grant 隔离、Dispatch 恢复、运行证据和回滚/前滚验证。
|
||||
- Portal Adapter 与 Spark Provisioning 仅保留在 Archive,不属于产品发布图。
|
||||
- Future Incubator 保持隔离,不属于 V2R1C1 发布输入。
|
||||
@@ -337,6 +337,8 @@ class HermesAdapter:
|
||||
lease_seconds: int | None = None,
|
||||
) -> HermesJob:
|
||||
duration = int(lease_seconds or self.default_lease_seconds)
|
||||
if duration < 5:
|
||||
raise ValueError("lease_seconds must be >= 5")
|
||||
with self.store.lock:
|
||||
self._requeue_expired_locked()
|
||||
current = self._owned_job_locked(job_id, tenant_id, worker_id)
|
||||
|
||||
@@ -191,6 +191,14 @@ class CandidateApplication:
|
||||
if not ({"runtime", "platform_admin"} & set(context.roles)):
|
||||
raise Unauthorized("runtime reconciliation role is required")
|
||||
|
||||
@staticmethod
|
||||
def _require_control_plane_cancel(context: RequestContext) -> None:
|
||||
required = {"runtime", "platform_admin"}
|
||||
if not required.issubset(set(context.roles)):
|
||||
raise Unauthorized(
|
||||
"Hermes cancellation requires trusted AIOS control-plane authority"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _required_identity(payload: Mapping[str, Any], name: str) -> str:
|
||||
value = str(payload.get(name) or "").strip()
|
||||
@@ -459,6 +467,13 @@ class CandidateApplication:
|
||||
int(expected_revision) if expected_revision is not None else None
|
||||
)
|
||||
if action == "cancel":
|
||||
self._require_control_plane_cancel(context)
|
||||
if payload.get("worker_id") is not None:
|
||||
raise Unauthorized("Hermes workers may observe but not initiate cancel")
|
||||
if payload.get("cancellation_source") != "aios-control-plane":
|
||||
raise ValueError(
|
||||
"cancellation_source must be aios-control-plane"
|
||||
)
|
||||
result = self.hermes.cancel(
|
||||
job.job_id,
|
||||
tenant_id=job.tenant_id,
|
||||
|
||||
Regular → Executable
Regular → Executable
+18
-6
@@ -8,12 +8,28 @@ STATE_DIR="${AIOS_V2_STATE_DIR:-/var/lib/aios-v2}"
|
||||
BACKUP_ROOT="${AIOS_V2_BACKUP_ROOT:-/var/backups/aios-v2}"
|
||||
TARGET_RELEASE="${1:-}"
|
||||
RESTORE_STATE="${AIOS_V2_RESTORE_STATE:-0}"
|
||||
HEALTH_RETRIES="${AIOS_V2_ROLLBACK_HEALTH_RETRIES:-30}"
|
||||
HEALTH_RETRY_DELAY="${AIOS_V2_ROLLBACK_HEALTH_RETRY_DELAY:-1}"
|
||||
|
||||
fail() {
|
||||
echo "ERROR: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
run_healthcheck() {
|
||||
local release="$1"
|
||||
local attempt
|
||||
for ((attempt = 1; attempt <= HEALTH_RETRIES; attempt++)); do
|
||||
if AIOS_V2_SERVICE="$SERVICE" \
|
||||
AIOS_V2_STATE_DIR="$STATE_DIR" \
|
||||
"$release/deploy/aios-v2/healthcheck/check.sh"; then
|
||||
return 0
|
||||
fi
|
||||
[[ "$attempt" -lt "$HEALTH_RETRIES" ]] && sleep "$HEALTH_RETRY_DELAY"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
[[ "${EUID}" -eq 0 ]] || fail "rollback must run as root"
|
||||
[[ -n "$TARGET_RELEASE" ]] || fail "usage: $0 <release-name-or-absolute-path>"
|
||||
|
||||
@@ -53,9 +69,7 @@ mv -Tf "${CURRENT_LINK}.next" "$CURRENT_LINK"
|
||||
systemctl daemon-reload
|
||||
systemctl start "$SERVICE"
|
||||
|
||||
if AIOS_V2_SERVICE="$SERVICE" \
|
||||
AIOS_V2_STATE_DIR="$STATE_DIR" \
|
||||
"$TARGET_PATH/deploy/aios-v2/healthcheck/check.sh"; then
|
||||
if run_healthcheck "$TARGET_PATH"; then
|
||||
echo "ROLLBACK_COMPLETE target=$TARGET_PATH backup=$BACKUP_DIR"
|
||||
exit 0
|
||||
fi
|
||||
@@ -78,9 +92,7 @@ systemctl daemon-reload
|
||||
systemctl start "$SERVICE" || true
|
||||
|
||||
if [[ -n "$PREVIOUS_PATH" && -x "$PREVIOUS_PATH/deploy/aios-v2/healthcheck/check.sh" ]]; then
|
||||
AIOS_V2_SERVICE="$SERVICE" \
|
||||
AIOS_V2_STATE_DIR="$STATE_DIR" \
|
||||
"$PREVIOUS_PATH/deploy/aios-v2/healthcheck/check.sh" || true
|
||||
run_healthcheck "$PREVIOUS_PATH" || true
|
||||
fi
|
||||
|
||||
fail "rollback target failed; previous release restored; evidence=$BACKUP_DIR"
|
||||
|
||||
@@ -349,6 +349,8 @@ signature
|
||||
- 过期、未来时间超差、签名错误、Key ID 或 Fingerprint 不匹配时拒绝。
|
||||
- Fingerprint 使用恒定时间比较。
|
||||
- `key_id` 只引用密钥,不包含密钥材料。
|
||||
- Candidate 组合层必须把 `AIOS_OPENCLAW_SIGNING_KEY_ID` 原样传入 Orchestrator,
|
||||
不得在已有批准 Key ID 时回落为默认值。
|
||||
|
||||
### 11.2 OpenClawResult
|
||||
|
||||
@@ -587,6 +589,10 @@ POST /api/v2/tasks/{id}/fail -> 403
|
||||
- 默认只回滚代码。
|
||||
- 状态恢复需独立 Rollback Grant 和显式批准。
|
||||
- 回滚后必须执行 Healthcheck 与恢复验证。
|
||||
- Release Archive 必须保留 `rollback.sh` 与 `healthcheck/check.sh` 的 executable bit;
|
||||
验收测试必须阻止非执行模式进入候选包。
|
||||
- `systemctl start` 后的回滚健康检查必须执行有界 readiness 重试,默认最多 30 次、
|
||||
每次间隔 1 秒;不得因服务尚未监听的一次瞬时拒绝误判目标 Release 失败。
|
||||
|
||||
## 18. 契约变更规则
|
||||
|
||||
|
||||
@@ -1,244 +1,104 @@
|
||||
# AIOS V2R1 加固与实际验收刷新报告
|
||||
# AIOS V2R1 Hermes 生命周期最终验证报告
|
||||
|
||||
- 报告版本:`V2R1-hermes-lifecycle-refresh-20260721.2`
|
||||
- 报告版本:`V2R1-hermes-lifecycle-20260721.3`
|
||||
- 日期:`2026-07-21`
|
||||
- 分支:`patch/chatgpt/AIOS-V2R1-HERMES-LIFECYCLE-20260721`
|
||||
- 总体状态:`PARTIAL / BLOCKED_EVIDENCE_REQUIRED`
|
||||
- 固定验证 OID:`95d2e52cb55c7b913e89bc6bed2bcdacf67512d4`
|
||||
- 总体状态:`PARTIAL / BLOCKED_GLOBAL_WORKTREE_CLEANLINESS`
|
||||
- 发布决策:`STOP_PREPRODUCTION`
|
||||
- Gate A:`PASS`(执行方报告 `0 errors / 0 warnings`)
|
||||
- Gate B:`PASS`(执行方报告 `10/10`)
|
||||
- 离线 Acceptance:`PASS_WITH_EXPECTED_WARNING`(`8 passed / 0 failed / 1 expected warning`)
|
||||
- 生产发布:`NOT_APPROVED`
|
||||
|
||||
> 2026-07-21 当前分支已实现默认关闭的内部 Hermes Worker 生命周期 API、
|
||||
> `SQLiteHermesStore`、Audit/Event/Evidence 写入和严格 Dispatch/Result Binding;真实
|
||||
> localhost HTTP 专项测试为 `17/17`。在提交后的 16 步验证、持久 Evidence 和独立 Reviewer
|
||||
> 完成前,发布决策仍保持 `STOP_PREPRODUCTION`,不得把实现存在等同于最终验收放行。
|
||||
## 1. 执行结论
|
||||
|
||||
## 1. 证据来源与可信度说明
|
||||
`BLK-LIVE-HERMES-FULL-LIFECYCLE-EVIDENCE-MISSING` 的 Hermes 功能与证据子条件已在固定 OID 上全部通过。候选实现复用现有 Hermes Adapter、Queue、Lease、Task 与 Orchestrator 状态机,新增持久 SQLite Store 和默认关闭的受保护内部生命周期接口。Hermes 完整生命周期 `17/17`、候选测试 `49/49`、Gate A、Gate B `10/10`、离线 Acceptance `8/0/1`、真实 OpenClaw HTTP、重启恢复、双向回滚和最终健康检查均通过。
|
||||
|
||||
本报告依据执行方提供的实际执行结论、OID、同步状态、验收统计和日志路径刷新。当前 GitOps 工具可以提交和读取仓库内容,但不能直接读取所列主机绝对路径下的日志,因此:
|
||||
但 Owner 指令规定只有全部 Acceptance 条件同时满足时才允许正式解除该 Blocker。由于“所有 Worktree clean”失败,本报告不得把它标记为正式 `RESOLVED`;准确状态是 `EVIDENCE_COMPLETE / FORMAL_CLOSURE_BLOCKED`。
|
||||
|
||||
- 本报告将这些结果标记为“执行方已实际验证并提供证据路径”。
|
||||
- 本会话未独立重放或读取日志内容。
|
||||
- Merge、Tag、生产部署和风险接受仍需 AIOS Owner 独立批准。
|
||||
- 任何与原始日志不一致的情况,应以不可变日志、退出码和签名 Evidence 为准。
|
||||
最终发布门禁仍失败:权威 Bare Repo 登记的 88 个 worktree 中有 10 个脏 worktree。候选 worktree 和活动 Controller worktree 均 clean,且无 locked/prunable;但 Owner 的验收条件要求所有 worktree clean,因此不得准备 RC、不得发起 Tag Approval Request、不得进入预生产评审。
|
||||
|
||||
主要证据路径:
|
||||
## 2. 关键实现
|
||||
|
||||
- `/var/lib/aios-gitops/acceptance/aios-v2r1-20260721T0325Z/online-runtime-openclaw-final4.log`
|
||||
- `/var/lib/aios-gitops/acceptance/aios-v2r1-20260721T0325Z/restart-recovery.log`
|
||||
- `/var/lib/aios-gitops/acceptance/aios-v2r1-20260721T0325Z/rollback-drill-final3.log`
|
||||
- `SQLiteHermesStore` 持久保存 Job、Result、Idempotency 与 Worker Heartbeat。
|
||||
- 现有 `HermesAdapter` 保持唯一 Queue/Lease 状态机,支持指定 Job claim、租约到期 requeue、重启恢复与严格终态冲突。
|
||||
- 生命周期身份绑定覆盖 tenant、task、trace、principal、provenance、run、dispatch、job、cell、profile。
|
||||
- start/heartbeat/complete/fail 强制 Lease Owner;complete/fail/cancel 通过 `ExecutionOrchestrator.reconcile_hermes` 更新 Task 与 Dispatch。
|
||||
- cancel 仅允许同时具备 `runtime` 与 `platform_admin` 的 AIOS Control Plane,要求 `cancellation_source=aios-control-plane`,并拒绝携带 `worker_id`,Worker 只能观察取消。
|
||||
- 所有成功生命周期操作写入 Audit/Event/Execution Evidence;接口由 `AIOS_HERMES_LIFECYCLE_API_ENABLED` 控制,默认关闭。
|
||||
|
||||
## 2. 权威版本与仓库状态
|
||||
## 3. 固定 OID 验证
|
||||
|
||||
| 项目 | 刷新值 | 状态 |
|
||||
|---|---|---|
|
||||
| 权威 Bare Repo | `/data/aios-gitops/repo.git` | 已报告可用 |
|
||||
| Candidate OID | `ba7669c3b49f98cf3500af6ea966ba0db472ff3b` | 已同步 |
|
||||
| OpenClaw Task/Gitea OID | `0be3ba09e42b4f6db56461e3ca3a3fcc0a487f31` | `local_oid == gitea_oid` |
|
||||
| Codex Task/Gitea OID | `6b0db21a852928106600914075ca50114cb07def` | `local_oid == gitea_oid` |
|
||||
| 活动隔离 Release OID | `b158041b8633e658c34ce182f3c8aa97b4bf5f9a` | 当前验收 Release |
|
||||
| Controller 修复 OID | `6188da26453505dacde9d6d298191437164c8d27` | detached、clean、fully synced |
|
||||
| OpenClaw Runtime 插件 | `2.1.0-rc.3` | 已用于在线验收 |
|
||||
| OpenClaw 包含最新 Candidate | 是 | 通过 |
|
||||
| OpenClaw/Codex Worktree | clean | 通过 |
|
||||
| Worktree 锁 | `0` | 通过 |
|
||||
| Prunable Worktree | `0` | 通过 |
|
||||
| `main` 修改 | 无 | 通过 |
|
||||
| Tag 创建 | 无 | 通过 |
|
||||
| Force Push | 无 | 通过 |
|
||||
| 生产流量切换 | 无 | 通过 |
|
||||
|
||||
## 3. 原始五项高风险 Blocker
|
||||
|
||||
以下五项均已解除,当前未发现回退:
|
||||
|
||||
| Blocker | 刷新状态 | 证据摘要 |
|
||||
|---|---|---|
|
||||
| `BLK-OPENCLAW-PLAINTEXT-SECRETS` | `RESOLVED` | `plaintext/unresolved/shadowed/legacy = 0`;Gateway Token 已轮换;未记录 Secret 值 |
|
||||
| `BLK-AIOS-V2-SIGNING-MATERIAL-MISSING` | `RESOLVED` | Ed25519 Key ID `openclaw-v2r1-candidate-ed25519`;`aios:aios 0600`;sign/verify、篡改拒绝通过 |
|
||||
| `BLK-CANDIDATE-NOT-MERGED` | `RESOLVED` | OpenClaw 包含最新 Candidate;三分支本地与 Gitea OID 一致 |
|
||||
| `BLK-OPENCLAW-RUN-PROVENANCE-MISSING` | `RESOLVED` | 已实现 Workflow Provenance、持久 Store、最小权限 Child Grant、Scoped Writer、Dispatch/Result 严格绑定及相关测试 |
|
||||
| `BLK-CONTROLLER-LEGACY-GITEA-CHECK` | `RESOLVED` | 活跃代码清除旧 `aios-v23` 硬编码;Controller 12/12;Token 降权为 `read:repository` 并通过 systemd `LoadCredential` 注入 |
|
||||
|
||||
### 3.1 Run Provenance 刷新说明
|
||||
|
||||
旧状态认为插件只有进程内 `runId/sender` Map,缺少 Owner-signed schema、持久 Store 和专用 Writer。当前加固实现已经提供:
|
||||
|
||||
- 无操作权限的父 Workflow Provenance;
|
||||
- Ed25519 签名与公钥验证;
|
||||
- SQLite WAL Provenance/Grant/Usage/Event Store;
|
||||
- Runtime、Evidence、Git、Deployment、Rollback、Audit、Code Change 独立 Child Grant;
|
||||
- GitOperation 级别限制;
|
||||
- 服务级 Scoped Writer 与 CLI 单 Grant 授权;
|
||||
- 撤销、过期、重放和上下文绑定;
|
||||
- 持久 Dispatch 与 Runtime Result 严格 Reconcile。
|
||||
|
||||
因此,`BLK-OPENCLAW-RUN-PROVENANCE-MISSING` 不再成立。
|
||||
|
||||
## 4. 安全验证结果
|
||||
|
||||
### 4.1 Secret 与凭据
|
||||
|
||||
| 检查 | 结果 |
|
||||
| 项目 | 结果 |
|
||||
|---|---|
|
||||
| 原明文 Secret 发现 | `3` |
|
||||
| 当前明文 Secret | `0` |
|
||||
| unresolved | `0` |
|
||||
| shadowed | `0` |
|
||||
| legacy | `0` |
|
||||
| Gateway Token 轮换 | 通过 |
|
||||
| OneAPI 实际 Agent 调用 | 通过 |
|
||||
| Controller Token 权限 | `read:repository` |
|
||||
| Controller Token 注入 | systemd `LoadCredential` |
|
||||
| Secret 值写入记录 | 否 |
|
||||
| Python syntax/import | PASS |
|
||||
| 全部 candidate tests | `49/49` |
|
||||
| Grant isolation | `11/11` |
|
||||
| Dispatch recovery | `1/1` |
|
||||
| Hermes lifecycle | `17/17` |
|
||||
| Docs code gate / Gate A | `0 errors / 0 warnings` |
|
||||
| Secret scan | `547 tracked files / 0 violations` |
|
||||
| SQLite quick_check | `2/2 ok` |
|
||||
| Gate B | `10/10` |
|
||||
| Offline Acceptance | `8 passed / 0 failed / 1 expected warning` |
|
||||
| OpenClaw real HTTP | `COMPLETED` |
|
||||
| Hermes full live rerun | `17/17` |
|
||||
| Restart recovery | `2/2` |
|
||||
| Previous → Current rollback/forward | PASS |
|
||||
| State preservation | `STATE_PRESERVED_EXACTLY=PASS` |
|
||||
| Corrected final health (`16R`) | PASS,三服务 active |
|
||||
|
||||
### 4.2 Signing Material
|
||||
原 `16.log` 由非服务用户执行健康脚本,打印 state-dir 权限失败后被外层脚本错误覆盖为退出码 0,因此不作为通过证据。纠错后的 `16R.log` 使用受控 `sudo env`,子 shell 保留失败码,所有健康项实际 PASS 且 `EXIT_CODE=0`。原文件保留用于审计。
|
||||
|
||||
| 检查 | 结果 |
|
||||
|---|---|
|
||||
| 文件存在 | 是 |
|
||||
| Key ID | `openclaw-v2r1-candidate-ed25519` |
|
||||
| 所有者/权限 | `aios:aios 0600` |
|
||||
| 合同 | 真实 Ed25519,`aios.openclaw.command.v2` |
|
||||
| sign/verify | 通过 |
|
||||
| 篡改拒绝 | 通过 |
|
||||
| 过期拒绝 | 通过 |
|
||||
| 跨租户拒绝 | 通过 |
|
||||
回滚日志中的短暂 connection-refused 发生于 systemd 重启窗口内,受 `AIOS_V2_ROLLBACK_HEALTH_RETRIES=30` 与 1 秒间隔限制;前后两次均在界限内达到健康、输出 `ROLLBACK_COMPLETE`,并完成状态文件精确哈希对账。
|
||||
|
||||
## 5. Gate 与 Acceptance 刷新
|
||||
## 4. Evidence
|
||||
|
||||
| Gate/验收项 | 实际结果 | 刷新状态 |
|
||||
- 根目录:`/var/lib/aios-gitops/acceptance/aios-v2r1-hermes-lifecycle-20260721T054205Z`
|
||||
- `steps.tsv` SHA256:`b2ad20585ba7f576e85657827a0b1db6f252887bbd73bcd718df38623e9d95cf`
|
||||
- `final-live-gate.log` SHA256:`82040c674759dacf587658c5e936c313a1f50e8e2425be48ad891927befdf4fa`
|
||||
- `16R.log` SHA256:`641246927a372ebaa9e6dde8b018b88275b2ba15a442473759b23fb1f215d9cf`
|
||||
- `15.log` SHA256:`b0a474e2a74164f560c4f7572091911f32011c75faccd37a3c7315046275011e`
|
||||
- `13.log` SHA256:`b9f637cca6e97ed893bf38530e05cd33b78e324c5e8865d4c602dfeac22a7710`
|
||||
- `12R2.log` SHA256:`0c431f5f5f1c1b17acda160c917b08c7f4036485016c23e1236b9b6f4a78de67`
|
||||
|
||||
证据只记录身份、状态、命令、时间、退出码与 Hash,不记录 Secret 值。
|
||||
|
||||
## 5. Git 与运行态门禁
|
||||
|
||||
| 门禁 | 当前值 | 结果 |
|
||||
|---|---|---|
|
||||
| Gate A | `0 errors / 0 warnings` | `PASS` |
|
||||
| Gate B | `10/10` | `PASS` |
|
||||
| 离线 Acceptance | `8 passed / 0 failed / 1 expected warning` | `PASS_WITH_EXPECTED_WARNING` |
|
||||
| OpenClaw 在线 Health | 通过 | `PASS` |
|
||||
| OpenClaw Execute | 通过 | `PASS` |
|
||||
| OpenClaw Status | 通过 | `PASS` |
|
||||
| OpenClaw Cancel | 通过 | `PASS` |
|
||||
| OpenClaw Timeout | 通过 | `PASS` |
|
||||
| OpenClaw 幂等 | 通过 | `PASS` |
|
||||
| OpenClaw 篡改拒绝 | 通过 | `PASS` |
|
||||
| OpenClaw 过期拒绝 | 通过 | `PASS` |
|
||||
| OpenClaw 跨租户拒绝 | 通过 | `PASS` |
|
||||
| AIOS → OpenClaw 真实 HTTP | `COMPLETED` | `PASS` |
|
||||
| AIOS/Hermes 基础 enqueue/reconcile | 通过 | `PASS` |
|
||||
| OpenClaw 跨重启幂等 | 通过 | `PASS` |
|
||||
| AIOS Tenant/Agent/Task/Audit/Idempotency/Evidence 恢复 | 通过 | `PASS` |
|
||||
| SQLite `PRAGMA quick_check` | `ok` | `PASS` |
|
||||
| 受控双向回滚 | Previous `2a2b702…` ↔ Current `b158041…` | `PASS` |
|
||||
| 回滚业务状态保护 | 未覆盖业务状态 | `PASS` |
|
||||
| Live Hermes 完整生命周期 | 真实 localhost HTTP `17/17`;待提交后全序验证与 Reviewer | `MITIGATED_PENDING_REVIEW` |
|
||||
| Bare/Gitea/Candidate OID | 全部 `95d2e52cb55c7b913e89bc6bed2bcdacf67512d4` | PASS |
|
||||
| Candidate worktree | clean | PASS |
|
||||
| Active Controller | `6188da26453505dacde9d6d298191437164c8d27`,detached、clean | PASS |
|
||||
| Locked worktree | `0` | PASS |
|
||||
| Prunable worktree | `0` | PASS |
|
||||
| 全局 worktree clean | `10 dirty / 88 total` | FAIL |
|
||||
| 当前隔离 Release | `b158041b8633e658c34ce182f3c8aa97b4bf5f9a` | 已恢复 |
|
||||
| AIOS/OpenClaw/Controller services | active | PASS |
|
||||
|
||||
## 6. Controller Health
|
||||
10 个脏 worktree 均不属于本任务允许清理的范围:
|
||||
|
||||
| 检查 | 结果 |
|
||||
|---|---|
|
||||
| 活跃修复 OID | `6188da26453505dacde9d6d298191437164c8d27` |
|
||||
| 旧 `aios-v23` 硬编码 | 活跃代码中已清除 |
|
||||
| Controller 测试 | `12/12` |
|
||||
| Controller Worktree | detached;本轮初检发现 Runtime audit/state 生成 11 项脏文件,待 Controller 门禁修复或可信清理 |
|
||||
| Gitea | `true` |
|
||||
| local_sync | `synced` |
|
||||
| gitea_sync | `synced` |
|
||||
| oid_match | `true` |
|
||||
| branch_sync | `true` |
|
||||
| sync_status | `fully_synced` |
|
||||
| 首次部署失败回滚 | 已实际触发并验证 |
|
||||
1. `chatgpt/TASK-V2R1-PERSONAL-WEIXIN-GOLDEN-CONTRACT-R2-20260715`(36)
|
||||
2. `chatgpt/TASK-V2R1-PERSONAL-WEIXIN-PORTAL-ADAPTER-20260715`(2)
|
||||
3. `chatgpt/TASK-WORKTREE-CONCURRENCY-CHATGPT-20260715T055106UTC8`(2)
|
||||
4. `codex`(56)
|
||||
5. `codex/TASK-CODEX-AIOS-SPARK-RUNNER-PROVISIONING-20260717T103500UTC8`(6)
|
||||
6. `controller`(11)
|
||||
7. `openclaw`(5)
|
||||
8. `openclaw/TASK-OPENCLAW-V2R1-PERSONAL-WEIXIN-B3-EVIDENCE-HARDEN-20260716T133000UTC8`(3)
|
||||
9. `openclaw/TASK-V2R1-OPENCLAW-WEIXIN-WEB-LOGIN-CONTRACT-20260715`(20)
|
||||
10. `openclaw/TASK-WORKTREE-CONCURRENCY-OPENCLAW-20260715T055106UTC8`(3)
|
||||
|
||||
## 7. 当前唯一发布阻塞
|
||||
## 6. Reviewer
|
||||
|
||||
### `BLK-LIVE-HERMES-FULL-LIFECYCLE-EVIDENCE-MISSING`
|
||||
独立 Spark Reviewer 首先发现 cancel 权限边界不够明确;该问题已在 `95d2e52` 修复并新增三条 HTTP 断言。纠错后 Reviewer 确认代码安全边界、16 步证据与有界回滚均 PASS。对发布门禁的最终布尔复核为:`DIRTY_WORKTREE_COUNT=10` 且 `GLOBAL_WORKTREE_CLEAN=false`,所以全局门禁 FAIL,不能进入预生产评审。
|
||||
|
||||
Live AIOS 当前只暴露 Hermes `enqueue/reconcile`,没有可调用或可观测的完整在线 Worker 生命周期端点,因此以下场景尚无完整在线证据:
|
||||
## 7. Blocker 与发布决策
|
||||
|
||||
- `claim`
|
||||
- `start`
|
||||
- `heartbeat`
|
||||
- `fail`
|
||||
- `cancel`
|
||||
- `lease expiry`
|
||||
- `worker crash recovery`
|
||||
- `Cell/Profile rejection`
|
||||
- `invalid-result rejection`
|
||||
- 功能与证据子条件通过、正式关闭受阻:`BLK-LIVE-HERMES-FULL-LIFECYCLE-EVIDENCE-MISSING`
|
||||
- 直接阻断条件:`BLK-GLOBAL-WORKTREE-CLEANLINESS`
|
||||
- 状态:`BLOCKED_EVIDENCE_REQUIRED`
|
||||
- 决策:`STOP_PREPRODUCTION`
|
||||
|
||||
这不是 Run Provenance 缺失,也不是基础 Hermes Adapter 失效;它是在线验收可观测面和完整生命周期证据不足。
|
||||
本轮未修改 `main`、未创建 Tag、未 Force Push、未切换生产流量、未部署新 RC、未输出 Secret。
|
||||
|
||||
### 7.1 解除条件
|
||||
|
||||
必须在隔离预发布环境中实际完成并保存:
|
||||
|
||||
1. Worker claim/start/heartbeat 正向链路;
|
||||
2. Worker fail/cancel 终态链路;
|
||||
3. Lease 到期重新排队或重新领取;
|
||||
4. Worker 进程崩溃后的恢复;
|
||||
5. 错误 Cell/Profile 的拒绝;
|
||||
6. 非 Lease Owner 或上下文不匹配 Result 的拒绝;
|
||||
7. Dispatch、Task、Audit、Evidence、Grant Receipt 的一致性;
|
||||
8. 服务重启后继续 Reconcile;
|
||||
9. 完整命令、时间、退出码、日志路径和 Artifact Hash;
|
||||
10. Owner/Reviewer 对证据的独立复核。
|
||||
|
||||
### 7.2 不接受的替代证据
|
||||
|
||||
以下不能解除本 Blocker:
|
||||
|
||||
- 仅有单元测试文件;
|
||||
- 仅有离线 Hermes enqueue/reconcile;
|
||||
- 仅证明 OpenClaw 在线链路;
|
||||
- 仅修改状态文档;
|
||||
- 仅提供无退出码或无日志路径的口头结论;
|
||||
- 通过手工修改 Task 状态伪造 Worker 生命周期。
|
||||
|
||||
## 8. 发布决策
|
||||
|
||||
### 8.1 当前决策
|
||||
|
||||
```text
|
||||
Overall: PARTIAL / VALIDATION_IN_PROGRESS
|
||||
Gate A: PASS
|
||||
Gate B: PASS
|
||||
Offline: PASS_WITH_EXPECTED_WARNING
|
||||
OpenClaw Live: PASS
|
||||
Hermes Basic: PASS
|
||||
Hermes Full: 17/17 ISOLATED LIVE; PENDING FINAL REVIEW
|
||||
Preproduction: STOP
|
||||
Production: NOT APPROVED
|
||||
```
|
||||
|
||||
### 8.2 允许事项
|
||||
|
||||
- 继续在当前非 `main` 加固分支修复与补证据;
|
||||
- 在隔离 Release/预发布环境增加 Hermes 生命周期端点或受控验收驱动;
|
||||
- 运行在线负向测试、重启恢复和回滚演练;
|
||||
- 更新 `.agent` Evidence、Acceptance 日志与本报告;
|
||||
- 提交 Reviewer 可复核的 Evidence Manifest。
|
||||
|
||||
### 8.3 禁止事项
|
||||
|
||||
- 不得修改 `main`;
|
||||
- 不得创建生产 Tag;
|
||||
- 不得 Force Push;
|
||||
- 不得切换生产流量;
|
||||
- 不得因 Gate A/B 和 OpenClaw 已通过而忽略 Hermes 完整在线证据;
|
||||
- 不得把当前状态描述为“全部完成”或“可放行预生产”。
|
||||
|
||||
## 9. 后续最小执行计划
|
||||
|
||||
1. 按固定提交 OID 执行 16 步验证并保存命令、时间、退出码、日志和 Hash。
|
||||
2. 解决或可信隔离 Controller Worktree 的 Runtime dirty 漂移,恢复 detached/clean 门禁。
|
||||
3. 将 Evidence 写入租户隔离 `.agent` 路径并提交非 `main` 分支。
|
||||
4. 由独立 Reviewer 复核 Result/Dispatch/Task/Audit/Evidence/Grant Receipt 一致性。
|
||||
5. 全部通过后刷新为 `READY_FOR_PREPRODUCTION_REVIEW`;最终放行仍需 Owner 批准。
|
||||
|
||||
## 10. 最终结论
|
||||
|
||||
五项原始高风险 Blocker 已全部解除,Gate A、Gate B、离线 Acceptance、OpenClaw 在线链路、基础 Hermes、重启恢复、SQLite 完整性和双向回滚均已有执行方报告的实际通过结果。
|
||||
|
||||
Hermes 完整 Worker 生命周期实现与 `17/17` 隔离在线测试已经完成,但固定 OID 的完整验证、
|
||||
Controller clean、持久 Evidence 和独立 Reviewer 尚未完成。因此本次刷新结论为:
|
||||
|
||||
> **AIOS V2R1 Hermes 生命周期阻塞已实现层面缓解,当前处于固定 OID 全量验证阶段。
|
||||
> 继续停止预生产放行,直到 16 步证据、Controller clean、OID 同步和独立 Reviewer 全部通过。**
|
||||
下一步唯一允许动作:由各 worktree Owner 审查并提交、归档或可信清理上述 10 个脏 worktree,然后重新执行全局 Git 门禁。只有全局 dirty 数量降为 0 后,才允许准备 RC 与 Tag Approval Request。
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# AIOS V2R1C1 Release Notes
|
||||
|
||||
- VRC: `V2R1C1`
|
||||
- SemVer: `2.1.0-rc.1`
|
||||
- 固定产品基线: `fb739f6e8ff9c031d319221ace68dce157694086`
|
||||
- 当前状态: `RELEASE_VALIDATION_PASS / FINAL_METADATA_COMMIT_REVALIDATION_REQUIRED`
|
||||
- 发布决策: `STOP_PREPRODUCTION`
|
||||
|
||||
OpenClaw Command v2 Companion:
|
||||
|
||||
- 分支: `patch/openclaw/AIOS-V2R1C1-COMMAND-V2-COMPANION-20260721`
|
||||
- 源 OID: `83f8f878c7da5dd8263f2af2efa80750492e5cb3`
|
||||
- Companion OID: `12d1c13170e0c5a691d67a9408e739e7a17064a3`
|
||||
- 插件版本: `2.1.0-rc.4`
|
||||
- 合同: `aios.openclaw.command.v2` / `Ed25519`
|
||||
- Artifact SHA256: `aadd5f3cfa0d8e796a21f6368f5c95e8c60e9063d6e9fcd9c4947cfa0c013671`
|
||||
- 隔离验证: `AIOS -> OpenClaw V2 PASS`,正向与负向在线合同均通过。
|
||||
|
||||
旧 Release OID `80c4cbde03a82c30648a09b817bc2f03d5402936` 保留为原始 HTTP 401 失败诊断基线。Release OID `0778a31ec073e7c90003ef091f1d093c16bf22e5` 已实际完成 Gate A/B、文档同步、Secret Scan、Release Metadata、OpenClaw 第 13 步正负向、Hermes、重启恢复、隔离回滚/前滚和最终健康门禁,全部通过。
|
||||
|
||||
本次最终元数据闭环仍只修改五个允许的 Release 元数据文件;提交后形成的最终 OID 必须再次执行 Gate A/B、文档同步、Secret Scan、Release Metadata 和 OpenClaw 第 13 步正负向复验。复验通过前 Tag 保持不存在,生产流量保持未切换。
|
||||
|
||||
本分支只包含发布元数据。Personal Weixin Portal Adapter、Spark 专有 Provisioning、Future Incubator、Worktree 并发实验和长期 Agent 工作目录均未进入发布图。
|
||||
|
||||
只有最终 Release OID 的全部复验和步骤 14–17 通过后,才允许创建不可变 `V2R1C1` Tag。
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import stat
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
@@ -28,6 +30,7 @@ from aios_v2 import (
|
||||
)
|
||||
from aios_v2.dispatch_store import DispatchState, SQLiteDispatchRepository
|
||||
from aios_v2.gateway import GatewayApplication
|
||||
from aios_v2.app import build_application
|
||||
from aios_v2.persistence import DurableControlPlaneService, SQLiteSnapshotRepository
|
||||
|
||||
|
||||
@@ -68,6 +71,47 @@ def bootstrap(service: ControlPlaneService, tenant_id: str = "tenant-a"):
|
||||
|
||||
|
||||
class CandidateFlowTests(unittest.TestCase):
|
||||
def test_rollback_entrypoints_are_executable_in_release_archive(self) -> None:
|
||||
for relative in (
|
||||
"deploy/aios-v2/rollback/rollback.sh",
|
||||
"deploy/aios-v2/healthcheck/check.sh",
|
||||
):
|
||||
mode = (REPO_ROOT / relative).stat().st_mode
|
||||
self.assertTrue(mode & stat.S_IXUSR, relative)
|
||||
|
||||
def test_rollback_waits_for_bounded_service_readiness(self) -> None:
|
||||
script = (REPO_ROOT / "deploy/aios-v2/rollback/rollback.sh").read_text()
|
||||
self.assertIn("AIOS_V2_ROLLBACK_HEALTH_RETRIES", script)
|
||||
self.assertIn("run_healthcheck", script)
|
||||
self.assertIn("HEALTH_RETRY_DELAY", script)
|
||||
|
||||
def test_build_application_propagates_openclaw_signing_key_id(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
material_path = Path(temp_dir) / "signing-material.bin"
|
||||
material_path.write_bytes(OPENCLAW_PRIVATE_SEED)
|
||||
material_path.chmod(0o600)
|
||||
values = {
|
||||
"AIOS_V2_STATE_DIR": temp_dir,
|
||||
"AIOS_OPENCLAW_URL": "http://127.0.0.1:18789",
|
||||
"AIOS_OPENCLAW_SIGNING_MATERIAL_FILE": str(material_path),
|
||||
"AIOS_OPENCLAW_SIGNING_KEY_ID": "openclaw-v2r1-candidate-ed25519",
|
||||
"AIOS_OPENCLAW_CREDENTIAL_REF": "secretref:test",
|
||||
}
|
||||
previous = {key: os.environ.get(key) for key in values}
|
||||
try:
|
||||
os.environ.update(values)
|
||||
application = build_application()
|
||||
finally:
|
||||
for key, value in previous.items():
|
||||
if value is None:
|
||||
os.environ.pop(key, None)
|
||||
else:
|
||||
os.environ[key] = value
|
||||
self.assertEqual(
|
||||
application.orchestrator.openclaw_key_id,
|
||||
"openclaw-v2r1-candidate-ed25519",
|
||||
)
|
||||
|
||||
def test_http_identity_headers_are_case_insensitive(self) -> None:
|
||||
request_context = GatewayApplication.context_from_headers(
|
||||
{
|
||||
|
||||
@@ -260,7 +260,25 @@ class HermesLiveLifecycleTests(unittest.TestCase):
|
||||
|
||||
def test_06_cancel(self) -> None:
|
||||
dispatch = self._dispatch("cancel")
|
||||
status, payload = self._lifecycle("cancel", self._identity(dispatch))
|
||||
identity = self._identity(dispatch)
|
||||
runtime_only = self._headers(**{"X-AIOS-Roles": "runtime"})
|
||||
status, _ = self._request(
|
||||
"POST",
|
||||
"/api/v2/internal/runtime/hermes/lifecycle/cancel",
|
||||
{**identity, "cancellation_source": "aios-control-plane"},
|
||||
headers=runtime_only,
|
||||
)
|
||||
self.assertEqual(status, 401)
|
||||
status, _ = self._lifecycle(
|
||||
"cancel",
|
||||
identity,
|
||||
worker_id="worker-must-not-cancel",
|
||||
cancellation_source="aios-control-plane",
|
||||
)
|
||||
self.assertEqual(status, 401)
|
||||
status, payload = self._lifecycle(
|
||||
"cancel", identity, cancellation_source="aios-control-plane"
|
||||
)
|
||||
self.assertEqual(status, 200)
|
||||
self.assertEqual(payload["task"]["state"], "CANCELLED")
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"vrc": "V2R1C1",
|
||||
"semver": "2.1.0-rc.1",
|
||||
"product_baseline_oid": "fb739f6e8ff9c031d319221ace68dce157694086",
|
||||
"release_branch": "release/AIOS-V2R1C1-20260721",
|
||||
"old_release_oid": "80c4cbde03a82c30648a09b817bc2f03d5402936",
|
||||
"validated_release_parent_oid": "0778a31ec073e7c90003ef091f1d093c16bf22e5",
|
||||
"openclaw_companion_oid": "12d1c13170e0c5a691d67a9408e739e7a17064a3",
|
||||
"openclaw_plugin_version": "2.1.0-rc.4",
|
||||
"openclaw_artifact_sha256": "aadd5f3cfa0d8e796a21f6368f5c95e8c60e9063d6e9fcd9c4947cfa0c013671",
|
||||
"validation_status": "PASS",
|
||||
"deployment_status": "NOT_STARTED",
|
||||
"previous_oid": "b158041b8633e658c34ce182f3c8aa97b4bf5f9a"
|
||||
}
|
||||
Reference in New Issue
Block a user