set -euo pipefail release=/home/ps/knowledge-v5-search-20260916 test ! -e "$release" test "$(docker image inspect zyt/wecom-admin:current --format '{{.Id}}')" = 'sha256:5eedfd342540725f61075cf02fe94a93e94e68f06719e3f9eac6c064f204a975' python3 - <<'PY' from pathlib import Path import json,hashlib manifest=json.loads(Path('/home/ps/knowledge-v4-review-20260916/manifest.json').read_text(encoding='utf-8-sig')) changed=[] for row in manifest: path=Path('/opt/im-admin')/row['path'].replace('\\','/') if not path.is_file() or hashlib.sha256(path.read_bytes()).hexdigest().lower()!=row['sha256'].lower(): changed.append(row['path']) assert not changed, 'Production files changed since the last release: '+str(changed) print('Production baseline matches the verified full-review release.',flush=True) PY mkdir -m 700 "$release" cd /opt/im-admin tar -czf "$release/source-before.tar.gz" wechat_rpa admin-web/apps/web-antd/src admin-web/apps/web-antd/dist deploy/im-admin/compose.yaml docker tag zyt/wecom-admin:current zyt/wecom-admin:before-knowledge-v5-search-20260916 docker image inspect zyt/wecom-admin:current --format '{{.Id}}' > "$release/image-before.txt" docker exec -i im-admin-api-1 python - <<'PY' | tee "$release/before.json" import sqlite3,json c=sqlite3.connect('file:/data/backend.db?mode=ro',uri=True) tables=['archive_message','archive_conversation','archive_person','archive_source_account','desktop_accounts','model_providers','users','knowledge_item','knowledge_job','knowledge_watch'] counts={t:c.execute('SELECT COUNT(*) FROM '+t).fetchone()[0] for t in tables} print(json.dumps({'counts':counts,'job_states':dict(c.execute('SELECT status,COUNT(*) FROM knowledge_job GROUP BY status')), 'enabled_tenants':c.execute('SELECT COUNT(*) FROM knowledge_settings WHERE enabled!=0').fetchone()[0]})) PY