Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
174799eed2 | ||
|
|
940a31515d | ||
|
|
f3a6ed42af | ||
|
|
1824699c59 | ||
|
|
b99d881d26 |
@@ -0,0 +1,63 @@
|
||||
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
|
||||
@@ -0,0 +1,77 @@
|
||||
# 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.
|
||||
@@ -1,64 +0,0 @@
|
||||
# V1R4C4 Integration Plan
|
||||
|
||||
## Goal
|
||||
|
||||
Create the next reliability-focused baseline after V1R4C3.
|
||||
|
||||
The integration goal is not bulk patch merging. It is controlled consolidation.
|
||||
|
||||
## Phase 1: P0 Reliability Integration
|
||||
|
||||
Merge or integrate:
|
||||
|
||||
- Gitea branch consistency sentinel.
|
||||
- Autonomous safe-mode gate.
|
||||
- Controller mutation guard.
|
||||
- Gitea incident response documentation.
|
||||
- Branch metadata drift prevention.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- Gitea refs, branch metadata and API state remain consistent.
|
||||
- Runtime acceptance sequence succeeds.
|
||||
|
||||
## Phase 2: P1 Capability Review
|
||||
|
||||
Review for consolidation:
|
||||
|
||||
- autonomous controller dispatch;
|
||||
- agent event bus;
|
||||
- GPT message plane;
|
||||
- observability capabilities;
|
||||
- governance/isolation changes;
|
||||
- search gateway improvements.
|
||||
|
||||
Each item requires:
|
||||
|
||||
- diff review;
|
||||
- duplicate detection;
|
||||
- regression check;
|
||||
- baseline compatibility decision.
|
||||
|
||||
## Phase 3: P2 Cleanup
|
||||
|
||||
Archive or supersede:
|
||||
|
||||
- smoke tests;
|
||||
- acceptance-only branches;
|
||||
- auth verification branches;
|
||||
- temporary diagnostics;
|
||||
- historical promotion requests.
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
The integration is complete when:
|
||||
|
||||
1. No patch branch has undefined status.
|
||||
2. Reliability controls are part of the active baseline.
|
||||
3. Historical branches are archived with reason.
|
||||
4. Acceptance tests pass.
|
||||
5. Future autonomous changes are protected by lifecycle controls.
|
||||
|
||||
## Safety Rule
|
||||
|
||||
Do not trade reliability for patch count reduction. A clean backlog with incorrect merges is worse than a larger but controlled backlog.
|
||||
@@ -1,138 +0,0 @@
|
||||
# Patch Lifecycle Reconciliation Inventory - 2026-07-10
|
||||
|
||||
Baseline at reconciliation: `V1R4C3`.
|
||||
|
||||
Current branch scan found:
|
||||
|
||||
- `61` branches under `patch/*`
|
||||
- `75` non-main operational branches
|
||||
- `5` P0 merge candidates
|
||||
- `16` P1 keep-open review candidates
|
||||
- `14` P2 superseded branches
|
||||
- `40` P2 archive branches
|
||||
|
||||
Note: the user-reported backlog was 59. The current runtime scan shows 61 `patch/*` branches and 75 non-main operational branches. This inventory records the current observed state.
|
||||
|
||||
## Execution Decision
|
||||
|
||||
Do not bulk merge.
|
||||
|
||||
Execute lifecycle reconciliation:
|
||||
|
||||
```text
|
||||
P0 -> controlled merge into V1R4C4 reliability integration
|
||||
P1 -> diff review, consolidate or supersede
|
||||
P2 superseded -> do not merge
|
||||
P2 archive -> preserve evidence, close/mark archived after owner-safe cleanup
|
||||
```
|
||||
|
||||
## P0 Merge Candidates
|
||||
|
||||
| Branch | Status | Action |
|
||||
|---|---|---|
|
||||
| `feature/gitea-reliability-guardrails-20260710` | `merge` | P0 reliability guardrails required for V1R4C4 |
|
||||
| `incident/gitea-autonomous-ops-stop-20260710` | `merge` | P0 incident record required for V1R4C4 |
|
||||
| `ops/patch-lifecycle-reconciliation-20260710` | `merge` | P0 lifecycle governance required before backlog cleanup |
|
||||
| `patch/autonomous-controller-systemd-health-20260709` | `merge` | P0 autonomous controller health guardrails |
|
||||
| `patch/gitea-branch-index-sync` | `merge` | P0 branch metadata drift recovery/prevention |
|
||||
|
||||
## P1 Keep-Open Review Candidates
|
||||
|
||||
| Branch | Status | Action |
|
||||
|---|---|---|
|
||||
| `patch/agent-event-bus-unified` | `keep-open` | P1 capability consolidation candidate |
|
||||
| `patch/agent-gpt-message-plane` | `keep-open` | P1 capability consolidation candidate |
|
||||
| `patch/agent-observability-webui` | `keep-open` | P1 capability consolidation candidate |
|
||||
| `patch/aios-autonomous-orchestrator-architecture-review-v1` | `keep-open` | P1 architecture review candidate |
|
||||
| `patch/autonomous-controller-dispatch-20260709` | `keep-open` | P1 controller dispatch candidate; verify against P0 guardrails |
|
||||
| `patch/chatgpt-actions-consequential-governance` | `keep-open` | P1 governance candidate |
|
||||
| `patch/fix-tag-confirmation-state-machine` | `keep-open` | P1 governance fix candidate |
|
||||
| `patch/gitops-change-archive-audit` | `keep-open` | P1 audit/governance candidate |
|
||||
| `patch/gpt-actions-consequential-governance` | `keep-open` | P1 governance candidate |
|
||||
| `patch/group-owner-agent-context-isolation` | `keep-open` | P1 isolation candidate |
|
||||
| `patch/search-gateway-governed-general-capability` | `keep-open` | P1 capability candidate |
|
||||
| `patch/self-evolution-agent-orchestration-policy` | `keep-open` | P1 governance policy candidate |
|
||||
| `patch/user-portal-rbac-ops-dashboard` | `keep-open` | P1 portal capability candidate |
|
||||
| `patch/user-profile-isolation` | `keep-open` | P1 isolation candidate |
|
||||
| `patch/v1r4c1-review-risk-fixes` | `keep-open` | P1 review risk-fix candidate; verify if superseded by V1R4C3 |
|
||||
| `patch/web-ui-complete-gitops-dashboard-20260706` | `keep-open` | P1 UI capability candidate; verify overlap with portal/dashboard patches |
|
||||
|
||||
## P2 Superseded
|
||||
|
||||
| Branch | Status | Action |
|
||||
|---|---|---|
|
||||
| `patch/V1R2C1-autonomous-orchestrator-foundation` | `superseded` | Superseded by V1R4C3 autonomous operations baseline unless diff proves otherwise |
|
||||
| `patch/V1R2C2-autonomous-recovery-chain-integration` | `superseded` | Superseded by V1R4C3 autonomous operations baseline unless diff proves otherwise |
|
||||
| `patch/V1R2C2-autonomous-recovery-loop` | `superseded` | Superseded by V1R4C3 autonomous operations baseline unless diff proves otherwise |
|
||||
| `patch/V1R2C2-system-supervisor-recovery-v1` | `superseded` | Superseded by V1R4C3 autonomous operations baseline unless diff proves otherwise |
|
||||
| `patch/V1R2C3-custom-gpt-schema-rollback` | `superseded` | Superseded by current GPT Actions runtime acceptance |
|
||||
| `patch/V1R2C3-gpt-actions-clientresponse-compat` | `superseded` | Superseded by current GPT Actions runtime acceptance |
|
||||
| `patch/V1R2C3-revert-confirm-governance-test` | `superseded` | Superseded by current owner-gate governance |
|
||||
| `patch/V1R2C3-tag-approval-action-governance` | `superseded` | Superseded by current owner-gate governance unless diff proves otherwise |
|
||||
| `patch/V1R2C3-tag-execute-idempotent-permission` | `superseded` | Superseded by current owner-gate governance unless diff proves otherwise |
|
||||
| `patch/collab-custom-gpt-20260706T104130Z` | `superseded` | Superseded by self-evolution orchestration policy and later baselines |
|
||||
| `patch/collab-local-codex-20260706T104130Z` | `superseded` | Superseded by self-evolution orchestration policy and later baselines |
|
||||
| `patch/gitops-write-auth-fix` | `superseded` | Superseded by current successful runtime write acceptance |
|
||||
| `patch/user-portal-rbac-ops-dashboard-v1r2c0` | `superseded` | Superseded by later user portal RBAC ops branches |
|
||||
| `patch/v1r3c0-user-portal-rbac-ops-20260708` | `superseded` | Superseded by V1R4C3 or later portal/dashboard candidates unless diff proves otherwise |
|
||||
|
||||
## P2 Archive
|
||||
|
||||
| Branch | Status | Action |
|
||||
|---|---|---|
|
||||
| `check/gitops-actions-loaded-20260708` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `patch/actions-double-bearer-20260706T134646Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/actions-final-smoke-20260706T135238Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/actions-invalid-diag-smoke-20260706T140311Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/actions-raw-token-smoke-20260706T134706Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/bridge-write-auth-smoke-20260706T132506Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/chatgpt-actions-acceptance-20260706T093843Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/chatgpt-actions-acceptance-20260706T094207Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/chatgpt-br-1783496324783-496c38aa` | `archive` | Temporary diagnostic/autogenerated branch; do not merge unless separately revalidated |
|
||||
| `patch/chatgpt-model-acceptance-20260706T093843Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/chatgpt-model-acceptance-20260706T094207Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/codex-gitops-acceptance-20260706T102314Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/codex-online-sync-acceptance-20260706T102819Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/codex-write-auth-smoke-20260706T115256Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gitea-runtime-acceptance-20260710` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gitops-write-auth-fix-smoke-20260706T114818Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gitops-write-auth-smoke-20260706T115230Z` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-auth-live-20260708` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-auth-patch-test` | `archive` | Archive pending diff; not in P0/P1 integration path |
|
||||
| `patch/gpt-actions-auth-test` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-auth-test-1783429590` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-commitfile-test` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-live-verify-v1r2c3-20260708` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-model-priority-test` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-nl-plan-test` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/gpt-actions-rollback-request-test` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/user-portal-me-route-diagnostics-20260709` | `archive` | Temporary diagnostic/autogenerated branch; do not merge unless separately revalidated |
|
||||
| `patch/v1r2c3-baseline-promotion-20260708` | `archive` | Archive pending diff; not in P0/P1 integration path |
|
||||
| `patch/v1r2c3-final-smoke-20260708` | `archive` | Smoke/acceptance/auth/diagnostic branch; do not merge into main |
|
||||
| `patch/v1r2c3-promotion-request-20260708` | `archive` | Archive pending diff; not in P0/P1 integration path |
|
||||
| `promote/V1R3C1-baseline` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `request/tag-V1R2C3` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `request/tag-V1R3C0-self-loop-autonomous-engine` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `request/tag-V1R3C1-self-loop-corrective` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `test/alias-test-branch` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `test/alias-verify` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `test/alias-write-verify` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `test/cmd-write-permission-verify-v2` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `test/diag-branch` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
| `test/gitea-runtime-acceptance-20260710` | `archive` | Non-production verification/request branch; retain as evidence only |
|
||||
|
||||
## Required Closeout Actions
|
||||
|
||||
1. Merge/integrate only the P0 reliability items after diff review.
|
||||
2. Review P1 candidates and convert each to either `merge` or `superseded`.
|
||||
3. Mark P2 branches as archived/superseded in GitOps records.
|
||||
4. Do not delete remote branches until branch metadata sentinel is deployed and healthy.
|
||||
5. Run acceptance after each closeout batch:
|
||||
|
||||
```text
|
||||
getRuntimeStatus -> getBaseline -> createBranch -> createPatch
|
||||
```
|
||||
|
||||
## Safety Constraint
|
||||
|
||||
Branch deletion or force update is not part of this reconciliation step. Cleanup must not create new Gitea metadata drift.
|
||||
@@ -1,170 +0,0 @@
|
||||
# Patch Lifecycle Policy
|
||||
|
||||
## Purpose
|
||||
|
||||
Prevent long-lived GitOps patch branches from accumulating into reliability risk.
|
||||
|
||||
A patch is not allowed to remain in an undefined state. Every patch branch must have one explicit lifecycle status:
|
||||
|
||||
```text
|
||||
merge
|
||||
superseded
|
||||
archive
|
||||
reject
|
||||
keep-open
|
||||
```
|
||||
|
||||
## Principle
|
||||
|
||||
The goal is not to merge every patch. The goal is to eliminate unmanaged patch state.
|
||||
|
||||
```text
|
||||
many unreviewed patches
|
||||
↓
|
||||
zero undefined patches
|
||||
```
|
||||
|
||||
## Lifecycle States
|
||||
|
||||
### merge
|
||||
|
||||
Use when the patch is still valid, current, non-duplicative, and required in the active baseline.
|
||||
|
||||
Required before merge:
|
||||
|
||||
1. Diff reviewed against current baseline.
|
||||
2. No regression against V1R4C3 or later.
|
||||
3. Conflict risk known.
|
||||
4. Runtime acceptance test defined.
|
||||
5. Owner/admin approval recorded for medium or high risk changes.
|
||||
|
||||
### superseded
|
||||
|
||||
Use when the patch intent has already been absorbed by a later baseline or a newer patch.
|
||||
|
||||
Required evidence:
|
||||
|
||||
- newer branch or baseline provides the same function;
|
||||
- old branch should not be merged;
|
||||
- branch may be retained only as historical evidence.
|
||||
|
||||
### archive
|
||||
|
||||
Use when the patch is useful as historical evidence, smoke-test proof, acceptance proof, or temporary validation branch, but should not enter main.
|
||||
|
||||
Examples:
|
||||
|
||||
- smoke tests;
|
||||
- authentication probes;
|
||||
- acceptance branches;
|
||||
- temporary diagnostics;
|
||||
- one-off verification branches.
|
||||
|
||||
### reject
|
||||
|
||||
Use when the patch is unsafe, incorrect, obsolete, or conflicts with the current architecture.
|
||||
|
||||
Required evidence:
|
||||
|
||||
- reason for rejection;
|
||||
- known replacement path, if any.
|
||||
|
||||
### keep-open
|
||||
|
||||
Use only for active work that is intentionally not ready to merge.
|
||||
|
||||
Required fields:
|
||||
|
||||
- owner;
|
||||
- next action;
|
||||
- target baseline;
|
||||
- expiration/review date.
|
||||
|
||||
## Priority Classes
|
||||
|
||||
### P0: Reliability and stop-the-line fixes
|
||||
|
||||
Must be reviewed first.
|
||||
|
||||
Includes:
|
||||
|
||||
- incident documentation;
|
||||
- Gitea consistency sentinel;
|
||||
- autonomous safe mode;
|
||||
- controller health guardrails;
|
||||
- branch metadata drift prevention;
|
||||
- fixes required to prevent autonomous operation stop.
|
||||
|
||||
### P1: Current product or platform capabilities
|
||||
|
||||
Review for consolidation into the next integration baseline.
|
||||
|
||||
Includes:
|
||||
|
||||
- agent event bus;
|
||||
- GPT message plane;
|
||||
- observability UI;
|
||||
- autonomous controller dispatch;
|
||||
- governance and isolation patches;
|
||||
- search gateway capability.
|
||||
|
||||
### P2: Historical, test, and superseded branches
|
||||
|
||||
Do not merge by default. Archive or mark superseded.
|
||||
|
||||
Includes:
|
||||
|
||||
- smoke branches;
|
||||
- auth-test branches;
|
||||
- acceptance branches;
|
||||
- rollback-request tests;
|
||||
- model acceptance probes;
|
||||
- tag request branches;
|
||||
- old promotion branches;
|
||||
- temporary test branches.
|
||||
|
||||
## Required Cleanup Cadence
|
||||
|
||||
Patch lifecycle review must run when any of the following is true:
|
||||
|
||||
1. More than 20 patch branches are open.
|
||||
2. Any patch branch is older than 7 days without status.
|
||||
3. A baseline is promoted.
|
||||
4. An incident occurs.
|
||||
5. Gitea branch metadata drift is detected.
|
||||
|
||||
## Merge Restrictions
|
||||
|
||||
Never bulk merge old patches.
|
||||
|
||||
Old patches must not be merged if:
|
||||
|
||||
- they predate the current baseline and have no diff review;
|
||||
- they are smoke/test/auth-only branches;
|
||||
- they modify governance or credentials without owner approval;
|
||||
- they would overwrite newer baseline behavior;
|
||||
- their original purpose is unknown.
|
||||
|
||||
## Post-Cleanup Acceptance
|
||||
|
||||
After lifecycle cleanup or integration baseline creation, run:
|
||||
|
||||
```text
|
||||
getRuntimeStatus
|
||||
->
|
||||
getBaseline
|
||||
->
|
||||
createBranch
|
||||
->
|
||||
createPatch
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- read operations return active runtime information;
|
||||
- write operations return commit/revision/sync status;
|
||||
- no new branch metadata drift appears.
|
||||
|
||||
## Operational Rule
|
||||
|
||||
Any patch backlog large enough to affect autonomous operation reliability is a reliability concern and must be handled through controlled lifecycle reconciliation, not ad hoc merging.
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "branch",
|
||||
"branch": "feature/v1r4c4-owner-maintenance-gate-20260710",
|
||||
"base": "main",
|
||||
"created_by": "chatgpt-gitops-bot",
|
||||
"created_at": "2026-07-10T10:31:12Z",
|
||||
"direct_main_push": false,
|
||||
"owner_approval_required": true
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
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
|
||||
@@ -0,0 +1,153 @@
|
||||
#!/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())
|
||||
Reference in New Issue
Block a user