#!/usr/bin/env bash
set -Eeuo pipefail
umask 077

STEP_ID=STEP_050M07R18_R02_PREFLIGHT_FULL_TREE_COUNT_FIX_CONTINUATION
RESULT=STOP_R18_R02_NOT_STARTED
STOP_REASON=none
CURRENT_PHASE=initialization
CORE_CHANGE_COMPLETE=false
CORE_CHANGE_REPEATED=false
TARGET_INSTALLER_RERUN=false
MACHINE_GIT_COMPLETE=false
ROUTER_MACHINE_CLOSE_RERUN=false
COPY_VERIFY=FAIL
HTTP_VERIFY_PASS=false
RUNTIME_IMPACT=true
PUBLICATION_BARRIER=none
STEP_REPORT_URL=''
PROJECT_SOURCE_POST_URL=''
PROJECT_SOURCE_POST_FILE_URL=''
LOCAL_M07_PLAN_URL=''
GLOBAL_PROJECT_PLAN_URL=''
ACCESS_MAP_URL=''
VM100_PUBLIC_URL=''
VM101_PUBLIC_URL=''
VM121_PUBLIC_URL=''
VM101_MODEL_URL=''
VM101_METHODS_URL=''
VM130_SOURCE_URL=''
LATEST_ROOT_URL='https://reports.secret-studio.ru/latest/'
OLD_ROOT_URL='https://reports.secret-studio.ru/old/'
FACTS_URL=''
VERIFY_URL=''
ROLLBACK_URL=''
PUBLIC_OBJECT_KIND='step-report'
PREVIOUS_MOVED_COUNT=0
NEW_GENERATION_ID=''
NEW_GENERATION_DIR=''
PREVIOUS_GENERATION_ID='r15b2-20260716-215914'
ACTIVATION_TRANSACTION_DIR=''
ACTIVATION_ROLLBACK_FILE=''
TARGET_BACKUP_DIR=''
TARGET_ROLLBACK_FILE=''
SNAPSHOT_NAME=''
VM101_COMMIT=''
VM101_TREE=''
VM101_COUNT=''
R01_FAILURE_CLASSIFIED=false
R01_STEP_DIR=''
R01_STOP_REPORT_URL='https://reports.secret-studio.ru/latest/20260718-075534_step050m07r18_r02_preflight_full_tree_count_fix_continuation_stop/'

BUNDLE_DIR="$(cd "$(dirname "$0")" && pwd -P)"
SELF="$(readlink -f "$0")"
BUNDLE_ZIP="${BUNDLE_ZIP:?BUNDLE_ZIP is required}"
EXPECTED_BUNDLE_SHA256="${EXPECTED_BUNDLE_SHA256:?EXPECTED_BUNDLE_SHA256 is required}"
EXPECTED_INSTALLER_SHA256="${EXPECTED_INSTALLER_SHA256:?EXPECTED_INSTALLER_SHA256 is required}"
BASE="${ROUTER_OPS_BASE:-/opt/router-ops}"
PUBLISHER="$BASE/bin/router-publish-report"
HTTP="$BASE/bin/router-http-verify"
FINALIZER="$BASE/bin/router-step-finalize"
SAFE_BUILDER="$BASE/bin/router-public-safe-payload"
HTML_BUILDER="$BASE/bin/router-public-html-aliases"
MACHINE_CLOSE="$BASE/bin/router-machine-close"
WORKFLOW_LIB="$BASE/lib/router-step-workflow.sh"
CONTRACT_LIB="$BASE/lib/router-publication-contract.sh"
TS="$(date -u +%Y%m%d-%H%M%S)"
STEP_DIR="$BASE/steps/${TS}_${STEP_ID}"
mkdir -p "$STEP_DIR"; chmod 700 "$STEP_DIR"
STEP_FILE="$STEP_DIR/step-code.sh"
BUNDLE_COPY="$STEP_DIR/$(basename "$BUNDLE_ZIP")"
cp -a "$SELF" "$STEP_FILE"; chmod 700 "$STEP_FILE"
cp -a "$BUNDLE_ZIP" "$BUNDLE_COPY"

REPORT="$STEP_DIR/report.txt"
FACTS="$STEP_DIR/facts.json"
VERIFY="$STEP_DIR/verify.txt"
ROLLBACK="$STEP_DIR/rollback.sh"
MAIN_LOG="$STEP_DIR/main.log"
PROGRESS="$STEP_DIR/progress.log"
TRANSFER="$STEP_DIR/transfer-verify.txt"
PHASE_CURRENT="$STEP_DIR/phase-current.env"
PHASE_EVENTS="$STEP_DIR/phase-events.log"
PREFLIGHT_DIR="$STEP_DIR/publication-preflight"
COMPONENTS="$STEP_DIR/components"
EXPORT_DIR="$STEP_DIR/vm101-export"
mkdir -p "$PREFLIGHT_DIR" "$COMPONENTS" "$EXPORT_DIR"

exec 3>&1
exec >>"$MAIN_LOG" 2>&1
progress(){ printf '>>> [%s] %s\n' "$(date '+%F %T')" "$*" | tee -a "$PROGRESS" >&3; }
source "$BUNDLE_DIR/plans/current-links.env"
source "$WORKFLOW_LIB"
source "$CONTRACT_LIB"
router_step_workflow_init "$PHASE_CURRENT" "$PHASE_EVENTS" \
  transfer_verification target_preflight target_core target_postcheck machine_git vm130_exact_clone \
  source_publication model_publication methods_publication plan_publication project_source_publication \
  step_report_publication external_http_verification

vm101_run_script(){
  local script="$1"
  ssh -o BatchMode=yes pve-mgts \
    "ssh -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 'sh -s'" <"$script"
}
vm101_run_command(){
  local cmd="$1"
  ssh -o BatchMode=yes pve-mgts \
    "ssh -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 '$cmd'"
}
field(){ local file="$1" key="$2"; awk -F= -v k="$key" '$1==k{v=substr($0,index($0,"=")+1)} END{print v}' "$file"; }
phase_begin(){ CURRENT_PHASE="$1"; router_step_phase_begin "$1" "${2:-none}"; progress "$1"; }
phase_done(){ router_step_phase_complete "$1" "${2:-complete}"; }

write_rollback(){
  cat >"$ROLLBACK" <<EOF
#!/usr/bin/env bash
set -Eeuo pipefail
[[ "\${CONFIRM_R18_ROLLBACK:-}" == YES ]] || { echo RESULT=STOP_R18_ROLLBACK_CONFIRMATION_REQUIRED; echo 'Set CONFIRM_R18_ROLLBACK=YES'; exit 2; }
ACTIVATION_ROLLBACK='$ACTIVATION_ROLLBACK_FILE'
TARGET_ROLLBACK='$TARGET_ROLLBACK_FILE'
[[ -n "\$ACTIVATION_ROLLBACK" && -n "\$TARGET_ROLLBACK" ]] || { echo RESULT=STOP_R18_ROLLBACK_EVIDENCE_MISSING; exit 2; }
cat > /tmp/r18-runtime-rollback.sh <<'REMOTE'
#!/bin/sh
set -eu
ACTIVATION_ROLLBACK='$ACTIVATION_ROLLBACK_FILE'
TARGET_ROLLBACK='$TARGET_ROLLBACK_FILE'
[ -x "\$ACTIVATION_ROLLBACK" ] || { echo RESULT=STOP_R18_ACTIVATION_ROLLBACK_MISSING; exit 3; }
[ -x "\$TARGET_ROLLBACK" ] || { echo RESULT=STOP_R18_TARGET_ROLLBACK_MISSING; exit 3; }
"\$ACTIVATION_ROLLBACK"
"\$TARGET_ROLLBACK"
echo RESULT=PASS_R18_RUNTIME_AND_FILES_ROLLED_BACK
REMOTE
ssh -o BatchMode=yes pve-mgts "ssh -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 'sh -s'" < /tmp/r18-runtime-rollback.sh
rm -f /tmp/r18-runtime-rollback.sh
/opt/router-ops/bin/router-machine-close VM101 'R18 rollback: restore pre-R18 VM101 runtime and managed files'
echo RESULT=PASS_R18_ROLLBACK_AND_MACHINE_GIT_PUBLISHED
EOF
  chmod 700 "$ROLLBACK"
}

write_docs(){
  local step_sha
  step_sha="$(sha256sum "$STEP_FILE"|awk '{print $1}')"
  write_rollback
  cat >"$REPORT" <<EOF
RESULT=$RESULT
STEP_ID=$STEP_ID
STOP_REASON=$STOP_REASON
CURRENT_PHASE=$CURRENT_PHASE
R01_FAILURE_CLASSIFIED=$R01_FAILURE_CLASSIFIED
R01_CORE_CHANGE_COMPLETE=false
R01_TARGET_CORE_STATUS=pending
R01_STOP_REPORT_URL=$R01_STOP_REPORT_URL
CORE_CHANGE_COMPLETE=$CORE_CHANGE_COMPLETE
CORE_CHANGE_REPEATED=$CORE_CHANGE_REPEATED
TARGET_INSTALLER_RERUN=$TARGET_INSTALLER_RERUN
MACHINE_GIT_COMPLETE=$MACHINE_GIT_COMPLETE
ROUTER_MACHINE_CLOSE_RERUN=$ROUTER_MACHINE_CLOSE_RERUN
COPY_VERIFY=$COPY_VERIFY
STEP_SHA256=$step_sha
HTTP_VERIFY_PASS=$HTTP_VERIFY_PASS
PUBLICATION_BARRIER=$PUBLICATION_BARRIER
RUNTIME_IMPACT=$RUNTIME_IMPACT
SNAPSHOT_NAME=${SNAPSHOT_NAME:-none}
PREVIOUS_GENERATION_ID=$PREVIOUS_GENERATION_ID
NEW_GENERATION_ID=${NEW_GENERATION_ID:-none}
NEW_GENERATION_DIR=${NEW_GENERATION_DIR:-none}
VM101_COMMIT=${VM101_COMMIT:-none}
VM101_TREE=${VM101_TREE:-none}
VM101_MANAGED_FILE_COUNT=${VM101_COUNT:-none}
STEP_REPORT_URL=${STEP_REPORT_URL:-PENDING_NOT_PUBLISHED}
PROJECT_SOURCE_POST_URL=${PROJECT_SOURCE_POST_URL:-PENDING_NOT_PUBLISHED}
PROJECT_SOURCE_POST_FILE_URL=${PROJECT_SOURCE_POST_FILE_URL:-PENDING_NOT_PUBLISHED}
LOCAL_M07_PLAN_URL=$LOCAL_M07_PLAN_URL
GLOBAL_PROJECT_PLAN_URL=$GLOBAL_PROJECT_PLAN_URL
ACCESS_MAP_URL=$ACCESS_MAP_URL
VM100_PUBLIC_URL=$VM100_PUBLIC_URL
VM101_PUBLIC_URL=$VM101_PUBLIC_URL
VM121_PUBLIC_URL=$VM121_PUBLIC_URL
VM101_MODEL_URL=$VM101_MODEL_URL
VM101_METHODS_URL=$VM101_METHODS_URL
VM130_SOURCE_URL=$VM130_SOURCE_URL
LATEST_ROOT_URL=$LATEST_ROOT_URL
OLD_ROOT_URL=$OLD_ROOT_URL
FACTS_URL=${FACTS_URL:-PENDING_NOT_PUBLISHED}
VERIFY_URL=${VERIFY_URL:-PENDING_NOT_PUBLISHED}
ROLLBACK_URL=${ROLLBACK_URL:-PENDING_NOT_PUBLISHED}
PUBLIC_OBJECT_KIND=$PUBLIC_OBJECT_KIND
PREVIOUS_MOVED_COUNT=$PREVIOUS_MOVED_COUNT
EOF
  cat >"$VERIFY" <<EOF
RESULT=$RESULT
VM130_R17_HELPERS_VERIFIED=true
PUBLICATION_PREFLIGHT_BEFORE_VM101_CORE=true
VM101_PRE_BASELINE_COMMIT=d01016420799492ea6e0ce1a526abafe910f18ed
VM101_PRE_BASELINE_TREE=1972e4bc69dfbfdfb14d210a44a3fdc772ee88de
VM101_POST_EXPECTED_TREE=c110da07f841ba1686ea7261388a78d575c1ec23
VM101_POST_EXPECTED_COUNT=35
SNAPSHOT_NAME=${SNAPSHOT_NAME:-none}
TARGET_PACKAGE_SHA256=1c0dd0036e22308150a317cc964ab60b94a4caf42eb715429b93dbd2ab96a16e
PREVIOUS_GENERATION_ID=$PREVIOUS_GENERATION_ID
NEW_GENERATION_ID=${NEW_GENERATION_ID:-none}
ACTIVE_GENERATION_REPLACED=$CORE_CHANGE_COMPLETE
REPAIR_COUNTER_RESET=$CORE_CHANGE_COMPLETE
DIRECT_FAILOPEN_USED=false
PARTIAL_ACTIVATION=false
TARGET_POSTCHECK=$([[ "$CURRENT_PHASE" == complete || "$(router_step_phase_status target_postcheck 2>/dev/null || true)" == complete ]] && echo PASS || echo NOT_COMPLETE)
MACHINE_GIT_COMPLETE=$MACHINE_GIT_COMPLETE
HTTP_VERIFY_PASS=$HTTP_VERIFY_PASS
PUBLICATION_BARRIER=$PUBLICATION_BARRIER
EOF
  python3 - "$FACTS" <<PY
import json,sys
obj={
 "schema":"router-step-facts-v1","step_id":"$STEP_ID","result":"$RESULT","stop_reason":"$STOP_REASON",
 "current_phase":"$CURRENT_PHASE","r01_failure_classified":"$R01_FAILURE_CLASSIFIED"=="true","r01_core_change_complete":False,"r01_target_core_status":"pending","r01_stop_report_url":"$R01_STOP_REPORT_URL","core_change_complete":"$CORE_CHANGE_COMPLETE"=="true",
 "core_change_repeated":False,"target_installer_rerun":False,"machine_git_complete":"$MACHINE_GIT_COMPLETE"=="true",
 "router_machine_close_rerun":False,"copy_verify":"$COPY_VERIFY","http_verify_pass":"$HTTP_VERIFY_PASS"=="true",
 "publication_barrier":"$PUBLICATION_BARRIER","runtime_impact":True,"direct_failopen_used":False,
 "snapshot_name":"$SNAPSHOT_NAME","previous_generation_id":"$PREVIOUS_GENERATION_ID","new_generation_id":"$NEW_GENERATION_ID",
 "vm101_commit":"$VM101_COMMIT","vm101_tree":"$VM101_TREE","vm101_managed_file_count":"$VM101_COUNT",
 "step_report_url":"$STEP_REPORT_URL","vm101_public_url":"$VM101_PUBLIC_URL","model_url":"$VM101_MODEL_URL",
 "methods_url":"$VM101_METHODS_URL","plan_url":"$LOCAL_M07_PLAN_URL","project_source_post_url":"$PROJECT_SOURCE_POST_URL"
}
with open(sys.argv[1],'w') as f: json.dump(obj,f,indent=2,sort_keys=True); f.write('\n')
PY
}

print_final(){
  write_docs
  for x in \
    "RESULT=$RESULT" \
    "STEP_REPORT_URL=${STEP_REPORT_URL:-PENDING_NOT_PUBLISHED}" \
    "PROJECT_SOURCE_POST_URL=${PROJECT_SOURCE_POST_URL:-PENDING_NOT_PUBLISHED}" \
    "PROJECT_SOURCE_POST_FILE_URL=${PROJECT_SOURCE_POST_FILE_URL:-PENDING_NOT_PUBLISHED}" \
    "LOCAL_M07_PLAN_URL=$LOCAL_M07_PLAN_URL" \
    "GLOBAL_PROJECT_PLAN_URL=$GLOBAL_PROJECT_PLAN_URL" \
    "ACCESS_MAP_URL=$ACCESS_MAP_URL" \
    "VM100_PUBLIC_URL=$VM100_PUBLIC_URL" \
    "VM101_PUBLIC_URL=$VM101_PUBLIC_URL" \
    "VM121_PUBLIC_URL=$VM121_PUBLIC_URL" \
    "VM101_MODEL_URL=$VM101_MODEL_URL" \
    "VM101_METHODS_URL=$VM101_METHODS_URL" \
    "VM130_SOURCE_URL=$VM130_SOURCE_URL" \
    "LATEST_ROOT_URL=$LATEST_ROOT_URL" \
    "OLD_ROOT_URL=$OLD_ROOT_URL" \
    "FACTS_URL=${FACTS_URL:-PENDING_NOT_PUBLISHED}" \
    "VERIFY_URL=${VERIFY_URL:-PENDING_NOT_PUBLISHED}" \
    "ROLLBACK_URL=${ROLLBACK_URL:-PENDING_NOT_PUBLISHED}" \
    "PUBLIC_OBJECT_KIND=$PUBLIC_OBJECT_KIND" \
    "PREVIOUS_MOVED_COUNT=$PREVIOUS_MOVED_COUNT" \
    "COPY_VERIFY=$COPY_VERIFY" \
    "STEP_SHA256=$(sha256sum "$STEP_FILE"|awk '{print $1}')" \
    "HTTP_VERIFY_PASS=$HTTP_VERIFY_PASS" \
    "RUNTIME_IMPACT=$RUNTIME_IMPACT"; do printf '%s\n' "$x" >&3; done
}

publish_stop_report(){
  set +e
  write_docs
  local html safe label
  html="$STEP_DIR/stop-html"; safe="$STEP_DIR/stop-safe"; label="step050m07r18_r02_preflight_full_tree_count_fix_continuation_stop"
  python3 "$HTML_BUILDER" --facts "$FACTS" --verify "$VERIFY" --rollback "$ROLLBACK" --output-dir "$html" --title-prefix R18 >/dev/null 2>&1
  "$SAFE_BUILDER" "$safe" "$STEP_FILE" step-code.sh "$REPORT" report.txt "$FACTS" facts.json "$VERIFY" verify.txt "$ROLLBACK" rollback.sh "$MAIN_LOG" main.log "$PROGRESS" progress.log "$TRANSFER" transfer-verify.txt "$PHASE_CURRENT" phase-current.txt "$PHASE_EVENTS" phase-events.log "$html/facts-public.html" facts-public.html "$html/verify-public.html" verify-public.html "$html/rollback-public.html" rollback-public.html >/dev/null 2>&1
  "$FINALIZER" --label "$label" --payload-dir "$safe" --workflow-current "$PHASE_CURRENT" --workflow-events "$PHASE_EVENTS" --output-env "$STEP_DIR/stop-finalize.env" --expect-kind step-report >"$STEP_DIR/stop-finalize.log" 2>&1
  if [[ -s "$STEP_DIR/stop-finalize.env" ]]; then
    STEP_REPORT_URL="$(field "$STEP_DIR/stop-finalize.env" PUBLIC_URL)"
    PUBLICATION_BARRIER=verified
    HTTP_VERIFY_PASS=true
  fi
  set -e
}

stop(){
  local result="$1" reason="$2" rc="${3:-1}"
  trap - ERR
  RESULT="$result"; STOP_REASON="$reason"
  router_step_phase_fail "$CURRENT_PHASE" "$reason" >/dev/null 2>&1 || true
  if [[ "$CORE_CHANGE_COMPLETE" != true && -n "$TARGET_ROLLBACK_FILE" ]]; then
    progress "pre-core rollback"
    cat >"$STEP_DIR/target-rollback-remote.sh" <<EOF
#!/bin/sh
set -eu
[ -x '$TARGET_ROLLBACK_FILE' ] && '$TARGET_ROLLBACK_FILE'
EOF
    vm101_run_script "$STEP_DIR/target-rollback-remote.sh" >"$COMPONENTS/target-rollback.log" 2>&1 || true
  fi
  if ! router_step_publication_is_verified; then publish_stop_report || true; fi
  print_final
  exit "$rc"
}
trap 'stop STOP_R18_UNEXPECTED_ERROR "phase=$CURRENT_PHASE line=$LINENO rc=$?" 1' ERR

publish_object(){
  local label="$1" expect="$2" outvar="$3"; shift 3
  local log="$STEP_DIR/publish-${expect}.log" envf="$STEP_DIR/publish-${expect}.env"
  "$PUBLISHER" "$label" "$@" >"$log"
  router_publication_contract_load "$log" "$expect" || return 1
  "$HTTP" --url "$RPC_PUBLIC_URL" --output "$STEP_DIR/http-${expect}-index.html" >"$STEP_DIR/http-${expect}.log" 2>&1
  printf -v "$outvar" '%s' "$RPC_PUBLIC_URL"
  cp "$log" "$envf"
}

phase_begin transfer_verification
actual_zip="$(sha256sum "$BUNDLE_COPY"|awk '{print $1}')"
actual_inst="$(sha256sum "$STEP_FILE"|awk '{print $1}')"
[[ "$actual_zip" == "$EXPECTED_BUNDLE_SHA256" && "$actual_inst" == "$EXPECTED_INSTALLER_SHA256" ]] || stop STOP_COPY_OR_TRANSFER_ERROR sha_mismatch 20
(cd "$BUNDLE_DIR" && sha256sum -c manifest.sha256) >"$STEP_DIR/manifest.log"
BUNDLE_ROOT="$BUNDLE_DIR" "$BASE/bin/router-bundle-gate" "$BUNDLE_DIR" >"$STEP_DIR/bundle-gate.log"
grep -qx RESULT=PASS_ROUTER_BUNDLE_GATE "$STEP_DIR/bundle-gate.log" || stop STOP_COPY_OR_TRANSFER_ERROR bundle_gate 20
COPY_VERIFY=PASS
cat >"$TRANSFER" <<EOF
COPY_VERIFY=PASS
EXPECTED_BUNDLE_SHA256=$EXPECTED_BUNDLE_SHA256
ACTUAL_BUNDLE_SHA256=$actual_zip
EXPECTED_INSTALLER_SHA256=$EXPECTED_INSTALLER_SHA256
ACTUAL_INSTALLER_SHA256=$actual_inst
MANIFEST_VERIFY=PASS
SYNTAX_VERIFY=PASS
FIXTURE_VERIFY=PASS
EOF
phase_done transfer_verification

phase_begin target_preflight
R01_STEP_DIR="$(find "$BASE/steps" -mindepth 1 -maxdepth 1 -type d -name '*_STEP_050M07R18_FULL_POOL_REFRESH_TRIGGER_AND_TRANSACTIONAL_REPLACEMENT_R01' -print | LC_ALL=C sort | tail -n 1)"
[[ -n "$R01_STEP_DIR" && -f "$R01_STEP_DIR/report.txt" && -f "$R01_STEP_DIR/phase-current.env" ]] || stop STOP_R18_R02_R01_EVIDENCE_MISSING "$R01_STEP_DIR" 21
grep -Fqx 'CORE_CHANGE_COMPLETE=false' "$R01_STEP_DIR/report.txt" || stop STOP_R18_R02_R01_CORE_CLASSIFICATION mismatch 21
grep -Fqx 'target_preflight=failed' "$R01_STEP_DIR/phase-current.env" || stop STOP_R18_R02_R01_PREFLIGHT_STATUS mismatch 21
grep -Fqx 'target_core=pending' "$R01_STEP_DIR/phase-current.env" || stop STOP_R18_R02_R01_CORE_STATUS mismatch 21
R01_FAILURE_CLASSIFIED=true
[[ "$(hostname)" == router-ops ]] || stop STOP_R18_WRONG_HOST "$(hostname)" 21
while read -r sha path; do [[ -f "$path" && "$(sha256sum "$path"|awk '{print $1}')" == "$sha" ]] || stop STOP_R18_VM130_HELPER_SHA "$path" 21; done <"$BUNDLE_DIR/reference/expected-vm130.sha256"
"$BASE/bin/router-workflow-r17-selftest" "$STEP_DIR/r17-selftest" >"$COMPONENTS/r17-selftest.log"
grep -qx RESULT=PASS_ROUTER_WORKFLOW_R17_SELFTEST "$COMPONENTS/r17-selftest.log" || stop STOP_R18_R17_SELFTEST marker 21
declare -a PREFS=(
  'vm101_git_source_r18_preflight:vm101:README.md'
  'vm101_model_full_pool_refresh_r18:vm101-model:model/system-model-template.txt'
  'vm101_methods_full_pool_refresh_r18:vm101-methods:methods/methods-limitations.txt'
  'local_architecture_plan_vm101_autonomous_hmn_recovery_r18:local-m07-plan:plans/canonical-plan-r18.md'
  'project_source_post_vm101_full_pool_refresh_r18:project-source-post:post/WG_PAID_MGTS_VM101_FULL_POOL_REFRESH_TRIGGER_AND_TRANSACTIONAL_REPLACEMENT_R18.md'
  'step050m07r18_full_pool_refresh_trigger_and_transactional_replacement:step-report:README.md'
)
for spec in "${PREFS[@]}"; do
  IFS=: read -r label kind rel <<<"$spec"
  "$PUBLISHER" --classify "$label" >"$PREFLIGHT_DIR/${kind}.classify"
  grep -Fqx "PUBLIC_OBJECT_KIND=$kind" "$PREFLIGHT_DIR/${kind}.classify" || stop STOP_R18_PUBLICATION_CLASSIFY "$label" 22
  "$PUBLISHER" --preflight "$label" "$BUNDLE_DIR/$rel" >"$PREFLIGHT_DIR/${kind}.preflight"
  grep -qx RESULT=PASS_ROUTER_PUBLISH_PREFLIGHT "$PREFLIGHT_DIR/${kind}.preflight" || stop STOP_R18_PUBLICATION_PREFLIGHT "$label" 22
done
vm101_run_script "$BUNDLE_DIR/scripts/vm101-preflight.sh" >"$COMPONENTS/vm101-preflight.log"
grep -qx RESULT=PASS_R18_VM101_PREFLIGHT "$COMPONENTS/vm101-preflight.log" || stop STOP_R18_VM101_PREFLIGHT marker 23
SNAPSHOT_NAME="R18_PRE_$(date -u +%Y%m%d_%H%M%S)"
[[ ${#SNAPSHOT_NAME} -le 32 && ${#SNAPSHOT_NAME} -le 40 ]] || stop STOP_R18_SNAPSHOT_NAME_LENGTH "$SNAPSHOT_NAME" 23
ssh -o BatchMode=yes pve-mgts "bash -s -- '$SNAPSHOT_NAME'" <"$BUNDLE_DIR/scripts/pve-snapshot.sh" >"$COMPONENTS/pve-snapshot.log"
grep -qx RESULT=PASS_R18_PRE_SNAPSHOT_CREATED "$COMPONENTS/pve-snapshot.log" || stop STOP_R18_SNAPSHOT marker 23
phase_done target_preflight

phase_begin target_core
progress "transfer verified VM101 target package"
ssh -o BatchMode=yes pve-mgts "ssh -o BatchMode=yes -i /root/.ssh/pve_to_openwrt_mgts_ed25519 root@10.71.100.2 'cat > /tmp/vm101-r18-target-package.tar.gz'" <"$BUNDLE_DIR/payload/vm101-r18-target-package.tar.gz"
remote_pkg_sha="$(vm101_run_command "sha256sum /tmp/vm101-r18-target-package.tar.gz | cut -d' ' -f1")"
[[ "$remote_pkg_sha" == 1c0dd0036e22308150a317cc964ab60b94a4caf42eb715429b93dbd2ab96a16e ]] || stop STOP_R18_REMOTE_PACKAGE_SHA "$remote_pkg_sha" 24
vm101_run_script "$BUNDLE_DIR/scripts/vm101-apply.sh" >"$COMPONENTS/vm101-apply.log"
grep -qx RESULT=PASS_R18_VM101_PAYLOAD_INSTALLED "$COMPONENTS/vm101-apply.log" || stop STOP_R18_VM101_APPLY marker 24
TARGET_BACKUP_DIR="$(field "$COMPONENTS/vm101-apply.log" BACKUP_DIR)"
TARGET_ROLLBACK_FILE="$(field "$COMPONENTS/vm101-apply.log" ROLLBACK_FILE)"
[[ -n "$TARGET_BACKUP_DIR" && -n "$TARGET_ROLLBACK_FILE" ]] || stop STOP_R18_TARGET_ROLLBACK_EVIDENCE missing 24
progress "live provider refresh, generation build and transactional replacement"
set +e
vm101_run_script "$BUNDLE_DIR/scripts/vm101-run-core.sh" > >(tee -a "$COMPONENTS/vm101-core.log" "$MAIN_LOG" >&3) 2>&1 &
core_pid=$!
(
  while kill -0 "$core_pid" 2>/dev/null; do sleep 30; kill -0 "$core_pid" 2>/dev/null && progress "target_core heartbeat: provider/generation transaction still running" || true; done
) & heartbeat_pid=$!
wait "$core_pid"; core_rc=$?
kill "$heartbeat_pid" >/dev/null 2>&1 || true; wait "$heartbeat_pid" >/dev/null 2>&1 || true
set -e
[[ "$core_rc" -eq 0 ]] || stop STOP_R18_TARGET_CORE "rc=$core_rc" 25
grep -qx RESULT=PASS_R18_FULL_POOL_REFRESH "$COMPONENTS/vm101-core.log" || stop STOP_R18_TARGET_CORE_MARKER missing 25
NEW_GENERATION_ID="$(field "$COMPONENTS/vm101-core.log" NEW_GENERATION_ID)"
NEW_GENERATION_DIR="$(field "$COMPONENTS/vm101-core.log" NEW_GENERATION_DIR)"
ACTIVATION_TRANSACTION_DIR="$(field "$COMPONENTS/vm101-core.log" ACTIVATION_TRANSACTION_DIR)"
ACTIVATION_ROLLBACK_FILE="$(field "$COMPONENTS/vm101-core.log" ACTIVATION_ROLLBACK_FILE)"
[[ -n "$NEW_GENERATION_ID" && "$NEW_GENERATION_ID" != "$PREVIOUS_GENERATION_ID" && -n "$ACTIVATION_ROLLBACK_FILE" ]] || stop STOP_R18_CORE_EVIDENCE missing 25
CORE_CHANGE_COMPLETE=true
phase_done target_core "$NEW_GENERATION_ID"

phase_begin target_postcheck
vm101_run_script "$BUNDLE_DIR/scripts/vm101-postcheck.sh" >"$COMPONENTS/vm101-postcheck.log"
grep -qx RESULT=PASS_R18_VM101_POSTCHECK "$COMPONENTS/vm101-postcheck.log" || stop STOP_R18_TARGET_POSTCHECK marker 26
phase_done target_postcheck

phase_begin machine_git
set +e
"$MACHINE_CLOSE" VM101 "$STEP_ID: full-pool refresh trigger and transactional replacement" > >(tee -a "$COMPONENTS/router-machine-close.log" "$MAIN_LOG" >&3) 2>&1
close_rc=$?
set -e
[[ "$close_rc" -eq 0 ]] || stop STOP_R18_ROUTER_MACHINE_CLOSE "rc=$close_rc" 27
VM101_PUBLIC_URL="$(field "$COMPONENTS/router-machine-close.log" VM101_PUBLIC_URL)"
[[ "$VM101_PUBLIC_URL" == https://reports.secret-studio.ru/latest/*/ ]] || stop STOP_R18_VM101_PUBLIC_URL missing 27
MACHINE_GIT_COMPLETE=true
phase_done machine_git

phase_begin vm130_exact_clone
CLONE="$STEP_DIR/vm101-exact-clone"
git clone --quiet --no-tags https://github.com/DChuvelev/wg-paid-vm101.git "$CLONE"
VM101_COMMIT="$(git -C "$CLONE" rev-parse HEAD)"
VM101_TREE="$(git -C "$CLONE" rev-parse HEAD^{tree})"
VM101_COUNT="$(git -C "$CLONE" ls-tree -r --name-only HEAD | wc -l | tr -d ' ')"
[[ "$VM101_TREE" == c110da07f841ba1686ea7261388a78d575c1ec23 && "$VM101_COUNT" == 35 && "$VM101_COMMIT" != d01016420799492ea6e0ce1a526abafe910f18ed ]] || stop STOP_R18_EXACT_CLONE_MISMATCH "commit=$VM101_COMMIT tree=$VM101_TREE count=$VM101_COUNT" 28
[[ -z "$(git -C "$CLONE" status --porcelain)" ]] || stop STOP_R18_EXACT_CLONE_DIRTY dirty 28
{
 echo "COMMIT=$VM101_COMMIT"; echo "TREE=$VM101_TREE"; echo "MANAGED_FILE_COUNT=$VM101_COUNT";
 git -C "$CLONE" show --stat --oneline --decorate --no-renames HEAD;
} >"$COMPONENTS/vm101-git-proof.txt"
phase_done vm130_exact_clone

phase_begin source_publication
"$HTTP" --url "$VM101_PUBLIC_URL" --output "$STEP_DIR/vm101-source-index.html" >"$COMPONENTS/vm101-source-http.log" 2>&1
phase_done source_publication

vm101_run_script "$BUNDLE_DIR/scripts/vm101-export-artifacts.sh" >"$COMPONENTS/vm101-export.log"
grep -qx RESULT=PASS_R18_VM101_EXPORT "$COMPONENTS/vm101-export.log" || stop STOP_R18_VM101_EXPORT marker 29
export_sha="$(field "$COMPONENTS/vm101-export.log" EXPORT_SHA256)"
vm101_run_command 'cat /tmp/vm101-r18-export.tar.gz' >"$STEP_DIR/vm101-r18-export.tar.gz"
[[ "$(sha256sum "$STEP_DIR/vm101-r18-export.tar.gz"|awk '{print $1}')" == "$export_sha" ]] || stop STOP_R18_EXPORT_TRANSFER_SHA mismatch 29
gzip -t "$STEP_DIR/vm101-r18-export.tar.gz"
tar -xzf "$STEP_DIR/vm101-r18-export.tar.gz" -C "$EXPORT_DIR"
(cd "$EXPORT_DIR" && sha256sum -c export-manifest.sha256 >/dev/null)

phase_begin model_publication
MODEL="$STEP_DIR/model-public"; mkdir -p "$MODEL"
cp "$BUNDLE_DIR/model/system-model-template.txt" "$MODEL/system-model.txt"
printf '\nLive authoritative state after R18\n' >>"$MODEL/system-model.txt"
cat "$EXPORT_DIR/runtime-contract.env" "$EXPORT_DIR/state-sanitized.txt" "$EXPORT_DIR/activation.kv" "$EXPORT_DIR/full-refresh-result.kv" >>"$MODEL/system-model.txt"
cp "$EXPORT_DIR/runtime-contract.env" "$MODEL/runtime-contract.txt"
for f in generation-metadata.txt generation-candidates.tsv generation-manifest-file.sha256 critical-files.sha256 vpn-runtime.txt service-status.txt activation.kv full-refresh-result.kv machine-git.txt quarantine-summary.txt; do [[ ! -f "$EXPORT_DIR/$f" ]] || cp "$EXPORT_DIR/$f" "$MODEL/$f"; done
mapfile -t model_files < <(find "$MODEL" -maxdepth 1 -type f -print | LC_ALL=C sort)
publish_object vm101_model_full_pool_refresh_trigger_r18 vm101-model VM101_MODEL_URL "${model_files[@]}" || stop STOP_R18_MODEL_PUBLICATION contract 30
phase_done model_publication

phase_begin methods_publication
METHODS="$STEP_DIR/methods-public"; mkdir -p "$METHODS"
cp "$BUNDLE_DIR/methods/methods-limitations.txt" "$METHODS/methods-limitations.txt"
cp "$BUNDLE_DIR/methods/access-routes.txt" "$METHODS/access-routes.txt"
cp "$MODEL/runtime-contract.txt" "$METHODS/runtime-contract.txt"
mapfile -t method_files < <(find "$METHODS" -maxdepth 1 -type f -print | LC_ALL=C sort)
publish_object vm101_methods_full_pool_refresh_trigger_r18 vm101-methods VM101_METHODS_URL "${method_files[@]}" || stop STOP_R18_METHODS_PUBLICATION contract 31
phase_done methods_publication

phase_begin plan_publication
publish_object local_architecture_plan_vm101_autonomous_hmn_recovery_r18 local-m07-plan LOCAL_M07_PLAN_URL "$BUNDLE_DIR/plans/canonical-plan-r18.md" || stop STOP_R18_PLAN_PUBLICATION contract 32
phase_done plan_publication

phase_begin project_source_publication
publish_object project_source_post_vm101_full_pool_refresh_trigger_r18 project-source-post PROJECT_SOURCE_POST_URL "$BUNDLE_DIR/post/WG_PAID_MGTS_VM101_FULL_POOL_REFRESH_TRIGGER_AND_TRANSACTIONAL_REPLACEMENT_R18.md" || stop STOP_R18_PROJECT_SOURCE_PUBLICATION contract 33
PROJECT_SOURCE_POST_FILE_URL="${PROJECT_SOURCE_POST_URL}WG_PAID_MGTS_VM101_FULL_POOL_REFRESH_TRIGGER_AND_TRANSACTIONAL_REPLACEMENT_R18.md"
phase_done project_source_publication

phase_begin step_report_publication
RESULT=PASS_R18_FULL_POOL_REFRESH_TRIGGER_AND_TRANSACTIONAL_REPLACEMENT
CURRENT_PHASE=step_report_publication
write_docs
HTML="$STEP_DIR/html"; SAFE="$STEP_DIR/safe"
python3 "$HTML_BUILDER" --facts "$FACTS" --verify "$VERIFY" --rollback "$ROLLBACK" --output-dir "$HTML" --title-prefix R18 >"$COMPONENTS/html-aliases.log"
"$SAFE_BUILDER" "$SAFE" \
  "$STEP_FILE" step-code.sh "$REPORT" report.txt "$FACTS" facts.json "$VERIFY" verify.txt "$ROLLBACK" rollback.sh \
  "$MAIN_LOG" main.log "$PROGRESS" progress.log "$TRANSFER" transfer-verify.txt \
  "$PHASE_CURRENT" phase-current.txt "$PHASE_EVENTS" phase-events.log \
  "$COMPONENTS/vm101-preflight.log" vm101-preflight.txt "$COMPONENTS/pve-snapshot.log" pve-snapshot.txt \
  "$COMPONENTS/vm101-apply.log" vm101-apply.txt "$COMPONENTS/vm101-core.log" vm101-core.txt \
  "$COMPONENTS/vm101-postcheck.log" vm101-postcheck.txt "$COMPONENTS/router-machine-close.log" router-machine-close.txt \
  "$COMPONENTS/vm101-git-proof.txt" vm101-git-proof.txt "$STEP_DIR/manifest.log" bundle-manifest-verify.txt \
  "$STEP_DIR/bundle-gate.log" bundle-gate.txt "$HTML/facts-public.html" facts-public.html \
  "$HTML/verify-public.html" verify-public.html "$HTML/rollback-public.html" rollback-public.html >"$COMPONENTS/safe-payload.log"
"$FINALIZER" --label step050m07r18_r02_preflight_full_tree_count_fix_continuation --payload-dir "$SAFE" \
  --workflow-current "$PHASE_CURRENT" --workflow-events "$PHASE_EVENTS" --output-env "$STEP_DIR/finalize.env" --expect-kind step-report >"$COMPONENTS/finalize.log"
STEP_REPORT_URL="$(field "$STEP_DIR/finalize.env" PUBLIC_URL)"
[[ "$STEP_REPORT_URL" == https://reports.secret-studio.ru/latest/*/ ]] || stop STOP_R18_STEP_REPORT_URL missing 34
PUBLICATION_BARRIER=verified
HTTP_VERIFY_PASS=true
FACTS_URL="${STEP_REPORT_URL}facts-public.html"
VERIFY_URL="${STEP_REPORT_URL}verify-public.html"
ROLLBACK_URL="${STEP_REPORT_URL}rollback-public.html"
PREVIOUS_MOVED_COUNT="$(field "$COMPONENTS/finalize.log" PREVIOUS_MOVED_COUNT)"; [[ -n "$PREVIOUS_MOVED_COUNT" ]] || PREVIOUS_MOVED_COUNT=0
phase_done step_report_publication

phase_begin external_http_verification
for url in "$VM101_PUBLIC_URL" "$VM101_MODEL_URL" "$VM101_METHODS_URL" "$LOCAL_M07_PLAN_URL" "$PROJECT_SOURCE_POST_URL" "$STEP_REPORT_URL"; do
  "$HTTP" --url "$url" --output "$STEP_DIR/http-final-$(printf '%s' "$url"|sha256sum|cut -c1-12).html" >>"$COMPONENTS/final-http.log" 2>&1
done
phase_done external_http_verification
router_step_workflow_mark_complete
CURRENT_PHASE=complete
RESULT=PASS_R18_FULL_POOL_REFRESH_TRIGGER_AND_TRANSACTIONAL_REPLACEMENT
PUBLICATION_BARRIER=verified
HTTP_VERIFY_PASS=true
write_docs
print_final
