@aiassesstech/mighty-mark 0.6.26 → 0.6.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,263 @@
1
+ #!/bin/bash
2
+ # ============================================================================
3
+ # OpenClaw Upgrade Script
4
+ # Author: BB (via Greg)
5
+ # Date: 2026-03-03
6
+ # Purpose: Safely upgrade OpenClaw to latest version with backups and verification
7
+ #
8
+ # This script upgrades the OpenClaw gateway binary only.
9
+ # For plugin/extension upgrades, use the manual sync pattern documented in:
10
+ # .cursor/rules/806-openclaw-extension-upgrade.mdc
11
+ #
12
+ # Mighty Mark monitors OpenClaw version and config integrity as part of
13
+ # the morning health check. After running this script, the next morning
14
+ # report will confirm the upgrade succeeded.
15
+ # ============================================================================
16
+
17
+ set -euo pipefail
18
+
19
+ GREEN='\033[0;32m'
20
+ YELLOW='\033[1;33m'
21
+ RED='\033[0;31m'
22
+ CYAN='\033[0;36m'
23
+ NC='\033[0m'
24
+
25
+ DRY_RUN=false
26
+ SKIP_GATEWAY_RESTART=false
27
+
28
+ usage() {
29
+ echo "Usage: $0 [OPTIONS]"
30
+ echo ""
31
+ echo "Options:"
32
+ echo " --dry-run Show what would happen without making changes"
33
+ echo " --skip-restart Upgrade binary but don't restart the gateway"
34
+ echo " -h, --help Show this help"
35
+ echo ""
36
+ echo "This script upgrades the OpenClaw gateway binary."
37
+ echo "For plugin upgrades, see .cursor/rules/806-openclaw-extension-upgrade.mdc"
38
+ }
39
+
40
+ while [[ $# -gt 0 ]]; do
41
+ case $1 in
42
+ --dry-run) DRY_RUN=true; shift ;;
43
+ --skip-restart) SKIP_GATEWAY_RESTART=true; shift ;;
44
+ -h|--help) usage; exit 0 ;;
45
+ *) echo "Unknown option: $1"; usage; exit 1 ;;
46
+ esac
47
+ done
48
+
49
+ echo -e "${CYAN}════════════════════════════════════════════════════${NC}"
50
+ echo -e "${CYAN} OpenClaw Upgrade Script ${NC}"
51
+ echo -e "${CYAN}════════════════════════════════════════════════════${NC}"
52
+ echo ""
53
+
54
+ if $DRY_RUN; then
55
+ echo -e "${YELLOW} ⚠ DRY RUN — no changes will be made${NC}"
56
+ echo ""
57
+ fi
58
+
59
+ # Step 1: Record current version
60
+ echo -e "${YELLOW}[1/8] Recording current version...${NC}"
61
+ CURRENT_VERSION=$(openclaw --version 2>&1 || echo "unknown")
62
+ echo " Current: $CURRENT_VERSION"
63
+
64
+ LATEST_VERSION=$(npm view openclaw version 2>/dev/null || echo "unknown")
65
+ echo " Latest: $LATEST_VERSION"
66
+
67
+ if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ] && [ "$CURRENT_VERSION" != "unknown" ]; then
68
+ echo ""
69
+ echo -e "${GREEN} Already on latest version — nothing to do.${NC}"
70
+ exit 0
71
+ fi
72
+ echo ""
73
+
74
+ # Step 2: Backup config
75
+ echo -e "${YELLOW}[2/8] Backing up configuration...${NC}"
76
+ TIMESTAMP=$(date +%Y%m%d-%H%M%S)
77
+
78
+ if [ -f ~/.openclaw/openclaw.json ]; then
79
+ if $DRY_RUN; then
80
+ echo " [DRY RUN] Would backup ~/.openclaw/openclaw.json"
81
+ else
82
+ cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.pre-upgrade-$TIMESTAMP
83
+ echo " ✅ ~/.openclaw/openclaw.json → openclaw.json.pre-upgrade-$TIMESTAMP"
84
+ fi
85
+ else
86
+ echo " ⚠️ ~/.openclaw/openclaw.json not found — skipping"
87
+ fi
88
+
89
+ if [ -f ~/.clawdbot/openclaw.json ]; then
90
+ if $DRY_RUN; then
91
+ echo " [DRY RUN] Would backup ~/.clawdbot/openclaw.json"
92
+ else
93
+ cp ~/.clawdbot/openclaw.json ~/.clawdbot/openclaw.json.pre-upgrade-$TIMESTAMP
94
+ echo " ✅ ~/.clawdbot/openclaw.json → openclaw.json.pre-upgrade-$TIMESTAMP"
95
+ fi
96
+ fi
97
+ echo ""
98
+
99
+ # Step 3: Backup extensions
100
+ echo -e "${YELLOW}[3/8] Backing up extensions...${NC}"
101
+ if [ -d ~/.openclaw/extensions ]; then
102
+ if $DRY_RUN; then
103
+ echo " [DRY RUN] Would backup ~/.openclaw/extensions"
104
+ else
105
+ cp -r ~/.openclaw/extensions ~/.openclaw/extensions.pre-upgrade-$TIMESTAMP
106
+ echo " ✅ ~/.openclaw/extensions → extensions.pre-upgrade-$TIMESTAMP"
107
+ fi
108
+ else
109
+ echo " ⚠️ ~/.openclaw/extensions not found — skipping"
110
+ fi
111
+ echo ""
112
+
113
+ # Step 4: Backup agent workspaces (SOUL.md files etc.)
114
+ echo -e "${YELLOW}[4/8] Backing up agent workspaces...${NC}"
115
+ if [ -d ~/.openclaw/agents ]; then
116
+ if $DRY_RUN; then
117
+ echo " [DRY RUN] Would backup ~/.openclaw/agents"
118
+ else
119
+ cp -r ~/.openclaw/agents ~/.openclaw/agents.pre-upgrade-$TIMESTAMP
120
+ echo " ✅ ~/.openclaw/agents → agents.pre-upgrade-$TIMESTAMP"
121
+ fi
122
+ else
123
+ echo " ⚠️ ~/.openclaw/agents not found — skipping"
124
+ fi
125
+
126
+ # Also trigger a fleet backup if the system is installed (pre-upgrade safety net)
127
+ if [ -x /opt/fleet-backup/fleet-backup.sh ]; then
128
+ echo ""
129
+ echo " Fleet backup system detected — running pre-upgrade backup..."
130
+ if $DRY_RUN; then
131
+ echo " [DRY RUN] Would run /opt/fleet-backup/fleet-backup.sh"
132
+ else
133
+ if /opt/fleet-backup/fleet-backup.sh 2>&1 | tail -3; then
134
+ echo " ✅ Fleet backup completed"
135
+ else
136
+ echo -e " ${YELLOW}⚠️ Fleet backup had issues (non-fatal, continuing)${NC}"
137
+ fi
138
+ fi
139
+ fi
140
+ echo ""
141
+
142
+ # Step 5: Stop gateway
143
+ echo -e "${YELLOW}[5/8] Stopping openclaw-gateway...${NC}"
144
+ if $DRY_RUN; then
145
+ echo " [DRY RUN] Would stop openclaw-gateway"
146
+ elif $SKIP_GATEWAY_RESTART; then
147
+ echo " Skipped (--skip-restart)"
148
+ else
149
+ systemctl stop openclaw-gateway
150
+ sleep 2
151
+ if systemctl is-active --quiet openclaw-gateway; then
152
+ echo -e " ${RED}❌ Gateway still running — aborting${NC}"
153
+ exit 1
154
+ fi
155
+ echo " ✅ Gateway stopped"
156
+ fi
157
+ echo ""
158
+
159
+ # Step 6: Upgrade
160
+ echo -e "${YELLOW}[6/8] Upgrading OpenClaw to latest...${NC}"
161
+ if $DRY_RUN; then
162
+ echo " [DRY RUN] Would run: npm install -g openclaw@latest"
163
+ else
164
+ npm install -g openclaw@latest 2>&1 | tail -5
165
+ fi
166
+ echo ""
167
+
168
+ # Step 7: Start gateway and verify
169
+ echo -e "${YELLOW}[7/8] Starting openclaw-gateway...${NC}"
170
+ if $DRY_RUN; then
171
+ echo " [DRY RUN] Would start openclaw-gateway"
172
+ elif $SKIP_GATEWAY_RESTART; then
173
+ echo " Skipped (--skip-restart)"
174
+ else
175
+ systemctl start openclaw-gateway
176
+ echo " Waiting 10 seconds for startup..."
177
+ sleep 10
178
+
179
+ if systemctl is-active --quiet openclaw-gateway; then
180
+ echo -e " ${GREEN}✅ Gateway is running${NC}"
181
+ else
182
+ echo -e " ${RED}❌ Gateway failed to start!${NC}"
183
+ echo ""
184
+ echo -e "${RED} Checking logs:${NC}"
185
+ journalctl -u openclaw-gateway --no-pager -n 20
186
+ echo ""
187
+ echo -e "${YELLOW} To rollback:${NC}"
188
+ CURRENT_SEMVER=$(echo "$CURRENT_VERSION" | grep -oP '\d+\.\d+\.\d+' || echo "")
189
+ echo " systemctl stop openclaw-gateway"
190
+ if [ -n "$CURRENT_SEMVER" ]; then
191
+ echo " npm install -g openclaw@$CURRENT_SEMVER"
192
+ else
193
+ echo " npm install -g openclaw@<previous-version>"
194
+ fi
195
+ echo " cp ~/.openclaw/openclaw.json.pre-upgrade-$TIMESTAMP ~/.openclaw/openclaw.json"
196
+ echo " systemctl start openclaw-gateway"
197
+ exit 1
198
+ fi
199
+ fi
200
+ echo ""
201
+
202
+ # Step 8: Verify new version and health
203
+ echo -e "${YELLOW}[8/8] Post-upgrade verification...${NC}"
204
+ if $DRY_RUN; then
205
+ echo " [DRY RUN] Upgrade would go from $CURRENT_VERSION → $LATEST_VERSION"
206
+ else
207
+ NEW_VERSION=$(openclaw --version 2>&1 || echo "unknown")
208
+ echo " Previous: $CURRENT_VERSION"
209
+ echo " Current: $NEW_VERSION"
210
+ fi
211
+ echo ""
212
+
213
+ # Check that config keys are intact
214
+ echo " Checking config integrity..."
215
+ if [ -f ~/.openclaw/openclaw.json ]; then
216
+ if python3 -c "
217
+ import json, sys
218
+ with open('$HOME/.openclaw/openclaw.json') as f:
219
+ cfg = json.load(f)
220
+
221
+ issues = []
222
+ if not cfg.get('gateway', {}).get('controlUi', {}).get('allowedOrigins'):
223
+ issues.append('gateway.controlUi.allowedOrigins missing')
224
+
225
+ if not cfg.get('plugins', {}).get('allow'):
226
+ issues.append('plugins.allow missing or empty')
227
+
228
+ if issues:
229
+ for i in issues:
230
+ print(f' ⚠️ {i}')
231
+ sys.exit(1)
232
+ else:
233
+ print(' ✅ controlUi.allowedOrigins present')
234
+ print(' ✅ plugins.allow present')
235
+ " 2>/dev/null; then
236
+ :
237
+ else
238
+ echo -e " ${YELLOW}⚠️ Config may need manual review${NC}"
239
+ fi
240
+ fi
241
+
242
+ echo ""
243
+ if $DRY_RUN; then
244
+ echo -e "${YELLOW}════════════════════════════════════════════════════${NC}"
245
+ echo -e "${YELLOW} DRY RUN COMPLETE — no changes were made ${NC}"
246
+ echo -e "${YELLOW} Run without --dry-run to apply ${NC}"
247
+ echo -e "${YELLOW}════════════════════════════════════════════════════${NC}"
248
+ else
249
+ echo -e "${GREEN}════════════════════════════════════════════════════${NC}"
250
+ echo -e "${GREEN} Upgrade complete: ${NEW_VERSION:-$LATEST_VERSION}${NC}"
251
+ echo -e "${GREEN}════════════════════════════════════════════════════${NC}"
252
+ echo ""
253
+ echo " Backups saved with timestamp: $TIMESTAMP"
254
+ echo " To clean up old backups later:"
255
+ echo " ls ~/.openclaw/*.pre-upgrade-*"
256
+ echo " ls -d ~/.openclaw/extensions.pre-upgrade-* 2>/dev/null"
257
+ echo " ls -d ~/.openclaw/agents.pre-upgrade-* 2>/dev/null"
258
+ echo ""
259
+ echo " Mighty Mark's next morning check will verify the upgrade."
260
+ echo " To check immediately:"
261
+ echo " openclaw tool mark_health"
262
+ fi
263
+ echo ""
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # validate-openclaw-config.sh — Validate openclaw.json before gateway restart
4
+ #
5
+ # Usage (on VPS):
6
+ # bash /opt/mighty-mark/validate-openclaw-config.sh
7
+ # bash /opt/mighty-mark/validate-openclaw-config.sh /path/to/openclaw.json
8
+ #
9
+ # This prevents Bug 10 (Rule 806): gateway crash from invalid config.
10
+ # OpenClaw uses strict Zod validation. Unknown keys or out-of-range values
11
+ # cause every agent to spam "Invalid config" errors on restart.
12
+ #
13
+ # Known schema constraints (OpenClaw 2026.3.x):
14
+ # agents.defaults.subagents.maxSpawnDepth: 1-5
15
+ # agents.defaults.subagents.maxChildrenPerAgent: 1-20
16
+ # agents.defaults.subagents: .strict() (no unknown keys)
17
+ # session.dmScope: "main" | "per-channel-peer"
18
+ # tools.exec.security: "full" | "allowlist" | "none"
19
+
20
+ set -euo pipefail
21
+
22
+ CONFIG_FILE="${1:-/root/.openclaw/openclaw.json}"
23
+
24
+ if [ ! -f "$CONFIG_FILE" ]; then
25
+ echo "❌ Config file not found: $CONFIG_FILE"
26
+ exit 1
27
+ fi
28
+
29
+ echo "=== OpenClaw Config Validation ==="
30
+ echo "File: $CONFIG_FILE"
31
+ echo ""
32
+
33
+ ERRORS=0
34
+ WARNINGS=0
35
+
36
+ # Check valid JSON
37
+ if ! python3 -c "import json; json.load(open('$CONFIG_FILE'))" 2>/dev/null; then
38
+ echo "❌ FATAL: File is not valid JSON"
39
+ exit 1
40
+ fi
41
+ echo "✅ Valid JSON"
42
+
43
+ # Check known schema constraints using python3
44
+ python3 << 'PYEOF'
45
+ import json, sys
46
+
47
+ config_file = sys.argv[1] if len(sys.argv) > 1 else "/root/.openclaw/openclaw.json"
48
+ with open(config_file) as f:
49
+ cfg = json.load(f)
50
+
51
+ errors = []
52
+ warnings = []
53
+
54
+ # Check agents.defaults.subagents
55
+ defaults = cfg.get("agents", {}).get("defaults", {})
56
+ subagents = defaults.get("subagents", {})
57
+
58
+ if subagents:
59
+ known_keys = {"maxSpawnDepth", "maxChildrenPerAgent"}
60
+ unknown = set(subagents.keys()) - known_keys
61
+ for k in unknown:
62
+ errors.append(f"agents.defaults.subagents.{k}: Unknown key (OpenClaw uses .strict() — will be rejected)")
63
+
64
+ depth = subagents.get("maxSpawnDepth")
65
+ if depth is not None:
66
+ if not isinstance(depth, (int, float)) or depth < 1 or depth > 5:
67
+ errors.append(f"agents.defaults.subagents.maxSpawnDepth={depth}: must be 1-5")
68
+
69
+ children = subagents.get("maxChildrenPerAgent")
70
+ if children is not None:
71
+ if not isinstance(children, (int, float)) or children < 1 or children > 20:
72
+ errors.append(f"agents.defaults.subagents.maxChildrenPerAgent={children}: must be 1-20")
73
+
74
+ # Check session.dmScope
75
+ session = cfg.get("session", {})
76
+ dm_scope = session.get("dmScope")
77
+ if dm_scope and dm_scope not in ("main", "per-channel-peer"):
78
+ errors.append(f"session.dmScope={dm_scope}: must be 'main' or 'per-channel-peer'")
79
+
80
+ # Check tools.exec.security
81
+ tools = cfg.get("tools", {}).get("exec", {})
82
+ security = tools.get("security")
83
+ if security and security not in ("full", "allowlist", "none"):
84
+ errors.append(f"tools.exec.security={security}: must be 'full', 'allowlist', or 'none'")
85
+
86
+ # Check agents.list exists and has entries
87
+ agents_list = cfg.get("agents", {}).get("list", [])
88
+ if not agents_list:
89
+ warnings.append("agents.list is empty — no agents configured")
90
+
91
+ # Report
92
+ if errors:
93
+ print("")
94
+ for e in errors:
95
+ print(f"❌ {e}")
96
+ print("")
97
+ print(f"RESULT: {len(errors)} error(s) found — DO NOT restart the gateway!")
98
+ print("Fix the config and re-run this script.")
99
+ sys.exit(1)
100
+
101
+ if warnings:
102
+ print("")
103
+ for w in warnings:
104
+ print(f"⚠️ {w}")
105
+
106
+ print("")
107
+ print("✅ Config passes known schema constraints")
108
+ print(" Run 'openclaw doctor' for full validation (includes constraints this script doesn't check)")
109
+ PYEOF
110
+
111
+ echo ""
112
+ echo "=== Also running 'openclaw doctor' for full validation ==="
113
+ if command -v openclaw &>/dev/null; then
114
+ openclaw doctor 2>&1 || true
115
+ else
116
+ echo "⚠️ 'openclaw' command not found — skipping full validation"
117
+ echo " Install with: npm install -g @aiassesstech/openclaw"
118
+ fi