#!/usr/bin/env bash set -euo pipefail expected_machine_id="caa7b1019517470f9d1368b6e79db49e" state_root="/var/lib/guanghu/personas/guanghu/hlcc-v16.0.1" binary="${state_root}/release/forgejo-16.0.1-linux-amd64" config="${state_root}/config/app.ini" work_path="${state_root}/data" database="${state_root}/data/hlcc.db" api="http://127.0.0.1:3340/api/v1" receipt_root="/var/lib/guanghu/architecture-provision/receipts" receipt="${receipt_root}/HLCC-PERSONA-WRITER-RETIREMENT-20260806.json" archive_root="/var/lib/guanghu/legacy-archives/persona-writers/20260806" token_name="hlcc-persona-final-sync-20260806" temporary="$(mktemp -d)" credential_file="${temporary}/credentials" token="" completed=0 writers=( chenglu-agent.service chenglu-daily.timer guideng-agent.service kezhou-daily.timer ) oneshots=( chenglu-daily.service kezhou-daily.service ) keepers=( chenglu-team-handshake.service guideng-team-handshake.service kezhou-team-handshake.service ) declare -A old_repositories=( [chenglu-agent]="/var/lib/guanghu/forgejo/repositories/bingshuo/chenglu-agent.git" [guideng]="/var/lib/guanghu/forgejo/repositories/bingshuo/guideng.git" [kezhou]="/var/lib/guanghu/forgejo/repositories/bingshuo/kezhou.git" ) declare -A work_repositories=( [chenglu-agent]="/var/lib/chenglu-agent/repository" [guideng]="/var/lib/guanghu/personas/guideng/repository" [kezhou]="/var/lib/guanghu/personas/kezhou/repository" ) cleanup_token() { if test -n "$token"; then TOKEN_NAME="$token_name" DATABASE="$database" python3 - <<'PY' import os import sqlite3 connection = sqlite3.connect(os.environ["DATABASE"], timeout=15) try: with connection: owner = connection.execute( "select id from user where lower_name = ?", ("bingshuo",), ).fetchone() if owner: connection.execute( "delete from access_token where uid = ? and name = ?", (owner[0], os.environ["TOKEN_NAME"]), ) finally: connection.close() PY fi rm -f "$credential_file" rmdir "$temporary" 2>/dev/null || true } rollback() { systemctl enable --now guanghu-forgejo.service >/dev/null 2>&1 || true for unit in "${writers[@]}"; do systemctl enable --now "$unit" >/dev/null 2>&1 || true done cleanup_token } on_exit() { status=$? trap - EXIT if test "$completed" = 0; then rollback else cleanup_token fi exit "$status" } trap on_exit EXIT test "$(cat /etc/machine-id)" = "$expected_machine_id" test -x "$binary" test -f "$config" test -f "$database" test "$(systemctl is-active hlcc-jd-candidate.service)" = "active" test "$(curl -fsS http://127.0.0.1:3341/health | jq -r .ready)" = "true" for unit in "${keepers[@]}"; do test "$(systemctl is-active "$unit")" = "active" done for name in chenglu-agent guideng kezhou; do test -d "${old_repositories[$name]}" test -d "${state_root}/data/repositories/bingshuo/${name}.git" git --git-dir="${old_repositories[$name]}" fsck --connectivity-only --no-dangling done mkdir -p "$archive_root" "$receipt_root" for unit in "${writers[@]}" "${oneshots[@]}" guanghu-forgejo.service; do systemctl cat "$unit" >"${archive_root}/${unit}.txt" 2>&1 || true done source_paths=() for candidate in /opt/chenglu-agent /opt/guideng/agent /opt/kezhou/agent; do if test -e "$candidate"; then source_paths+=("$candidate") fi done if test "${#source_paths[@]}" -gt 0; then tar -czf "${archive_root}/legacy-persona-writer-source.tar.gz" "${source_paths[@]}" sha256sum "${archive_root}/legacy-persona-writer-source.tar.gz" \ >"${archive_root}/legacy-persona-writer-source.tar.gz.sha256" fi for unit in "${writers[@]}"; do systemctl disable --now "$unit" done for unit in "${oneshots[@]}"; do systemctl stop "$unit" || true done for unit in "${writers[@]}" "${oneshots[@]}"; do test "$(systemctl is-active "$unit" || true)" != "active" done token="$( runuser -u guanghu -- "$binary" admin user generate-access-token \ --username bingshuo \ --token-name "$token_name" \ --scopes write:repository,write:user \ --raw \ --config "$config" \ --work-path "$work_path" | tail -n 1 )" test -n "$token" test "${#token}" -ge 32 printf 'http://bingshuo:%s@127.0.0.1:3340\n' "$token" >"$credential_file" chmod 0600 "$credential_file" for name in chenglu-agent guideng kezhou; do source="${old_repositories[$name]}" target="http://127.0.0.1:3340/bingshuo/${name}.git" git -c "credential.helper=store --file ${credential_file}" \ --git-dir="$source" push --prune "$target" \ "refs/heads/*:refs/heads/*" \ "refs/tags/*:refs/tags/*" new_bare="${state_root}/data/repositories/bingshuo/${name}.git" old_refs="$( git --git-dir="$source" for-each-ref \ --format='%(refname) %(objectname)' refs/heads refs/tags | sort )" new_refs="$( git --git-dir="$new_bare" for-each-ref \ --format='%(refname) %(objectname)' refs/heads refs/tags | sort )" test "$new_refs" = "$old_refs" runuser -u guanghu -- \ git -c "safe.directory=$new_bare" --git-dir="$new_bare" \ fsck --connectivity-only --no-dangling git -C "${work_repositories[$name]}" remote set-url origin \ "https://guanghulab.com/code/bingshuo/${name}.git" done systemctl disable --now guanghu-forgejo.service test "$(systemctl is-active guanghu-forgejo.service || true)" != "active" for unit in "${keepers[@]}"; do test "$(systemctl is-active "$unit")" = "active" done test "$(curl -fsS http://127.0.0.1:3341/health | jq -r .ready)" = "true" if ss -ltnH | awk '{print $4}' | grep -Eq '(^|:)3001$'; then exit 41 fi chenglu_sha="$(git --git-dir="${old_repositories[chenglu-agent]}" rev-parse refs/heads/main)" guideng_sha="$(git --git-dir="${old_repositories[guideng]}" rev-parse refs/heads/main)" kezhou_sha="$(git --git-dir="${old_repositories[kezhou]}" rev-parse refs/heads/main)" jq -n \ --arg completed_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --arg chenglu "$chenglu_sha" \ --arg guideng "$guideng_sha" \ --arg kezhou "$kezhou_sha" \ --arg source_archive_sha "$( awk '{print $1}' "${archive_root}/legacy-persona-writer-source.tar.gz.sha256" 2>/dev/null || printf 'NO_SOURCE_ARCHIVE' )" \ '{ schema: "guanghu.persona-writer-retirement-receipt/v1", receipt_id: "HLCC-PERSONA-WRITER-RETIREMENT-20260806", target_node: "JD-FD-PRIMARY", completed_at: $completed_at, result: "PERIODIC_WRITERS_RETIRED_AFTER_EXACT_HISTORY_MIGRATION", controller: "ICE-P-ZY001", human_authority: "ICE-GL∞", repositories: [ {name:"bingshuo/chenglu-agent", main_sha:$chenglu, refs:"EXACT_MATCH"}, {name:"bingshuo/guideng", main_sha:$guideng, refs:"EXACT_MATCH"}, {name:"bingshuo/kezhou", main_sha:$kezhou, refs:"EXACT_MATCH"} ], periodic_writers: "DISABLED_AND_INACTIVE", old_repository_service: "DISABLED_AND_INACTIVE", role_handshake_services: "ALL_ACTIVE", current_code_channel: "HEALTHY", legacy_data_deleted: false, source_archive_sha256: $source_archive_sha, rule: "Scheduled repository writes are historical transport, not proof of language or persona continuity." }' >"${receipt}.tmp" chmod 0600 "${receipt}.tmp" mv "${receipt}.tmp" "$receipt" completed=1 token_to_delete="$token" cleanup_token token="" trap - EXIT printf 'PERIODIC_WRITERS_RETIRED receipt=%s token_deleted=%s\n' \ "$receipt" "$(test -n "$token_to_delete" && printf true)"