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

STEP_ID=STEP_050M07R18_R07_PACKAGE_SHA_AND_ROLLBACK_GUARD_FIX_CONTINUATION
RESULT=STOP_R18_R07_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
R02_FAILURE_CLASSIFIED=false
R03_FAILURE_CLASSIFIED=false
R03_FILES_AND_STATE_ROLLED_BACK=false
R04_FAILURE_CLASSIFIED=false
R04_FILES_AND_STATE_ROLLED_BACK=false
R05_FAILURE_CLASSIFIED=false
R06_SALVAGE_VERIFIED=false
R01_STEP_DIR=''
R02_STEP_DIR=''
R03_STEP_DIR=''
R04_STEP_DIR=''
R05_STEP_DIR=''
R06_STEP_DIR=''
R01_STOP_REPORT_URL='https://reports.secret-studio.ru/latest/20260718-075534_step050m07r18_full_pool_refresh_trigger_and_transactional_replacement_stop/'
R02_STOP_REPORT_URL='https://reports.secret-studio.ru/latest/20260718-082051_step050m07r18_r02_preflight_full_tree_count_fix_continuation_stop/'
R03_STOP_REPORT_URL='PENDING_NOT_PUBLISHED'
R04_STOP_REPORT_URL='https://reports.secret-studio.ru/latest/20260718-104740_step050m07r18_r04_orchestrator_contract_and_busybox_fix_continuation_stop/'
R05_STOP_REPORT_URL='https://reports.secret-studio.ru/latest/20260718-173106_step050m07r18_r05_provider_results_schema_adapter_continuation_stop/'
R06_PASS_REPORT_URL='https://reports.secret-studio.ru/latest/20260718-175715_step050m07r18_r06_control_plane_state_salvage_continuation/'

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"
STOP_GUARD_DIR="$STEP_DIR/.stop-handler-active"
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
R02_FAILURE_CLASSIFIED=$R02_FAILURE_CLASSIFIED
R02_CORE_CHANGE_COMPLETE=false
R02_TARGET_PREFLIGHT_STATUS=complete
R02_TARGET_CORE_STATUS=failed
R02_STOP_REPORT_URL=$R02_STOP_REPORT_URL
R02_SNAPSHOT_REUSED=true
R03_FAILURE_CLASSIFIED=$R03_FAILURE_CLASSIFIED
R03_CORE_CHANGE_COMPLETE=false
R03_TARGET_PREFLIGHT_STATUS=complete
R03_TARGET_CORE_STATUS=failed
R03_FILES_AND_STATE_ROLLED_BACK=$R03_FILES_AND_STATE_ROLLED_BACK
R03_STOP_REPORT_URL=$R03_STOP_REPORT_URL
R03_LOCAL_STEP_DIR=${R03_STEP_DIR:-none}
R04_FAILURE_CLASSIFIED=$R04_FAILURE_CLASSIFIED
R04_CORE_CHANGE_COMPLETE=false
R04_TARGET_PREFLIGHT_STATUS=complete
R04_TARGET_CORE_STATUS=failed
R04_FILES_AND_STATE_ROLLED_BACK=$R04_FILES_AND_STATE_ROLLED_BACK
R04_STOP_REPORT_URL=$R04_STOP_REPORT_URL
R04_LOCAL_STEP_DIR=${R04_STEP_DIR:-none}
R05_FAILURE_CLASSIFIED=$R05_FAILURE_CLASSIFIED
R05_CORE_CHANGE_COMPLETE=false
R05_TARGET_CORE_STATUS=failed
R05_TARGET_PACKAGE_SHA_GUARD_TRIGGERED=true
R05_STOP_REPORT_URL=$R05_STOP_REPORT_URL
R05_LOCAL_STEP_DIR=${R05_STEP_DIR:-none}
R06_SALVAGE_VERIFIED=$R06_SALVAGE_VERIFIED
R06_CONTROL_PLANE_STATE_RESTORED=true
R06_ACTIVE_GENERATION_ID=r15b2-20260716-215914
R06_REPAIR_COUNTER=0
R06_HEALTH_REPAIR_RUNNING=true
R06_PASS_REPORT_URL=$R06_PASS_REPORT_URL
R06_LOCAL_STEP_DIR=${R06_STEP_DIR:-none}
PACKAGE_SHA_CONSISTENCY_VERIFIED=true
EARLY_ROLLBACK_REQUIRES_BACKUP_READY=true
R04_PROVIDER_DOWNLOAD_COMPLETE=true
R04_PROVIDER_TEST_OK_COUNT=20
R04_FAILURE_SIGNATURE=insufficient_ranked_candidates_0
PUBLICATION_PREFLIGHT_REPEATED=false
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_TREE_SOURCE=live_machine_git_after_router_machine_close_and_exact_clone
VM101_POST_EXPECTED_COUNT=35
SNAPSHOT_NAME=${SNAPSHOT_NAME:-none}
TARGET_PACKAGE_SHA256=2fbbcc06cb85b5c8edfd2a9d15e6b4886424f1335c29df8893e325a5cec65997
TARGET_PACKAGE_SHA_RELEASE_INFO_MATCH=true
TARGET_PACKAGE_SHA_OUTER_INSTALLER_MATCH=true
TARGET_PACKAGE_SHA_REMOTE_APPLY_MATCH=true
TARGET_PACKAGE_SHA_ARCHIVE_MATCH=true
EARLY_ROLLBACK_BACKUP_READY_GUARD=true
R06_CONTROL_PLANE_SALVAGE_REQUIRED_AND_VERIFIED=true
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","r02_failure_classified":"$R02_FAILURE_CLASSIFIED"=="true","r02_core_change_complete":False,"r02_target_preflight_status":"complete","r02_target_core_status":"failed","r02_stop_report_url":"$R02_STOP_REPORT_URL","r02_snapshot_reused":True,"r03_failure_classified":"$R03_FAILURE_CLASSIFIED"=="true","r03_core_change_complete":False,"r03_target_preflight_status":"complete","r03_target_core_status":"failed","r03_files_and_state_rolled_back":"$R03_FILES_AND_STATE_ROLLED_BACK"=="true","r03_stop_report_url":"$R03_STOP_REPORT_URL","r03_local_step_dir":"$R03_STEP_DIR","r04_failure_classified":"$R04_FAILURE_CLASSIFIED"=="true","r04_core_change_complete":False,"r04_target_preflight_status":"complete","r04_target_core_status":"failed","r04_files_and_state_rolled_back":"$R04_FILES_AND_STATE_ROLLED_BACK"=="true","r04_stop_report_url":"$R04_STOP_REPORT_URL","r04_local_step_dir":"$R04_STEP_DIR","r04_provider_download_complete":True,"r04_provider_test_ok_count":20,"r04_failure_signature":"insufficient_ranked_candidates:0","r05_failure_classified":"$R05_FAILURE_CLASSIFIED"=="true","r05_core_change_complete":False,"r05_target_core_status":"failed","r05_target_package_sha_guard_triggered":True,"r05_stop_report_url":"$R05_STOP_REPORT_URL","r06_salvage_verified":"$R06_SALVAGE_VERIFIED"=="true","r06_control_plane_state_restored":True,"r06_active_generation_id":"r15b2-20260716-215914","r06_repair_counter":0,"r06_health_repair_running":True,"r06_pass_report_url":"$R06_PASS_REPORT_URL","package_sha_consistency_verified":True,"early_rollback_requires_backup_ready":True,"publication_preflight_repeated":False,"core_change_complete":"$CORE_CHANGE_COMPLETE"=="true",
 "core_change_repeated":False,"target_installer_rerun":"$TARGET_INSTALLER_RERUN"=="true","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_r07_package_sha_and_rollback_guard_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
  if ! mkdir "$STOP_GUARD_DIR" 2>/dev/null; then
    exit "$rc"
  fi
  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
R06_STEP_DIR="$(find "$BASE/steps" -mindepth 1 -maxdepth 1 -type d -name '*_STEP_050M07R18_R06_CONTROL_PLANE_STATE_SALVAGE_CONTINUATION' -print | LC_ALL=C sort | tail -n 1)"
[[ -n "$R06_STEP_DIR" && -f "$R06_STEP_DIR/report.txt" && -f "$R06_STEP_DIR/phase-current.env" && -f "$R06_STEP_DIR/components/vm101-salvage-postcheck.log" ]] || stop STOP_R18_R07_R06_EVIDENCE_MISSING "$R06_STEP_DIR" 21
grep -Fqx 'RESULT=PASS_R18_R06_CONTROL_PLANE_STATE_SALVAGED' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_RESULT mismatch 21
grep -Fqx 'STATE_CONTROL_PLANE_RESTORED=true' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_CONTROL_PLANE mismatch 21
grep -Fqx 'ACTIVE_GENERATION_ID=r15b2-20260716-215914' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_ACTIVE_GENERATION mismatch 21
grep -Fqx 'REPAIR_COUNTER=0' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_COUNTER mismatch 21
grep -Fqx 'HEALTH_REPAIR_RUNNING=true' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_SERVICE mismatch 21
grep -Fqx 'HTTP_VERIFY_PASS=true' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_HTTP_VERIFY mismatch 21
grep -Fqx 'VM101_MANAGED_FILES_CHANGED=false' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_MANAGED_FILES mismatch 21
grep -Fqx 'PROVIDER_REFRESH_REPEATED=false' "$R06_STEP_DIR/report.txt" || stop STOP_R18_R07_R06_PROVIDER_REPEAT mismatch 21
grep -Fqx 'target_core=complete' "$R06_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R06_CORE_STATUS mismatch 21
grep -Fqx 'target_postcheck=complete' "$R06_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R06_POSTCHECK_STATUS mismatch 21
grep -Fqx 'external_http_verification=complete' "$R06_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R06_FINAL_STATUS mismatch 21
grep -Fqx 'RESULT=PASS_R18_R06_CONTROL_PLANE_POSTCHECK' "$R06_STEP_DIR/components/vm101-salvage-postcheck.log" || stop STOP_R18_R07_R06_POSTCHECK_EVIDENCE missing 21
R06_SALVAGE_VERIFIED=true

R05_STEP_DIR="$(find "$BASE/steps" -mindepth 1 -maxdepth 1 -type d -name '*_STEP_050M07R18_R05_PROVIDER_RESULTS_SCHEMA_ADAPTER_CONTINUATION' -print | LC_ALL=C sort | tail -n 1)"
[[ -n "$R05_STEP_DIR" && -f "$R05_STEP_DIR/report.txt" && -f "$R05_STEP_DIR/phase-current.env" && -f "$R05_STEP_DIR/components/vm101-apply.log" ]] || stop STOP_R18_R07_R05_EVIDENCE_MISSING "$R05_STEP_DIR" 21
grep -Fqx 'CORE_CHANGE_COMPLETE=false' "$R05_STEP_DIR/report.txt" || stop STOP_R18_R07_R05_CORE_CLASSIFICATION mismatch 21
grep -Fqx 'target_core=failed' "$R05_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R05_CORE_STATUS mismatch 21
grep -Fqx 'RESULT=STOP_R18_TARGET_PACKAGE_SHA' "$R05_STEP_DIR/components/vm101-apply.log" || stop STOP_R18_R07_R05_FAILURE_SIGNATURE missing 21
if [[ -s "$R05_STEP_DIR/components/vm101-core.log" ]]; then stop STOP_R18_R07_R05_PROVIDER_REFRESH_UNEXPECTED started 21; fi
R05_FAILURE_CLASSIFIED=true
R04_STEP_DIR="$(find "$BASE/steps" -mindepth 1 -maxdepth 1 -type d -name '*_STEP_050M07R18_R04_ORCHESTRATOR_CONTRACT_AND_BUSYBOX_FIX_CONTINUATION' -print | LC_ALL=C sort | tail -n 1)"
[[ -n "$R04_STEP_DIR" && -f "$R04_STEP_DIR/phase-current.env" && -f "$R04_STEP_DIR/components/vm101-core.log" ]] || stop STOP_R18_R07_R04_EVIDENCE_MISSING "$R04_STEP_DIR" 21
grep -Fqx 'target_preflight=complete' "$R04_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R04_PREFLIGHT_STATUS mismatch 21
grep -Fqx 'target_core=failed' "$R04_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R04_CORE_STATUS mismatch 21
grep -Fqx 'RESULT=PASS_R18_VM101_PAYLOAD_INSTALLED' "$R04_STEP_DIR/components/vm101-apply.log" || stop STOP_R18_R07_R04_APPLY_EVIDENCE missing 21
grep -Fqx 'RESULT=PASS_R18_PRE_CORE_FILE_AND_STATE_ROLLBACK' "$R04_STEP_DIR/components/target-rollback.log" || stop STOP_R18_R07_R04_ROLLBACK_EVIDENCE missing 21
grep -Fq 'ERROR=insufficient_ranked_candidates:0' "$R04_STEP_DIR/components/vm101-core.log" || stop STOP_R18_R07_R04_FAILURE_SIGNATURE rank_zero_missing 21
grep -Fq 'Summary:' "$R04_STEP_DIR/components/vm101-core.log" || stop STOP_R18_R07_R04_PROVIDER_TEST_EVIDENCE summary_missing 21
grep -Fq 'total=35 OK=20 FAIL=15' "$R04_STEP_DIR/components/vm101-core.log" || stop STOP_R18_R07_R04_PROVIDER_TEST_EVIDENCE counts_missing 21
if grep -Fq '>>> [R18] generation build and validation' "$R04_STEP_DIR/components/vm101-core.log"; then stop STOP_R18_R07_R04_GENERATION_BUILD_UNEXPECTED started 21; fi
R04_FILES_AND_STATE_ROLLED_BACK=true

R02_STEP_DIR="$(find "$BASE/steps" -mindepth 1 -maxdepth 1 -type d -name '*_STEP_050M07R18_R02_PREFLIGHT_FULL_TREE_COUNT_FIX_CONTINUATION' -print | LC_ALL=C sort | tail -n 1)"
[[ -n "$R02_STEP_DIR" && -f "$R02_STEP_DIR/report.txt" && -f "$R02_STEP_DIR/phase-current.env" ]] || stop STOP_R18_R07_R02_EVIDENCE_MISSING "$R02_STEP_DIR" 21
grep -Fqx 'CORE_CHANGE_COMPLETE=false' "$R02_STEP_DIR/report.txt" || stop STOP_R18_R07_R02_CORE_CLASSIFICATION mismatch 21
grep -Fqx 'target_preflight=complete' "$R02_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R02_PREFLIGHT_STATUS mismatch 21
grep -Fqx 'target_core=failed' "$R02_STEP_DIR/phase-current.env" || stop STOP_R18_R07_R02_CORE_STATUS mismatch 21
SNAPSHOT_NAME="$(field "$R02_STEP_DIR/report.txt" SNAPSHOT_NAME)"
[[ "$SNAPSHOT_NAME" == R18_PRE_* && ${#SNAPSHOT_NAME} -le 32 && ${#SNAPSHOT_NAME} -le 40 ]] || stop STOP_R18_R07_R02_SNAPSHOT_EVIDENCE "$SNAPSHOT_NAME" 21
ssh -o BatchMode=yes pve-mgts "qm listsnapshot 101" >"$COMPONENTS/pve-snapshot-reuse.log"
grep -F "$SNAPSHOT_NAME" "$COMPONENTS/pve-snapshot-reuse.log" >/dev/null || stop STOP_R18_R07_SNAPSHOT_MISSING "$SNAPSHOT_NAME" 21

R01_FAILURE_CLASSIFIED=true
R02_FAILURE_CLASSIFIED=true
R03_FAILURE_CLASSIFIED=true
R03_FILES_AND_STATE_ROLLED_BACK=true
R04_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
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
phase_done target_preflight r06_salvage_pass_r05_package_sha_failure_r04_schema_failure_snapshot_and_live_r16_baseline_verified

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"
if ! vm101_run_command 'sha256sum /tmp/vm101-r18-target-package.tar.gz' >"$COMPONENTS/remote-package-sha256.txt"; then
  stop STOP_R18_REMOTE_PACKAGE_SHA_COMMAND ssh_failed 24
fi
remote_pkg_sha="$(awk 'NR==1{print $1}' "$COMPONENTS/remote-package-sha256.txt")"
[[ "$remote_pkg_sha" == 2fbbcc06cb85b5c8edfd2a9d15e6b4886424f1335c29df8893e325a5cec65997 ]] || stop STOP_R18_REMOTE_PACKAGE_SHA "$remote_pkg_sha" 24
TARGET_INSTALLER_RERUN=true
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
vm101_run_script "$BUNDLE_DIR/scripts/vm101-machine-git-facts.sh" >"$COMPONENTS/vm101-machine-git-facts.log"
grep -qx RESULT=PASS_R18_MACHINE_GIT_FACTS "$COMPONENTS/vm101-machine-git-facts.log" || stop STOP_R18_MACHINE_GIT_FACTS marker 27
VM101_COMMIT="$(field "$COMPONENTS/vm101-machine-git-facts.log" COMMIT)"
VM101_TREE="$(field "$COMPONENTS/vm101-machine-git-facts.log" TREE)"
VM101_COUNT="$(field "$COMPONENTS/vm101-machine-git-facts.log" MANAGED_FILE_COUNT)"
[[ "$VM101_COMMIT" =~ ^[0-9a-f]{40}$ && "$VM101_TREE" =~ ^[0-9a-f]{40}$ && "$VM101_COUNT" == 35 ]] || stop STOP_R18_MACHINE_GIT_FACTS_INVALID "commit=$VM101_COMMIT tree=$VM101_TREE count=$VM101_COUNT" 27
[[ "$VM101_COMMIT" != d01016420799492ea6e0ce1a526abafe910f18ed && "$VM101_TREE" != 1972e4bc69dfbfdfb14d210a44a3fdc772ee88de ]] || stop STOP_R18_MACHINE_GIT_NOT_ADVANCED "commit=$VM101_COMMIT tree=$VM101_TREE" 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"
CLONE_COMMIT="$(git -C "$CLONE" rev-parse HEAD)"
CLONE_TREE="$(git -C "$CLONE" rev-parse 'HEAD^{tree}')"
CLONE_COUNT="$(git -C "$CLONE" ls-tree -r --name-only HEAD | wc -l | tr -d ' ')"
[[ "$CLONE_COMMIT" == "$VM101_COMMIT" && "$CLONE_TREE" == "$VM101_TREE" && "$CLONE_COUNT" == "$VM101_COUNT" ]] || stop STOP_R18_EXACT_CLONE_MISMATCH "live=$VM101_COMMIT/$VM101_TREE/$VM101_COUNT clone=$CLONE_COMMIT/$CLONE_TREE/$CLONE_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-reuse.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-machine-git-facts.log" vm101-machine-git-facts.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_r07_package_sha_and_rollback_guard_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
