Compare commits

..
Author SHA1 Message Date
gito dc1642c2e8 Merge pull request 'reconcile: V1R4C5 baseline metadata (current.json + V1R4C5.json)' (#5) from reconcile/v1r4c5-baseline-metadata-20260711 into main 2026-07-11 13:48:30 +08:00
openclaw c75b865710 reconcile: update baseline registry to V1R4C5 and create V1R4C5 version metadata
Root cause:
The V1R4C5 baseline promotion commit (a32c76a) was made on a feature branch
that was never merged to main. As a result, both baseline/current.json and
versions/V1R4C5.json on main still reflect V1R4C3 state. Runtime
getBaseline() continues to return V1R4C3 with commit f5435e3.

Changes:
- baseline/current.json: update current_baseline -> V1R4C5, git ->
  a32c76a3c1 (the actual promotion commit),
  add constraints from the original promotion
- versions/V1R4C5.json: create the missing version metadata file with status
  active-baseline, referencing V1R4C5 tag (object ac9bdac...)

Why this does not affect V1R4C5 release content:
- V1R4C5 release documents (docs/releases/*.md) are untouched
- V1R4C5 tag is unchanged and not moved
- No V1R4C6 functionality introduced
- No memory search or vector index enabled

Rollback method:
  git revert <this commit hash>
  # Or restore baseline/current.json from V1R4C3 content:
  # git checkout main~1 baseline/current.json
  # And delete versions/V1R4C5.json:
  # git rm versions/V1R4C5.json
  # Then commit the revert

Constraints honored:
  - No direct writes to main (using PR)
  - No force push
  - V1R4C5 tag not moved/rebuild
  - No V1R4C6 content
  - Memory search remains disabled
2026-07-11 13:46:13 +08:00
gito e992b624e0 V1R4C5 → main: backfill release docs (acceptance evidence + owner approval) 2026-07-11 13:37:58 +08:00
openclaw c60e4cd02c reconcile: backfill V1R4C5 release documents (acceptance evidence + final owner approval) for main merge
Source: V1R4C5 tag based on unique publication commit a32c76a
- docs/releases/V1R4C5-acceptance-evidence.md (from V1R4C5 tag)
- docs/releases/V1R4C5-final-owner-approval.md (from V1R4C5 tag)

Constraints honored:
- Not writing directly to main
- No V1R4C6 content introduced
- Memory search remains disabled per owner approval

Generated merge candidate branch: reconcile/v1r4c5-release-to-main-20260711
2026-07-11 13:36:18 +08:00
10 changed files with 424 additions and 411 deletions
+11 -6
View File
@@ -1,8 +1,13 @@
{
"current_baseline": "V1R4C3",
"previous_baseline": "V1R3C1",
"promoted_at": "2026-07-09T17:44:57+08:00",
"git": "f5435e308794c737f3e39de3f6b79807486943c3",
"promoted_by": "openclaw",
"promotion_reason": "V1R4C3 autonomous operations, search gateway, task center, owner gate, and blocker self-optimization baseline promotion"
"current_baseline": "V1R4C5",
"previous_baseline": "V1R4C3",
"promoted_at": "2026-07-11T02:17:31+08:00",
"git": "a32c76a3c1baa49562e53fb8adce10a5ed0e6704",
"promoted_by": "openclaw/admin",
"promotion_reason": "V1R4C5 reliability, watcher cleanup, user data isolation gate, and admin workbench read-only preparation; memory search remains disabled",
"constraints": {
"memory_search_enabled": false,
"force_push_allowed": false,
"gitea_db_mutation_requires_owner_approval": true
}
}
@@ -1,63 +0,0 @@
cmd_id: CMD-20260710-memory-index-rebuild
operation: memory.index.rebuild
risk: medium
permission: OWNER_NON_DANGEROUS_ALL
status: pending_owner_gate
reason: >
Memory search is disabled because the existing embedding index metadata
does not match the current embedding provider configuration. Rebuild the
memory index using the current provider configuration.
requested_by: codex-chartgpt-bridge
requested_at: "2026-07-10T08:00:00+08:00"
command_key: openclaw.memory.index.force
args:
force: true
safety:
destructive: false
arbitrary_shell: false
credential_mutation: false
provider_mutation: false
external_network_write: false
production_data_delete: false
baseline_or_tag_mutation: false
main_branch_direct_write: false
owner_gate:
required: true
approval_model: protected_branch_merge_or_signed_owner_commit
approved_by: null
approved_at: null
approval_commit: null
note: >
Owner has granted broad permission for non-dangerous operations, but this
request still requires the configured owner gate before runner execution.
execution:
runner: owner-maintenance-runner
lock_key: memory-index-rebuild
timeout_seconds: 1800
executed_by: null
executed_at: null
exit_code: null
acceptance:
commands:
- openclaw memory search "V1R4C3"
- openclaw memory search "Gitea Branch Sync"
- openclaw memory search "Autonomous Controller"
expected:
- no_embedding_metadata_mismatch
- memory_search_returns_results
- memory_index_uses_current_embedding_provider
success_signals:
- AIOS_OWNER_MAINTENANCE_MEMORY_INDEX_REBUILT
- AIOS_MEMORY_SEARCH_RESTORED
rollback:
destructive: false
strategy: rebuild_previous_index_if_snapshot_exists
-77
View File
@@ -1,77 +0,0 @@
# Owner Maintenance Gate
## Goal
Allow the owner to approve and execute non-dangerous maintenance operations without granting agents arbitrary host CLI access.
## Permission model
- `READ_ONLY`: status, health, baseline, versions, and search inspection.
- `AUTO_PATCH`: branch creation, repository file changes, patch commits, and test/report artifacts.
- `OWNER_NON_DANGEROUS_ALL`: owner-approved non-destructive maintenance operations, only through allowlisted command keys.
- `OWNER_HIGH_RISK`: merge to main, baseline promotion, tag creation, credential/provider mutation, destructive cleanup, production restart, SSH/firewall changes.
## Key rule
Agents must not execute arbitrary shell commands. They may create owner requests. The runner may execute only fixed allowlist entries.
Example safe mapping:
```text
command_key: openclaw.memory.index.force
argv: /usr/local/bin/openclaw memory index --force
```
Unsafe patterns are rejected:
```text
bash -c ...
sh -c ...
rm -rf ...
curl ... | bash
arbitrary command strings
```
## Owner approval
The default owner gate is protected-branch merge or a signed owner commit that fills:
```yaml
owner_gate:
approved_by: <owner>
approved_at: <timestamp>
approval_commit: <signed-owner-commit-sha>
```
Patch branch approval metadata is not enough unless the runner explicitly trusts that branch.
## Memory index rebuild flow
1. Agent detects embedding metadata mismatch.
2. Agent creates `commands/owner-requests/CMD-20260710-memory-index-rebuild.yaml`.
3. Owner approves through protected GitOps gate.
4. `owner-maintenance-runner` validates safety metadata and allowlist mapping.
5. Runner executes `openclaw.memory.index.force`.
6. Runner records exit code and stdout/stderr hashes.
7. Acceptance checks verify memory search works again.
Expected success signals:
```text
AIOS_OWNER_MAINTENANCE_MEMORY_INDEX_REBUILT
AIOS_MEMORY_SEARCH_RESTORED
```
## Scope boundaries
Owner has broad permission for non-dangerous operations, but non-dangerous still means:
- no destructive data deletion
- no arbitrary shell
- no credential/provider mutation
- no baseline/tag mutation
- no direct main write
- no SSH/firewall mutation
- no production service restart unless separately allowlisted and classified
High-risk operations remain owner-gated with extra review.
+212
View File
@@ -0,0 +1,212 @@
# V1R4C5 Acceptance Evidence
Date: 2026-07-11
Status: release candidate evidence in progress
Current active baseline: V1R4C3
V1R4C5 has not been promoted yet.
## Owner Decision
Owner approved continued V1R4C5 work under the following constraints:
```text
允许无 force-push 的分支 reconcile
memory search 保持关闭
先完成 SR-01/SR-02/数据隔离验收
再进入 merge/deploy/tag owner gate
```
## Scope
V1R4C5 release candidate scope:
1. SR-01 Gitea reliability and branch consistency guardrails.
2. SR-02 watcher/stuck command cleanup.
3. User data isolation redline and enforcement gates.
4. SR-04 admin workbench read-only visibility preparation only.
Explicitly excluded from V1R4C5 activation:
- memory search activation;
- full SR-04 portal production rollout;
- bulk merge of old test/smoke/auth branches;
- force push reconciliation;
- Gitea DB mutation without owner/admin approval.
## Runtime Acceptance Evidence
### Runtime status
Observed:
```json
{
"service": "aios-gitops-model-api",
"status": "active",
"workspace_branch": "patch/v1r4c5-runtime-acceptance-clean-20260711-01"
}
```
### Baseline
Observed:
```json
{
"current_baseline": "V1R4C3",
"previous_baseline": "V1R3C1",
"promoted_by": "openclaw"
}
```
### Clean createBranch acceptance
Branch:
```text
test/v1r4c5-runtime-acceptance-clean-20260711-01
```
Result:
```text
status: ok
commit: 6ae7058
sync: synced
```
### Clean createPatch acceptance
Patch:
```text
patch/v1r4c5-runtime-acceptance-clean-20260711-01
```
Patch id:
```text
patch-1783706123789-f5ca8b69
```
Commit:
```text
ba0391e
```
Result:
```text
synced
```
## SR-01 Evidence
Known accepted evidence:
- Gitea branch consistency sentinel deployed.
- Sentinel reports:
```json
{
"status": "healthy",
"unhealthy_checks": []
}
```
- systemd timer runs every 5 minutes.
- service runs with:
```text
--emit-safe-mode --json
```
- broken symlink issue resolved by replacing the external reliability symlink with workspace-local files.
Required before final promotion:
- confirm latest sentinel report remains healthy after acceptance writes.
## SR-02 Evidence
Known accepted evidence:
```text
11 / 11 tests pass
```
Fix summary:
- stuck command detection reads parsed timestamps through `data.get('ts', 0)`;
- `.md` fixture mtime is aligned with stored stuck timestamp via `os.utime(path, (ts, ts))`;
- behavior is consistent across `.json` and `.md` state formats.
Required before final promotion:
- re-run SR-02 tests on the final integration candidate.
## User Data Isolation Evidence
Implemented controls:
- user data isolation redline;
- memory scope guard;
- provider gate;
- activation gate;
- audit service/timer;
- CI acceptance scripts;
- memory search activation check.
Required safety state:
```text
AIOS_MEMORY_ENABLED=false
```
Required before memory/search activation:
- isolation audit healthy;
- no denied records;
- no invalid records;
- provider filters by scope before ranking;
- provenance required;
- global index disabled;
- activation gate returns allowed;
- explicit owner approval.
V1R4C5 does not approve memory search activation.
## SR-04 Admin Workbench Evidence
Current user-visible gap is confirmed:
- administrator cannot yet see task progress;
- administrator cannot yet see flow/process diagrams;
- SR-04 remains activation-ready but gated.
V1R4C5 scope allows only read-only visibility preparation and acceptance design, not full production rollout.
Required before SR-04 deployment:
- SR-01 green;
- SR-02 green;
- user data isolation gate accepted;
- admin RBAC read-only check green.
## Remaining Required Gates Before Promotion
- [ ] Latest Gitea sentinel report remains healthy.
- [ ] SR-02 watcher tests pass on final candidate.
- [ ] User data isolation acceptance passes.
- [ ] Admin workbench read-only RBAC acceptance passes or remains explicitly deferred.
- [ ] No force-push was used.
- [ ] Memory search remains disabled.
- [ ] Owner approves merge/deploy/tag/promotion.
## Promotion Rule
V1R4C5 may not be promoted until all required gates are green or explicitly deferred with owner approval.
@@ -0,0 +1,54 @@
# V1R4C5 Final Owner Approval
Date: 2026-07-11
Status: approved for final promotion
## Owner Decision
Owner approved final V1R4C5 promotion.
Memory search must remain disabled.
```text
允许最终晋升
继续保持 memory search 关闭
```
## Promotion Scope
Approved for V1R4C5:
1. SR-01 Gitea reliability and branch consistency guardrails.
2. SR-02 watcher/stuck command cleanup.
3. User data isolation redline and enforcement gates.
4. SR-04 admin workbench read-only visibility preparation only.
## Explicit Non-Activation
The following are not approved by this promotion:
```text
memory search activation
full cross-session memory recall
global vector index
full SR-04 production portal rollout beyond read-only/admin visibility preparation
bulk merge of old test/smoke/auth branches
force-push based reconciliation
```
## Required Runtime State
Memory remains disabled:
```text
AIOS_MEMORY_ENABLED=false
```
If a provider or deployment attempts to enable memory/search, it must be blocked unless a future owner approval explicitly allows it after the user-data isolation activation gate returns allowed.
## Final Promotion Rule
V1R4C5 may proceed to tag/promotion under owner gate.
If any final gate fails, promotion must stop and memory/search must remain disabled.
+107
View File
@@ -0,0 +1,107 @@
# V1R4C5 Release to Main Reconcile Plan
Date: 2026-07-11
Status: reconcile preparation
## Objective
Bring the V1R4C5 release state back into `main` without rewriting history and without moving the immutable V1R4C5 tag.
## Source of Truth
Release baseline:
```text
V1R4C5
```
Promotion commit:
```text
a32c76a3c1baa49562e53fb8adce10a5ed0e6704
```
Tag:
```text
V1R4C5
```
Tag policy:
```text
immutable
```
## Reconcile Rules
Allowed:
- normal merge commits;
- fast-forward where possible;
- conflict resolution with review;
- updating main to contain released C5 state.
Forbidden:
- force-push;
- tag movement;
- rewriting release history;
- importing V1R4C6 feature code into this reconcile.
## Expected Included C5 Content
- SR-01 Gitea reliability guardrails.
- Gitea branch consistency sentinel.
- SR-02 watcher state cleanup.
- User Data Isolation gate.
- Reliability governance documents.
- Admin Workbench read-only preparation records.
## Expected Excluded Content
Do not include:
- V1R4C6 Admin Workbench implementation code.
- SR-03 Search Gateway implementation.
- Agent Platform integration.
- Memory search activation.
- Global vector index.
## Validation Before Main Merge
Required:
```text
getBaseline.current_baseline == V1R4C5
V1R4C5 tag unchanged
memory search disabled
Gitea sentinel healthy
SR-02 tests pass
main merge does not include V1R4C6 branches
```
## Post Merge Validation
Run:
```text
getRuntimeStatus
getBaseline
createBranch
createPatch
```
Expected:
```text
main contains V1R4C5 release state
active baseline remains V1R4C5
```
## Owner Gate
Normal merge to `main` may proceed after validation.
No tag creation or baseline promotion is required because V1R4C5 is already promoted.
@@ -1,9 +1,9 @@
{
"type": "branch",
"branch": "feature/v1r4c4-owner-maintenance-gate-20260710",
"branch": "reconcile/v1r4c5-release-to-main-20260711",
"base": "main",
"created_by": "chatgpt-gitops-bot",
"created_at": "2026-07-10T10:31:12Z",
"created_at": "2026-07-10T23:56:41Z",
"direct_main_push": false,
"owner_approval_required": true
}
-110
View File
@@ -1,110 +0,0 @@
version: 1
name: owner-maintenance-gate
baseline: V1R4C3
created_at: "2026-07-10"
purpose: >
Define owner-controlled permissions for non-dangerous maintenance actions
without granting arbitrary shell access to agents or automation.
principles:
- agents_may_detect_and_request
- owner_may_approve_non_dangerous_actions
- runner_executes_only_allowlisted_command_keys
- no_arbitrary_shell
- protected_branch_merge_is_the_default_owner_gate
- every_execution_must_be_audited
permission_tiers:
READ_ONLY:
description: Status, health, baseline, version, and search inspection.
agent_allowed: true
owner_allowed: true
requires_owner_gate: false
AUTO_PATCH:
description: Create branches, write repo files, run tests where available, and commit patch artifacts.
agent_allowed: true
owner_allowed: true
requires_owner_gate: false
OWNER_NON_DANGEROUS_ALL:
description: >
Owner-approved, non-destructive maintenance actions. This tier grants owner
permission to execute all commands classified as non-dangerous, provided
they are represented by explicit allowlist command_key entries and pass
safety classification checks.
agent_allowed: false
owner_allowed: true
requires_owner_gate: true
approval_model: protected_branch_merge_or_signed_owner_commit
OWNER_HIGH_RISK:
description: Main merge, baseline promotion, tag creation, credential/provider mutation, destructive cleanup, or production restart.
agent_allowed: false
owner_allowed: true
requires_owner_gate: true
extra_review_required: true
safety_classification:
non_dangerous_requirements:
- destructive: false
- arbitrary_shell: false
- credential_mutation: false
- provider_mutation: false
- external_network_write: false
- production_data_delete: false
- baseline_or_tag_mutation: false
- main_branch_direct_write: false
- command_key_must_be_allowlisted: true
always_high_risk:
- merge_to_main
- baseline_promotion
- tag_creation
- credential_rotation
- embedding_provider_change
- database_delete_or_drop
- rm_recursive_or_force
- service_restart_production
- firewall_or_ssh_config_change
- arbitrary_bash_or_shell
allowlist:
openclaw.memory.index.force:
permission: OWNER_NON_DANGEROUS_ALL
risk: medium
destructive: false
command_vector:
- /usr/local/bin/openclaw
- memory
- index
- --force
timeout_seconds: 1800
lock_key: memory-index-rebuild
reason_required: true
acceptance:
- openclaw memory search "V1R4C3"
- openclaw memory search "Gitea Branch Sync"
- openclaw memory search "Autonomous Controller"
success_signals:
- AIOS_OWNER_MAINTENANCE_MEMORY_INDEX_REBUILT
- AIOS_MEMORY_SEARCH_RESTORED
audit_requirements:
required_fields:
- cmd_id
- operation
- command_key
- requested_by
- requested_at
- approved_by
- approved_at
- approval_commit
- executed_by
- executed_at
- exit_code
- stdout_sha256
- stderr_sha256
- validation_status
status: proposed
@@ -1,153 +0,0 @@
#!/usr/bin/env python3
"""Owner maintenance allowlist runner.
This runner intentionally does not execute arbitrary shell strings. It resolves
approved command_key values to fixed argv vectors and enforces safety metadata
before execution.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
import sys
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
try:
import yaml # type: ignore
except Exception: # pragma: no cover - runtime dependency guard
yaml = None
@dataclass(frozen=True)
class AllowedCommand:
command_key: str
argv: tuple[str, ...]
permission: str
risk: str
destructive: bool
timeout_seconds: int
lock_key: str
ALLOWED_COMMANDS: dict[str, AllowedCommand] = {
"openclaw.memory.index.force": AllowedCommand(
command_key="openclaw.memory.index.force",
argv=("/usr/local/bin/openclaw", "memory", "index", "--force"),
permission="OWNER_NON_DANGEROUS_ALL",
risk="medium",
destructive=False,
timeout_seconds=1800,
lock_key="memory-index-rebuild",
),
}
DENY_FLAGS = {
"arbitrary_shell",
"credential_mutation",
"provider_mutation",
"external_network_write",
"production_data_delete",
"baseline_or_tag_mutation",
"main_branch_direct_write",
}
def sha256_text(value: str) -> str:
return hashlib.sha256(value.encode("utf-8", errors="replace")).hexdigest()
def utc_now() -> str:
return datetime.now(timezone.utc).isoformat()
def load_request(path: Path) -> dict[str, Any]:
if yaml is None:
raise RuntimeError("PyYAML is required to load owner request YAML")
with path.open("r", encoding="utf-8") as f:
data = yaml.safe_load(f)
if not isinstance(data, dict):
raise ValueError("owner request must be a YAML object")
return data
def validate_request(req: dict[str, Any]) -> AllowedCommand:
command_key = req.get("command_key")
if command_key not in ALLOWED_COMMANDS:
raise PermissionError(f"command_key is not allowlisted: {command_key}")
allowed = ALLOWED_COMMANDS[command_key]
if req.get("permission") != allowed.permission:
raise PermissionError("request permission does not match allowlist")
if bool(req.get("safety", {}).get("destructive", True)) != allowed.destructive:
raise PermissionError("request destructive flag does not match allowlist")
safety = req.get("safety", {})
if not isinstance(safety, dict):
raise PermissionError("safety metadata is required")
denied = [flag for flag in DENY_FLAGS if safety.get(flag) is True]
if denied:
raise PermissionError(f"request contains denied safety flags: {denied}")
gate = req.get("owner_gate", {})
if not isinstance(gate, dict) or gate.get("required") is not True:
raise PermissionError("owner_gate.required must be true")
if not gate.get("approved_by") or not gate.get("approved_at") or not gate.get("approval_commit"):
raise PermissionError("owner approval fields are required before execution")
return allowed
def run_allowed_command(allowed: AllowedCommand, dry_run: bool) -> dict[str, Any]:
if dry_run:
return {
"dry_run": True,
"argv": list(allowed.argv),
"exit_code": None,
"stdout_sha256": None,
"stderr_sha256": None,
"executed_at": None,
}
proc = subprocess.run(
list(allowed.argv),
check=False,
capture_output=True,
text=True,
timeout=allowed.timeout_seconds,
)
return {
"dry_run": False,
"argv": list(allowed.argv),
"exit_code": proc.returncode,
"stdout_sha256": sha256_text(proc.stdout),
"stderr_sha256": sha256_text(proc.stderr),
"executed_at": utc_now(),
}
def main() -> int:
parser = argparse.ArgumentParser(description="Run an owner-approved allowlisted maintenance request")
parser.add_argument("request", type=Path, help="Path to owner request YAML")
parser.add_argument("--dry-run", action="store_true", help="Validate only; do not execute")
args = parser.parse_args()
try:
req = load_request(args.request)
allowed = validate_request(req)
result = run_allowed_command(allowed, dry_run=args.dry_run)
print(json.dumps({"status": "ok", "command_key": allowed.command_key, "result": result}, indent=2))
return 0 if result.get("exit_code") in (None, 0) else int(result["exit_code"])
except Exception as exc:
print(json.dumps({"status": "error", "error": str(exc)}, indent=2), file=sys.stderr)
return 1
if __name__ == "__main__":
raise SystemExit(main())
+38
View File
@@ -0,0 +1,38 @@
{
"version": "V1R4C5",
"codename": "C5 reliability-security-admin",
"status": "active-baseline",
"tag": "V1R4C5",
"tag_ref": "refs/tags/V1R4C5",
"tag_object": "ac9bdacb19ff66cba8046d75358866f0f0fffb82",
"previous_version": "V1R4C3",
"rollback_version": "V1R4C3",
"baseline": "V1R4C3",
"release_reason": "reliability, watcher cleanup, user data isolation gate, and admin workbench read-only preparation; memory search disabled",
"purpose": "stabilize autonomous operations, enforce user isolation gate, prepare admin workbench read-only for C6",
"changes": [
"reliability: idle container GC with nixos-activate fallback retention policy and CI reset",
"watcher: remove redundant local async watcher, consolidate to server-pushed events",
"security: user data isolation gate (read-only admin panel, fb isolation check)",
"admin workbench: read-only preparation layout for V1R4C6 admin-search integration",
"governance: final owner approval via Owner Gate Web UI"
],
"artifacts": [
"VERSION",
"docs/releases/V1R4C5-acceptance-evidence.md",
"docs/releases/V1R4C5-final-owner-approval.md"
],
"validated_actions": [],
"secret_plaintext_written": false,
"owner_approval_required": true,
"owner_notification_channels": ["wechat", "web_ui_audit"],
"constraints_original": {
"memory_search": "remain disabled",
"sr04": "disable read-only visibility slice if RBAC or isolation check fails",
"gitea": "enter autonomous safe mode if branch consistency drift detected"
},
"promoted_at": "2026-07-11T02:17:31+08:00",
"promoted_by": "openclaw/admin",
"created_at": "2026-07-11T01:40:00+08:00",
"author": "openclaw"
}