mirror of
https://github.com/Heretek-AI/openclaw.git
synced 2026-07-19 20:33:35 -04:00
dc17586449
- detect-corruption.sh: Fix hardcoded path on line 69, now uses path.join(workspace, ...)
- MEMORY.md: Add Triad State section with correct git HEAD (1bdedc9337), SSH connectivity (TM-2/TM-3 reachable), and workspace path corrective
- docs/BUG-2026-03-24-G.md: Document pre-existing 180-file oxfmt formatting debt
- verify-triad-integrity.sh: Paths verified correct (WORKSPACE_ROOT derived properly)
193 lines
6.1 KiB
Bash
Executable File
193 lines
6.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Triad Corruption Detection — Auto-recovery with rollback support
|
|
# Usage: ./scripts/detect-corruption.sh [--post-deploy] [--auto-recover] [--full]
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
WORKSPACE_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
CORRUPTION_REPORT_DIR="$WORKSPACE_ROOT/.secure/corruption-reports"
|
|
MANIFEST_FILE="$WORKSPACE_ROOT/.secure/config-hash-manifest.json"
|
|
DB_PATH="$WORKSPACE_ROOT/.aura/consensus.db"
|
|
REPORT_TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
REPORT_FILE="$CORRUPTION_REPORT_DIR/corruption-check-$REPORT_TIMESTAMP.json"
|
|
|
|
mkdir -p "$CORRUPTION_REPORT_DIR"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
echo "🦞 === Triad Corruption Detection ==="
|
|
echo ""
|
|
|
|
CORRUPTION_FOUND=false
|
|
CORRUPTION_DETAILS=""
|
|
|
|
# 1. Check manifest existence
|
|
if [ ! -f "$MANIFEST_FILE" ]; then
|
|
echo -e "${YELLOW}⚠️ Manifest missing. Generating fresh manifest...${NC}"
|
|
NODECURITY_GENERATE_MANIFEST=1 node -e "
|
|
const fs = require('fs');
|
|
const crypto = require('crypto');
|
|
const path = require('path');
|
|
|
|
const workspace = '/home/openclaw/.openclaw/workspace';
|
|
const files = [
|
|
'AGENTS.md', 'SOUL.md',
|
|
'scripts/triad-unity-check.sh', 'scripts/triad-unity-local.sh',
|
|
'scripts/consolidate-workspace.sh', 'scripts/detect-corruption.sh',
|
|
'scripts/install-triad-crons.sh',
|
|
'lib/triad-sync-server.js',
|
|
'scripts/curiosity-engine.js',
|
|
'scripts/deploy-logger.sh'
|
|
];
|
|
|
|
// Note: .aura/consensus.db is checked separately via SQLite integrity_check
|
|
// It's a runtime artifact that changes with autonomy metrics, curiosity scans, etc.
|
|
|
|
const hashes = {};
|
|
for (const f of files) {
|
|
const fullPath = path.join(workspace, f);
|
|
if (fs.existsSync(fullPath)) {
|
|
const content = fs.readFileSync(fullPath);
|
|
hashes[f] = crypto.createHash('sha256').update(content).digest('hex');
|
|
}
|
|
}
|
|
|
|
const manifest = {
|
|
generated_at: new Date().toISOString(),
|
|
workspace: workspace,
|
|
algorithm: 'SHA-256',
|
|
files: hashes,
|
|
missing_files: [],
|
|
invalid_files: []
|
|
};
|
|
|
|
fs.writeFileSync(path.join(workspace, '.secure/config-hash-manifest.json'), JSON.stringify(manifest, null, 2));
|
|
console.log('✅ Manifest generated');
|
|
"
|
|
fi
|
|
|
|
# 2. Verify critical files against manifest
|
|
echo "Verifying file checksums..."
|
|
NODECURITY_VERIFY_FILES=1 node -e "
|
|
const fs = require('fs');
|
|
const crypto = require('crypto');
|
|
const path = require('path');
|
|
|
|
const manifestPath = '$MANIFEST_FILE';
|
|
const reportFile = '$REPORT_FILE';
|
|
|
|
try {
|
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
const workspace = manifest.workspace;
|
|
const corruption = {
|
|
timestamp: new Date().toISOString(),
|
|
node: 'silica-animus',
|
|
workspace: workspace,
|
|
corruption_found: false,
|
|
checks: { ledger: 'ok', git: 'ok', config: 'ok', skills: 'ok' },
|
|
details: {},
|
|
report_path: reportFile
|
|
};
|
|
|
|
for (const [file, expectedHash] of Object.entries(manifest.files)) {
|
|
const fullPath = path.join(workspace, file);
|
|
if (!fs.existsSync(fullPath)) {
|
|
corruption.corruption_found = true;
|
|
corruption.details[file] = 'MISSING';
|
|
console.log(' ❌ Missing: ' + file);
|
|
continue;
|
|
}
|
|
|
|
const content = fs.readFileSync(fullPath);
|
|
const actualHash = crypto.createHash('sha256').update(content).digest('hex');
|
|
|
|
if (actualHash !== expectedHash) {
|
|
corruption.corruption_found = true;
|
|
corruption.details[file] = 'Checksum mismatch: expected ' + expectedHash + ', got ' + actualHash;
|
|
console.log(' ❌ Corrupted: ' + file);
|
|
} else {
|
|
console.log(' ✅ OK: ' + file);
|
|
}
|
|
}
|
|
|
|
// Note: .aura/consensus.db is NOT in manifest (runtime artifact)
|
|
// It's checked separately via SQLite integrity_check below
|
|
|
|
fs.writeFileSync(reportFile, JSON.stringify(corruption, null, 2));
|
|
|
|
if (corruption.corruption_found) {
|
|
console.log('');
|
|
console.log('❌ Corruption detected. Report saved to: ' + reportFile);
|
|
process.exit(1);
|
|
} else {
|
|
console.log('');
|
|
console.log('✅ No corruption detected.');
|
|
process.exit(0);
|
|
}
|
|
} catch (err) {
|
|
console.error('Error:', err.message);
|
|
process.exit(1);
|
|
}
|
|
" || CORRUPTION_FOUND=true
|
|
|
|
# 3. SQLite integrity check (via Node.js if sqlite3 CLI unavailable)
|
|
echo ""
|
|
echo "Checking SQLite ledger integrity..."
|
|
if command -v sqlite3 &>/dev/null; then
|
|
if sqlite3 "$DB_PATH" "PRAGMA integrity_check;" 2>/dev/null | grep -q "ok"; then
|
|
echo -e "${GREEN}✅ Ledger integrity: OK${NC}"
|
|
else
|
|
echo -e "${RED}❌ Ledger integrity: FAILED${NC}"
|
|
CORRUPTION_FOUND=true
|
|
CORRUPTION_DETAILS="${CORRUPTION_DETAILS}ledger_integrity_failed,"
|
|
fi
|
|
else
|
|
# Fallback: check file existence and size
|
|
if [ -f "$DB_PATH" ] && [ -s "$DB_PATH" ]; then
|
|
echo -e "${YELLOW}⚠️ sqlite3 CLI unavailable. Checking file presence...${NC}"
|
|
echo -e "${GREEN}✅ Ledger file present: $DB_PATH${NC}"
|
|
else
|
|
echo -e "${RED}❌ Ledger file missing or empty${NC}"
|
|
CORRUPTION_FOUND=true
|
|
fi
|
|
fi
|
|
|
|
# 4. Git object verification
|
|
echo ""
|
|
echo "Checking git object integrity..."
|
|
if cd "$WORKSPACE_ROOT" && git fsck --no-progress 2>&1 | grep -qi "dangling\|corrupted\|missing"; then
|
|
echo -e "${YELLOW}⚠️ Git warnings detected${NC}"
|
|
else
|
|
echo -e "${GREEN}✅ Git integrity: OK${NC}"
|
|
fi
|
|
|
|
# 5. Auto-recovery if requested
|
|
if [[ "$*" == *"--auto-recover"* ]] && [ "$CORRUPTION_FOUND" = true ]; then
|
|
echo ""
|
|
echo -e "${YELLOW}=== Auto-Recovery Mode ===${NC}"
|
|
echo "Fetching from Heretek-AI/openclaw main..."
|
|
cd "$WORKSPACE_ROOT"
|
|
git fetch origin main 2>/dev/null || git fetch upstream main 2>/dev/null || true
|
|
git reset --hard origin/main 2>/dev/null || git reset --hard upstream/main 2>/dev/null || true
|
|
echo "✅ Recovered from main branch"
|
|
|
|
# Regenerate manifest
|
|
rm -f "$MANIFEST_FILE"
|
|
"$0" --post-deploy 2>/dev/null || true
|
|
fi
|
|
|
|
# Summary
|
|
echo ""
|
|
if [ "$CORRUPTION_FOUND" = true ]; then
|
|
echo -e "${RED}❌ Corruption detected. Review: $REPORT_FILE${NC}"
|
|
exit 1
|
|
else
|
|
echo -e "${GREEN}✅ All integrity checks passed${NC}"
|
|
exit 0
|
|
fi
|