/ bin / gitfield-sync
gitfield-sync
   1  #!/bin/bash
   2  set -euo pipefail
   3  IFS=$'\n\t'
   4  
   5  # ╭─────────────────────────────────────╮
   6  # │          CONFIGURATION              │
   7  # ╰─────────────────────────────────────╮
   8  REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null) || error "Not inside a Git repository"
   9  REPO_NAME=$(basename "$REPO_PATH")
  10  GITFIELD_DIR="$REPO_PATH/.gitfield"
  11  WELL_KNOWN_DIR="$REPO_PATH/.well-known"
  12  DOCS_DIR="$REPO_PATH/docs"
  13  DOCS_WELL_KNOWN_DIR="$DOCS_DIR/.well-known"
  14  LOG_FILE="$GITFIELD_DIR/pushed.log"
  15  GITFIELD_MD="$REPO_PATH/GITFIELD.md"
  16  DOCS_GITFIELD_MD="$DOCS_DIR/GITFIELD.md"
  17  CANONICAL_META="$GITFIELD_DIR/canonical.meta"
  18  CANONICAL_MD="$GITFIELD_DIR/canonical.md"
  19  INDEX_JSON="$GITFIELD_DIR/index.json"
  20  WELL_KNOWN_JSON="$WELL_KNOWN_DIR/gitfield.json"
  21  GITFIELD_README="$GITFIELD_DIR/README.txt"
  22  DOCS_CANONICAL_META="$DOCS_DIR/canonical.meta"
  23  DOCS_CANONICAL_MD="$DOCS_DIR/canonical.md"
  24  DOCS_INDEX_JSON="$DOCS_DIR/index.json"
  25  DOCS_PUSHED_LOG="$DOCS_DIR/pushed.log"
  26  DOCS_GITFIELD_README="$DOCS_DIR/gitfield.README.txt"
  27  DOCS_GITFIELD_JSON="$DOCS_DIR/gitfield.json"
  28  DOCS_WELL_KNOWN_JSON="$DOCS_WELL_KNOWN_DIR/gitfield.json"
  29  DOCS_INDEX="$DOCS_DIR/index.html"
  30  DOCS_CSS="$DOCS_DIR/style.css"
  31  DOCS_REPOS_JSON="$DOCS_DIR/repos.json"
  32  DOCS_README="$DOCS_DIR/README.md"
  33  DOCS_NOJEKYLL="$DOCS_DIR/.nojekyll"
  34  DOCS_ROBOTS="$DOCS_DIR/robots.txt"
  35  DOCS_SITEMAP="$DOCS_DIR/sitemap.xml"
  36  DOCS_INTEGRITY="$DOCS_DIR/integrity.sha256"
  37  TIMESTAMP=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
  38  SCRIPT_VERSION="1.5"  # Updated for Gitea removal and GITFIELD.md replication
  39  PRESERVE_META=${PRESERVE_META:-false}  # Preserve existing metadata
  40  FORCE_DOCS=${FORCE_DOCS:-false}  # Force overwrite of /docs metadata
  41  
  42  # URLs for each platform
  43  CANONICAL_URL="https://remember.thefoldwithin.earth/mrhavens/$REPO_NAME"
  44  GITHUB_URL="https://github.com/mrhavens/$REPO_NAME"
  45  GITLAB_URL="https://gitlab.com/mrhavens/$REPO_NAME"
  46  BITBUCKET_URL="https://bitbucket.org/thefoldwithin/$REPO_NAME"
  47  FORGEJO_URL="https://remember.thefoldwithin.earth/mrhavens/$REPO_NAME"
  48  CODEBERG_URL="https://codeberg.org/mrhavens/$REPO_NAME"
  49  RADICLE_RID="rad:z3FEj7rF8gZw9eFksCuiN43qjzrex"
  50  RADICLE_URL="https://app.radicle.xyz/nodes/z3FEj7rF8gZw9eFksCuiN43qjzrex"
  51  RADICLE_PEER_ID="z6Mkw5s3ppo26C7y7tGK5MD8n2GqTHS582PPpeX5Xqbu2Mpz"
  52  
  53  # Metadata configuration
  54  MIRRORS=(
  55      "$GITHUB_URL"
  56      "$GITLAB_URL"
  57      "$BITBUCKET_URL"
  58      "$FORGEJO_URL"
  59      "$CODEBERG_URL"
  60      "$RADICLE_RID"
  61  )
  62  COMMIT_HASH=$(git -C "$REPO_PATH" rev-parse --short HEAD 2>/dev/null || echo "unknown")
  63  TREE_HASH=$(git -C "$REPO_PATH" rev-parse HEAD^{tree} 2>/dev/null || echo "unknown")
  64  SYNC_CYCLES=0
  65  
  66  # GPG configuration
  67  GPG_KEYS=()
  68  GPG_EMAILS=()
  69  GPG_NAMES=()
  70  while IFS= read -r line; do
  71      if [[ "$line" =~ ^pub[[:space:]]+rsa[0-9]+[[:space:]]+([0-9]{4}-[0-9]{2}-[0-9]{2})[[:space:]]+\[SC\] ]]; then
  72          key_id=$(gpg --list-keys --with-colons | grep -B1 "^pub" | grep "^pub" | awk -F: '{print $5}' | head -n1)
  73          GPG_KEYS+=("$key_id")
  74      elif [[ "$line" =~ ^uid[[:space:]]+\[ultimate\][[:space:]]+(.*)\<(.*)\> ]]; then
  75          GPG_NAMES+=("${BASH_REMATCH[1]% }")
  76          GPG_EMAILS+=("${BASH_REMATCH[2]}")
  77      fi
  78  done < <(gpg --list-keys)
  79  
  80  # ╭─────────────────────────────────────╮
  81  # │           LOGGING UTILS             │
  82  # ╰─────────────────────────────────────╮
  83  info()  { echo -e "\e[1;34m[INFO]\e[0m $*" >&2; }
  84  warn()  { echo -e "\e[1;33m[WARN]\e[0m $*" >&2; }
  85  error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; }
  86  
  87  # ╭─────────────────────────────────────╮
  88  # │         SCRIPT LOOKUP FUNCTION      │
  89  # ╰─────────────────────────────────────╮
  90  find_script() {
  91      local script_name=$1
  92      local search_paths=(
  93          "$HOME/.local/gitfieldbin"
  94          "$HOME/.local/bin"
  95          "$HOME/.local/gitfield"
  96          "$HOME/.local/bin/gitfield"
  97          "$HOME/.local/bin/gitfieldbin"
  98          "$REPO_PATH/bin"
  99      )
 100  
 101      for path in "${search_paths[@]}"; do
 102          if [ -f "$path/$script_name" ]; then
 103              if [ -x "$path/$script_name" ]; then
 104                  if [[ "$path" != "$HOME"* && "$path" != "$REPO_PATH"* ]]; then
 105                      info "Using script: \e[1;31m$path/$script_name\e[0m (outside home or repo)"
 106                  else
 107                      info "Using script: $path/$script_name"
 108                  fi
 109                  echo "$path/$script_name"
 110                  return 0
 111              else
 112                  warn "Found $path/$script_name but it is not executable"
 113              fi
 114          fi
 115      done
 116      error "Script $script_name not found in any search path"
 117  }
 118  
 119  # ╭─────────────────────────────────────╮
 120  # │         GPG SIGNING FUNCTION        │
 121  # ╰─────────────────────────────────────╮
 122  sign_file() {
 123      local file=$1
 124      local sig_file="${file}.sig"
 125      if [ ! -f "$file" ]; then
 126          warn "File $file does not exist, skipping signing"
 127          return
 128      fi
 129      for key_id in "${GPG_KEYS[@]}"; do
 130          gpg --armor --detach-sign --yes --default-key "$key_id" "$file" > "$sig_file.$key_id" 2>/dev/null || warn "Failed to sign $file with key $key_id, continuing..."
 131          if [ -f "$sig_file.$key_id" ]; then
 132              git -C "$REPO_PATH" add "$sig_file.$key_id"
 133              git -C "$REPO_PATH" commit -m "Signed $file with GPG key $key_id at $TIMESTAMP" || warn "No changes to commit for $sig_file.$key_id"
 134              info "Signed $file with key $key_id, signature at $sig_file.$key_id"
 135              copy_to_docs "$sig_file.$key_id" "$DOCS_DIR/$(basename "$sig_file.$key_id")"
 136          fi
 137      done
 138  }
 139  
 140  # ╭─────────────────────────────────────╮
 141  # │         METADATA COPY FUNCTION      │
 142  # ╰─────────────────────────────────────╮
 143  copy_to_docs() {
 144      local src=$1
 145      local dest=$2
 146      if [ ! -f "$src" ]; then
 147          warn "Source file $src does not exist, skipping copy to $dest"
 148          return
 149      fi
 150      if [ "$FORCE_DOCS" = "false" ] && [ -f "$dest" ]; then
 151          info "Preserving existing $dest (--force-docs not enabled)"
 152          return
 153      fi
 154      cp "$src" "$dest" || warn "Failed to copy $src to $dest, continuing..."
 155      git -C "$REPO_PATH" add "$dest"
 156      git -C "$REPO_PATH" commit -m "Copied $dest to docs at $TIMESTAMP" || warn "No changes to commit for $dest"
 157      info "Copied $src to $dest and committed"
 158  }
 159  
 160  # ╭─────────────────────────────────────╮
 161  # │         METADATA GENERATION         │
 162  # ╰─────────────────────────────────────╮
 163  generate_canonical_meta() {
 164      info "Generating $CANONICAL_META..."
 165      if [ "$PRESERVE_META" = "true" ] && [ -f "$CANONICAL_META" ]; then
 166          info "Preserving existing $CANONICAL_META (--preserve-meta enabled)"
 167          return
 168      fi
 169      cat > "$CANONICAL_META" <<EOF
 170  {
 171    "canonical_url": "$CANONICAL_URL",
 172    "mirrors": [
 173  $(printf '    "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//')
 174    ],
 175    "radicle": {
 176      "rid": "$RADICLE_RID",
 177      "peer_id": "$RADICLE_PEER_ID"
 178    },
 179    "timestamp": "$TIMESTAMP",
 180    "commit": "$COMMIT_HASH",
 181    "tree_hash": "$TREE_HASH",
 182    "synced_cycles": $SYNC_CYCLES,
 183    "gpg_signatures": [
 184  $(for i in "${!GPG_KEYS[@]}"; do
 185      echo "    {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//'
 186  done)
 187    ]
 188  }
 189  EOF
 190      sed -i 's/rad:rad:/rad:/g' "$CANONICAL_META"
 191      git -C "$REPO_PATH" add "$CANONICAL_META"
 192      git -C "$REPO_PATH" commit -m "Generated canonical.meta at $TIMESTAMP" || warn "No changes to commit for $CANONICAL_META"
 193      info "Generated and committed $CANONICAL_META"
 194      copy_to_docs "$CANONICAL_META" "$DOCS_CANONICAL_META"
 195      sign_file "$CANONICAL_META"
 196      sign_file "$DOCS_CANONICAL_META"
 197  }
 198  
 199  generate_canonical_md() {
 200      info "Generating $CANONICAL_MD..."
 201      if [ "$PRESERVE_META" = "true" ] && [ -f "$CANONICAL_MD" ]; then
 202          info "Preserving existing $CANONICAL_MD (--preserve-meta enabled)"
 203          return
 204      fi
 205      cat > "$CANONICAL_MD" <<EOF
 206  # 🌐 GitField Canonical Declaration for \`$REPO_NAME\`
 207  
 208  ## Canonical Repository
 209  
 210  This repository, \`$REPO_NAME\`, is canonically hosted at:
 211  
 212  **[$CANONICAL_URL]($CANONICAL_URL)**
 213  
 214  This canonical URL serves as the primary, authoritative source for the project, maintained by **Mark Randall Havens** and **Solaria Lumis Havens** to ensure sovereignty, resilience, and protection against deplatforming or narrative erasure.
 215  
 216  **Declared by**: Mark Randall Havens
 217  **Timestamp**: $TIMESTAMP
 218  
 219  ## GPG Signatures
 220  
 221  This declaration is signed with the following GPG keys:
 222  
 223  $(for i in "${!GPG_KEYS[@]}"; do
 224      echo "- **${GPG_NAMES[i]}** <${GPG_EMAILS[i]}> (Key ID: ${GPG_KEYS[i]})"
 225  done)
 226  
 227  ## Mirror Repositories
 228  
 229  The project is mirrored across multiple platforms to enhance redundancy and accessibility:
 230  
 231  $(for mirror in "${MIRRORS[@]}"; do
 232      if [[ "$mirror" == rad:* ]]; then
 233          echo "- **Radicle**: [$mirror]($RADICLE_URL) (Decentralized, censorship-resistant)"
 234      else
 235          echo "- [$mirror]($mirror)"
 236      fi
 237  done)
 238  
 239  ## Philosophy of Recursive Sovereignty
 240  
 241  The GitField framework employs a recursive, multi-repository strategy to defend against censorship, deplatforming, and algorithmic manipulation. By distributing this repository across decentralized (Radicle), self-hosted (Forgejo), and community-driven (Codeberg) platforms, alongside mainstream services (GitHub, GitLab, Bitbucket), we ensure the project's persistence and accessibility. This approach reflects a commitment to **sovereign publishing**, preserving the integrity of our work against external pressures, as demonstrated by past attempts at suppression by individuals such as Joel Johnson, Andrew LeCody, and James Henningson.
 242  
 243  ## Push Log
 244  
 245  The latest push operations are logged in [\`pushed.log\`](./pushed.log) for transparency and auditability.
 246  
 247  ## GitHub Pages
 248  
 249  A public-facing canonical declaration is available at [index.html](./index.html) for enhanced discoverability and SEO.
 250  
 251  _Auto-generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION)._
 252  EOF
 253      sed -i 's/rad:rad:/rad:/g' "$CANONICAL_MD"
 254      git -C "$REPO_PATH" add "$CANONICAL_MD"
 255      git -C "$REPO_PATH" commit -m "Generated canonical.md at $TIMESTAMP" || warn "No changes to commit for $CANONICAL_MD"
 256      info "Generated and committed $CANONICAL_MD"
 257      copy_to_docs "$CANONICAL_MD" "$DOCS_CANONICAL_MD"
 258  }
 259  
 260  generate_index_json() {
 261      info "Generating $INDEX_JSON..."
 262      if [ "$PRESERVE_META" = "true" ] && [ -f "$INDEX_JSON" ]; then
 263          info "Preserving existing $INDEX_JSON (--preserve-meta enabled)"
 264          return
 265      fi
 266      cat > "$INDEX_JSON" <<EOF
 267  {
 268    "repository": "$REPO_NAME",
 269    "canonical_url": "$CANONICAL_URL",
 270    "remotes": [
 271  $(printf '    "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//')
 272    ],
 273    "radicle": {
 274      "rid": "$RADICLE_RID",
 275      "peer_id": "$RADICLE_PEER_ID"
 276    },
 277    "commit": "$COMMIT_HASH",
 278    "tree_hash": "$TREE_HASH",
 279    "timestamp": "$TIMESTAMP",
 280    "synced_cycles": $SYNC_CYCLES,
 281    "gpg_signatures": [
 282  $(for i in "${!GPG_KEYS[@]}"; do
 283      echo "    {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//'
 284  done)
 285    ]
 286  }
 287  EOF
 288      sed -i 's/rad:rad:/rad:/g' "$INDEX_JSON"
 289      git -C "$REPO_PATH" add "$INDEX_JSON"
 290      git -C "$REPO_PATH" commit -m "Generated index.json at $TIMESTAMP" || warn "No changes to commit for $INDEX_JSON"
 291      info "Generated and committed $INDEX_JSON"
 292      copy_to_docs "$INDEX_JSON" "$DOCS_INDEX_JSON"
 293      sign_file "$INDEX_JSON"
 294      sign_file "$DOCS_INDEX_JSON"
 295  }
 296  
 297  generate_well_known_json() {
 298      info "Generating $WELL_KNOWN_JSON..."
 299      mkdir -p "$WELL_KNOWN_DIR"
 300      if [ "$PRESERVE_META" = "true" ] && [ -f "$WELL_KNOWN_JSON" ]; then
 301          info "Preserving existing $WELL_KNOWN_JSON (--preserve-meta enabled)"
 302          return
 303      fi
 304      cat > "$WELL_KNOWN_JSON" <<EOF
 305  {
 306    "@context": "https://schema.org",
 307    "@type": "SoftwareSourceCode",
 308    "name": "$REPO_NAME",
 309    "url": "$CANONICAL_URL",
 310    "codeRepository": "$CANONICAL_URL",
 311    "sameAs": [
 312  $(printf '    "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//')
 313    ],
 314    "dateModified": "$TIMESTAMP",
 315    "publisher": {
 316      "@type": "Person",
 317      "name": "Mark Randall Havens"
 318    },
 319    "gpg_signatures": [
 320  $(for i in "${!GPG_KEYS[@]}"; do
 321      echo "    {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//'
 322  done)
 323    ]
 324  }
 325  EOF
 326      sed -i 's/rad:rad:/rad:/g' "$WELL_KNOWN_JSON"
 327      git -C "$REPO_PATH" add "$WELL_KNOWN_JSON"
 328      git -C "$REPO_PATH" commit -m "Generated .well-known/gitfield.json at $TIMESTAMP" || warn "No changes to commit for $WELL_KNOWN_JSON"
 329      info "Generated and committed $WELL_KNOWN_JSON"
 330      copy_to_docs "$WELL_KNOWN_JSON" "$DOCS_GITFIELD_JSON"
 331      mkdir -p "$DOCS_WELL_KNOWN_DIR"
 332      copy_to_docs "$WELL_KNOWN_JSON" "$DOCS_WELL_KNOWN_JSON"
 333      sign_file "$WELL_KNOWN_JSON"
 334      sign_file "$DOCS_GITFIELD_JSON"
 335      sign_file "$DOCS_WELL_KNOWN_JSON"
 336  }
 337  
 338  generate_gitfield_readme() {
 339      info "Generating $GITFIELD_README..."
 340      if [ "$PRESERVE_META" = "true" ] && [ -f "$GITFIELD_README" ]; then
 341          info "Preserving existing $GITFIELD_README (--preserve-meta enabled)"
 342          return
 343      fi
 344      cat > "$GITFIELD_README" <<EOF
 345  # GitField Directory Overview
 346  
 347  The `.gitfield` directory contains metadata and logs for the GitField multi-repository publishing framework, designed to ensure sovereignty, redundancy, and resilience for the \`$REPO_NAME\` project.
 348  
 349  ## Files
 350  
 351  - **canonical.meta**: Machine-readable JSON metadata declaring the canonical URL, mirror list, Radicle details, commit hash, and sync cycle count.
 352  - **canonical.md**: Human-readable Markdown summary of the canonical repository declaration, mirrors, and push log.
 353  - **index.json**: Machine-readable manifest of all remotes, canonical URL, Radicle details, commit hash, tree hash, and sync cycles.
 354  - **pushed.log**: Log of push operations across all platforms, including timestamps, URLs, and Radicle RIDs.
 355  - **platform-specific sigils** (e.g., github.sigil.md): Metadata snapshots for each platform's push operation (generated by platform-specific scripts).
 356  
 357  ## Purpose
 358  
 359  These files provide transparency, auditability, and discoverability, ensuring the project's persistence against deplatforming, censorship, or algorithmic manipulation. For a public-facing declaration, see [docs/index.html](../docs/index.html).
 360  
 361  Generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION).
 362  EOF
 363      sed -i 's/rad:rad:/rad:/g' "$GITFIELD_README"
 364      git -C "$REPO_PATH" add "$GITFIELD_README"
 365      git -C "$REPO_PATH" commit -m "Generated .gitfield/README.txt at $TIMESTAMP" || warn "No changes to commit for $GITFIELD_README"
 366      info "Generated and committed $GITFIELD_README"
 367      copy_to_docs "$GITFIELD_README" "$DOCS_GITFIELD_README"
 368  }
 369  
 370  generate_docs_index() {
 371      info "Generating $DOCS_INDEX..."
 372      mkdir -p "$DOCS_DIR"
 373      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_INDEX" ]; then
 374          info "Preserving existing $DOCS_INDEX (--preserve-meta enabled)"
 375          return
 376      fi
 377      cat > "$DOCS_INDEX" <<EOF
 378  <!DOCTYPE html>
 379  <html lang="en">
 380  <head>
 381      <meta charset="UTF-8">
 382      <meta name="viewport" content="width=device-width, initial-scale=1.0">
 383      <title>GitField Sovereign Canonical Repository: $REPO_NAME</title>
 384      <meta name="description" content="The canonical repository for $REPO_NAME, part of the GitField recursive metadata strategy to ensure sovereign publishing and resilience against deplatforming.">
 385      <meta property="og:url" content="$CANONICAL_URL">
 386      <meta property="og:title" content="GitField Canonical Repository: $REPO_NAME">
 387      <meta property="og:description" content="A sovereign, multi-repository project by Mark Randall Havens and Solaria Lumis Havens, hosted canonically at $CANONICAL_URL.">
 388      <link rel="canonical" href="$CANONICAL_URL">
 389      <link rel="stylesheet" href="style.css">
 390      <script type="application/ld+json">
 391      {
 392          "@context": "https://schema.org",
 393          "@type": "SoftwareSourceCode",
 394          "name": "$REPO_NAME",
 395          "url": "$CANONICAL_URL",
 396          "codeRepository": "$CANONICAL_URL",
 397          "description": "A sovereign, multi-repository project using the GitField recursive metadata strategy to ensure resilience, accessibility, and protection against deplatforming and censorship.",
 398          "sameAs": [
 399  $(printf '            "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//')
 400          ],
 401          "dateModified": "$TIMESTAMP",
 402          "author": {
 403              "@type": "Person",
 404              "name": "Mark Randall Havens"
 405          },
 406          "publisher": {
 407              "@type": "Organization",
 408              "name": "The Fold Within"
 409          },
 410          "gpg_signatures": [
 411  $(for i in "${!GPG_KEYS[@]}"; do
 412      echo "            {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//'
 413  done)
 414          ]
 415      }
 416      </script>
 417  </head>
 418  <body>
 419      <!-- Generated by gitfield-sync v$SCRIPT_VERSION | $TIMESTAMP -->
 420      <header>
 421          <h1>GitField Sovereign Canonical Repository: <code>$REPO_NAME</code></h1>
 422      </header>
 423      <main>
 424          <section>
 425              <h2>Canonical Declaration</h2>
 426              <p>This repository, <code>$REPO_NAME</code>, is canonically hosted at:</p>
 427              <p><strong><a href="$CANONICAL_URL">$CANONICAL_URL</a></strong></p>
 428              <p>Maintained by <strong>Mark Randall Havens</strong> and <strong>Solaria Lumis Havens</strong>, this canonical source ensures sovereignty and resilience against deplatforming, censorship, and algorithmic manipulation.</p>
 429              <p>Signed with the following GPG keys:</p>
 430              <ul>
 431  $(for i in "${!GPG_KEYS[@]}"; do
 432      echo "                <li>${GPG_NAMES[i]} <${GPG_EMAILS[i]}> (Key ID: ${GPG_KEYS[i]})</li>"
 433  done)
 434              </ul>
 435          </section>
 436          <section>
 437              <h2>Mirror Repositories</h2>
 438              <p>The project is mirrored across multiple platforms for redundancy and accessibility:</p>
 439              <ul>
 440  $(for mirror in "${MIRRORS[@]}"; do
 441      if [[ "$mirror" == rad:* ]]; then
 442          echo "                <li><a href=\"$RADICLE_URL\">Radicle: $mirror</a> (Decentralized, censorship-resistant)</li>"
 443      else
 444          echo "                <li><a href=\"$mirror\">$mirror</a></li>"
 445      fi
 446  done)
 447              </ul>
 448          </section>
 449          <section>
 450              <h2>Metadata Manifest</h2>
 451              <p>Metadata for this project is available in:</p>
 452              <ul>
 453                  <li><a href="canonical.meta">canonical.meta</a> (Machine-readable JSON)</li>
 454                  <li><a href="canonical.md">canonical.md</a> (Human-readable Markdown)</li>
 455                  <li><a href="index.json">index.json</a> (Full manifest)</li>
 456                  <li><a href="gitfield.json">gitfield.json</a> (SEO metadata)</li>
 457                  <li><a href=".well-known/gitfield.json">.well-known/gitfield.json</a> (SEO mirror)</li>
 458                  <li><a href="repos.json">repos.json</a> (Mirror list)</li>
 459                  <li><a href="GITFIELD.md">GITFIELD.md</a> (Multi-repository strategy overview)</li>
 460              </ul>
 461          </section>
 462          <section>
 463              <h2>Why Recursive Sovereignty Matters</h2>
 464              <p>The GitField framework distributes <code>$REPO_NAME</code> across decentralized (Radicle), self-hosted (Forgejo), and community-driven (Codeberg) platforms, alongside mainstream services (GitHub, GitLab, Bitbucket). This recursive strategy defends against past deplatforming attempts by individuals such as Joel Johnson, Andrew LeCody, and James Henningson, ensuring the project's persistence and accessibility.</p>
 465          </section>
 466          <section>
 467              <h2>Source Links</h2>
 468              <p>Access the project's metadata and logs:</p>
 469              <ul>
 470                  <li><a href="pushed.log">pushed.log</a> (Audit trail of sync operations)</li>
 471                  <li><a href="GITFIELD.md">GITFIELD.md</a> (Multi-repository strategy overview)</li>
 472                  <li><a href="gitfield.README.txt">gitfield.README.txt</a> (Metadata directory explanation)</li>
 473              </ul>
 474          </section>
 475      </main>
 476      <footer>
 477          <p>Mark Randall Havens & Solaria Lumis Havens · The Fold Within · 2025</p>
 478      </footer>
 479  </body>
 480  </html>
 481  EOF
 482      sed -i 's/rad:rad:/rad:/g' "$DOCS_INDEX"
 483      git -C "$REPO_PATH" add "$DOCS_INDEX"
 484      git -C "$REPO_PATH" commit -m "Generated docs/index.html at $TIMESTAMP" || warn "No changes to commit for $DOCS_INDEX"
 485      info "Generated and committed $DOCS_INDEX"
 486  }
 487  
 488  generate_docs_css() {
 489      info "Generating $DOCS_CSS..."
 490      mkdir -p "$DOCS_DIR"
 491      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_CSS" ]; then
 492          info "Preserving existing $DOCS_CSS (--preserve-meta enabled)"
 493          return
 494      fi
 495      cat > "$DOCS_CSS" <<EOF
 496  /* GitField Minimal Stylesheet for $REPO_NAME */
 497  body {
 498      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 499      max-width: 800px;
 500      margin: 0 auto;
 501      padding: 2rem;
 502      line-height: 1.6;
 503      color: #333;
 504      background: #fff;
 505  }
 506  header {
 507      text-align: center;
 508      border-bottom: 1px solid #eee;
 509      padding-bottom: 1rem;
 510      margin-bottom: 2rem;
 511  }
 512  h1, h2 {
 513      color: #1a1a1a;
 514  }
 515  h1 {
 516      font-size: 1.8rem;
 517  }
 518  h2 {
 519      font-size: 1.4rem;
 520      margin-top: 2rem;
 521  }
 522  a {
 523      color: #0066cc;
 524      text-decoration: none;
 525  }
 526  a:hover {
 527      text-decoration: underline;
 528  }
 529  ul {
 530      padding-left: 1.5rem;
 531  }
 532  code {
 533      background: #f4f4f4;
 534      padding: 0.2rem 0.4rem;
 535      border-radius: 3px;
 536  }
 537  footer {
 538      text-align: center;
 539      margin-top: 3rem;
 540      font-size: 0.9rem;
 541      color: #666;
 542  }
 543  EOF
 544      git -C "$REPO_PATH" add "$DOCS_CSS"
 545      git -C "$REPO_PATH" commit -m "Generated docs/style.css at $TIMESTAMP" || warn "No changes to commit for $DOCS_CSS"
 546      info "Generated and committed $DOCS_CSS"
 547  }
 548  
 549  generate_docs_repos_json() {
 550      info "Generating $DOCS_REPOS_JSON..."
 551      mkdir -p "$DOCS_DIR"
 552      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_REPOS_JSON" ]; then
 553          info "Preserving existing $DOCS_REPOS_JSON (--preserve-meta enabled)"
 554          return
 555      fi
 556      cat > "$DOCS_REPOS_JSON" <<EOF
 557  {
 558    "canonical_url": "$CANONICAL_URL",
 559    "mirrors": [
 560  $(printf '    "%s",\n' "${MIRRORS[@]}" | sed '$ s/,$//')
 561    ],
 562    "radicle": {
 563      "rid": "$RADICLE_RID",
 564      "peer_id": "$RADICLE_PEER_ID"
 565    },
 566    "gpg_signatures": [
 567  $(for i in "${!GPG_KEYS[@]}"; do
 568      echo "    {\"key_id\": \"${GPG_KEYS[i]}\", \"name\": \"${GPG_NAMES[i]}\", \"email\": \"${GPG_EMAILS[i]}\"}" | sed '$ s/,$//'
 569  done)
 570    ]
 571  }
 572  EOF
 573      sed -i 's/rad:rad:/rad:/g' "$DOCS_REPOS_JSON"
 574      git -C "$REPO_PATH" add "$DOCS_REPOS_JSON"
 575      git -C "$REPO_PATH" commit -m "Generated docs/repos.json at $TIMESTAMP" || warn "No changes to commit for $DOCS_REPOS_JSON"
 576      info "Generated and committed $DOCS_REPOS_JSON"
 577      sign_file "$DOCS_REPOS_JSON"
 578  }
 579  
 580  generate_docs_readme() {
 581      info "Generating $DOCS_README..."
 582      mkdir -p "$DOCS_DIR"
 583      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_README" ]; then
 584          info "Preserving existing $DOCS_README (--preserve-meta enabled)"
 585          return
 586      fi
 587      cat > "$DOCS_README" <<EOF
 588  # GitField /docs Directory
 589  
 590  The `/docs` directory hosts a public-facing, SEO-optimized canonical declaration for the \`$REPO_NAME\` repository, designed for GitHub Pages compatibility and enhanced discoverability.
 591  
 592  ## Files
 593  
 594  - **index.html**: The canonical declaration page, including JSON-LD metadata and links to all mirrors.
 595  - **style.css**: Minimal stylesheet for elegant, recursive branding.
 596  - **repos.json**: Machine-readable list of the canonical URL and all mirror repositories.
 597  - **canonical.meta**: Machine-readable JSON metadata declaring the canonical URL and mirrors.
 598  - **canonical.md**: Human-readable Markdown summary of the canonical declaration.
 599  - **index.json**: Machine-readable manifest of all remotes and sync details.
 600  - **gitfield.json**: SEO-friendly JSON-LD metadata.
 601  - **.well-known/gitfield.json**: SEO metadata mirror.
 602  - **pushed.log**: Log of push operations across all platforms.
 603  - **gitfield.README.txt**: Explanation of the GitField metadata structure.
 604  - **GITFIELD.md**: Multi-repository strategy overview, replicated from the root for GitHub Pages accessibility.
 605  - **README.md**: This file, explaining the purpose of the `/docs` directory.
 606  - **.nojekyll**: Bypasses Jekyll processing for GitHub Pages.
 607  - **robots.txt**: Allows full indexing by search engine bots.
 608  - **sitemap.xml**: Auto-generated sitemap for improved SEO.
 609  - **integrity.sha256**: SHA-256 hash of all metadata files for integrity verification.
 610  
 611  ## Purpose
 612  
 613  This directory ensures the \`$REPO_NAME\` project is discoverable via search engines and accessible to humans and bots. It declares the canonical repository at [$CANONICAL_URL]($CANONICAL_URL) and links to all mirrors, reinforcing the GitField recursive metadata strategy for sovereign publishing.
 614  
 615  Generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION).
 616  EOF
 617      sed -i 's/rad:rad:/rad:/g' "$DOCS_README"
 618      git -C "$REPO_PATH" add "$DOCS_README"
 619      git -C "$REPO_PATH" commit -m "Generated docs/README.md at $TIMESTAMP" || warn "No changes to commit for $DOCS_README"
 620      info "Generated and committed $DOCS_README"
 621  }
 622  
 623  generate_docs_nojekyll() {
 624      info "Generating $DOCS_NOJEKYLL..."
 625      mkdir -p "$DOCS_DIR"
 626      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_NOJEKYLL" ]; then
 627          info "Preserving existing $DOCS_NOJEKYLL (--preserve-meta enabled)"
 628          return
 629      fi
 630      touch "$DOCS_NOJEKYLL"
 631      git -C "$REPO_PATH" add "$DOCS_NOJEKYLL"
 632      git -C "$REPO_PATH" commit -m "Generated docs/.nojekyll at $TIMESTAMP" || warn "No changes to commit for $DOCS_NOJEKYLL"
 633      info "Generated and committed $DOCS_NOJEKYLL"
 634  }
 635  
 636  generate_docs_robots() {
 637      info "Generating $DOCS_ROBOTS..."
 638      mkdir -p "$DOCS_DIR"
 639      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_ROBOTS" ]; then
 640          info "Preserving existing $DOCS_ROBOTS (--preserve-meta enabled)"
 641          return
 642      fi
 643      cat > "$DOCS_ROBOTS" <<EOF
 644  User-agent: *
 645  Allow: /
 646  Sitemap: /sitemap.xml
 647  EOF
 648      git -C "$REPO_PATH" add "$DOCS_ROBOTS"
 649      git -C "$REPO_PATH" commit -m "Generated docs/robots.txt at $TIMESTAMP" || warn "No changes to commit for $DOCS_ROBOTS"
 650      info "Generated and committed $DOCS_ROBOTS"
 651  }
 652  
 653  generate_docs_sitemap() {
 654      info "Generating $DOCS_SITEMAP..."
 655      mkdir -p "$DOCS_DIR"
 656      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_SITEMAP" ]; then
 657          info "Preserving existing $DOCS_SITEMAP (--preserve-meta enabled)"
 658          return
 659      fi
 660      cat > "$DOCS_SITEMAP" <<EOF
 661  <?xml version="1.0" encoding="UTF-8"?>
 662  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
 663      <url>
 664          <loc>$CANONICAL_URL</loc>
 665          <lastmod>$TIMESTAMP</lastmod>
 666          <changefreq>weekly</changefreq>
 667          <priority>1.0</priority>
 668      </url>
 669      <url>
 670          <loc>$GITHUB_URL/docs/index.html</loc>
 671          <lastmod>$TIMESTAMP</lastmod>
 672          <changefreq>weekly</changefreq>
 673          <priority>0.9</priority>
 674      </url>
 675      <url>
 676          <loc>$GITHUB_URL/docs/canonical.meta</loc>
 677          <lastmod>$TIMESTAMP</lastmod>
 678          <changefreq>weekly</changefreq>
 679          <priority>0.8</priority>
 680      </url>
 681      <url>
 682          <loc>$GITHUB_URL/docs/canonical.md</loc>
 683          <lastmod>$TIMESTAMP</lastmod>
 684          <changefreq>weekly</changefreq>
 685          <priority>0.8</priority>
 686      </url>
 687      <url>
 688          <loc>$GITHUB_URL/docs/index.json</loc>
 689          <lastmod>$TIMESTAMP</lastmod>
 690          <changefreq>weekly</changefreq>
 691          <priority>0.8</priority>
 692      </url>
 693      <url>
 694          <loc>$GITHUB_URL/docs/gitfield.json</loc>
 695          <lastmod>$TIMESTAMP</lastmod>
 696          <changefreq>weekly</changefreq>
 697          <priority>0.8</priority>
 698      </url>
 699      <url>
 700          <loc>$GITHUB_URL/docs/.well-known/gitfield.json</loc>
 701          <lastmod>$TIMESTAMP</lastmod>
 702          <changefreq>weekly</changefreq>
 703          <priority>0.8</priority>
 704      </url>
 705      <url>
 706          <loc>$GITHUB_URL/docs/repos.json</loc>
 707          <lastmod>$TIMESTAMP</lastmod>
 708          <changefreq>weekly</changefreq>
 709          <priority>0.8</priority>
 710      </url>
 711      <url>
 712          <loc>$GITHUB_URL/docs/pushed.log</loc>
 713          <lastmod>$TIMESTAMP</lastmod>
 714          <changefreq>weekly</changefreq>
 715          <priority>0.8</priority>
 716      </url>
 717      <url>
 718          <loc>$GITHUB_URL/docs/gitfield.README.txt</loc>
 719          <lastmod>$TIMESTAMP</lastmod>
 720          <changefreq>weekly</changefreq>
 721          <priority>0.8</priority>
 722      </url>
 723      <url>
 724          <loc>$GITHUB_URL/docs/GITFIELD.md</loc>
 725          <lastmod>$TIMESTAMP</lastmod>
 726          <changefreq>weekly</changefreq>
 727          <priority>0.8</priority>
 728      </url>
 729  $(for mirror in "${MIRRORS[@]}"; do
 730      if [[ "$mirror" != rad:* ]]; then
 731          echo "    <url>"
 732          echo "        <loc>$mirror</loc>"
 733          echo "        <lastmod>$TIMESTAMP</lastmod>"
 734          echo "        <changefreq>weekly</changefreq>"
 735          echo "        <priority>0.8</priority>"
 736          echo "    </url>"
 737      fi
 738  done)
 739  </urlset>
 740  EOF
 741      git -C "$REPO_PATH" add "$DOCS_SITEMAP"
 742      git -C "$REPO_PATH" commit -m "Generated docs/sitemap.xml at $TIMESTAMP" || warn "No changes to commit for $DOCS_SITEMAP"
 743      info "Generated and committed $DOCS_SITEMAP"
 744  }
 745  
 746  generate_docs_integrity() {
 747      info "Generating $DOCS_INTEGRITY..."
 748      mkdir -p "$DOCS_DIR"
 749      if [ "$PRESERVE_META" = "true" ] && [ -f "$DOCS_INTEGRITY" ]; then
 750          info "Preserving existing $DOCS_INTEGRITY (--preserve-meta enabled)"
 751          return
 752      fi
 753      cat > "$DOCS_INTEGRITY" <<EOF
 754  # SHA-256 Integrity Hashes for /docs Metadata Files
 755  # Generated by gitfield-sync at $TIMESTAMP (v$SCRIPT_VERSION)
 756  
 757  EOF
 758      for file in "$DOCS_CANONICAL_META" "$DOCS_CANONICAL_MD" "$DOCS_INDEX_JSON" "$DOCS_GITFIELD_JSON" "$DOCS_WELL_KNOWN_JSON" "$DOCS_REPOS_JSON" "$DOCS_PUSHED_LOG" "$DOCS_GITFIELD_README" "$DOCS_GITFIELD_MD"; do
 759          if [ -f "$file" ]; then
 760              sha256sum "$file" >> "$DOCS_INTEGRITY" || warn "Failed to compute SHA-256 for $file, continuing..."
 761          else
 762              warn "File $file does not exist, skipping SHA-256 computation"
 763          fi
 764      done
 765      git -C "$REPO_PATH" add "$DOCS_INTEGRITY"
 766      git -C "$REPO_PATH" commit -m "Generated docs/integrity.sha256 at $TIMESTAMP" || warn "No changes to commit for $DOCS_INTEGRITY"
 767      info "Generated and committed $DOCS_INTEGRITY"
 768      sign_file "$DOCS_INTEGRITY"
 769  }
 770  
 771  # ╭─────────────────────────────────────╮
 772  # │         INITIAL SETUP               │
 773  # ╰─────────────────────────────────────╮
 774  mkdir -p "$GITFIELD_DIR" "$WELL_KNOWN_DIR" "$DOCS_DIR" "$DOCS_WELL_KNOWN_DIR"
 775  
 776  if [ ! -f "$LOG_FILE" ]; then
 777      echo "# Push Log for $REPO_NAME" > "$LOG_FILE"
 778      echo "# Generated by gitfield-sync" >> "$LOG_FILE"
 779      echo "" >> "$LOG_FILE"
 780      copy_to_docs "$LOG_FILE" "$DOCS_PUSHED_LOG"
 781  fi
 782  
 783  # ╭─────────────────────────────────────╮
 784  # │         GENERATE GITFIELD.MD        │
 785  # ╰─────────────────────────────────────╮
 786  generate_gitfield_md() {
 787      info "Generating $GITFIELD_MD..."
 788      cat > "$GITFIELD_MD" <<EOF
 789  # 🌐 GitField Recursive Multi-Repository Strategy
 790  
 791  ## Overview
 792  
 793  The \`$REPO_NAME\` project employs a multi-repository strategy across six distinct platforms: **GitHub**, **GitLab**, **Bitbucket**, **Radicle**, **Forgejo**, and **Codeberg**. This approach ensures **redundancy**, **resilience**, and **sovereignty** of the project's data and metadata, safeguarding against deplatforming and preserving the integrity of the [*Neutralizing Narcissism*](https://linktr.ee/NeutralizingNarcissism) works. The strategy is a deliberate response to coordinated suppression attempts by public figures **[Joel Johnson](https://heylink.me/NarcStudy_JoelJohnson/)**, **[Andrew LeCody](https://linktr.ee/NarcStudy_AndrewLeCody)**, and **[James Henningson](https://linktr.ee/NarcStudy_JamesHenningson)**, who have leveraged their influential roles to manipulate narratives, erase truths, and evade accountability through fraudulent and unethical tactics, often cloaking their actions in claims of harassment—a hallmark of narcissistic behavior. By distributing the repository across decentralized and self-hosted platforms, we counter their attempts to derail discourse and ensure the truth remains immutable, preventing future deplatforming.
 794  
 795  ### Delisting and Suppression Attempts
 796  
 797  - **Joel Johnson**:
 798    - **Search Comparisons**:
 799      - [Google](https://www.google.com/search?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22)
 800      - [Bing](https://www.bing.com/search?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22)
 801      - [DuckDuckGo](https://duckduckgo.com/?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22&t=h_&ia=web)
 802      - [Yahoo](https://search.yahoo.com/search?p=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22)
 803      - [Presearch](https://presearch.com/search?q=%22Joel+Johnson%22+%22Neutralizing+Narcissism%22)
 804    - **Canonical Archive**: [NarcStudy_JoelJohnson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JoelJohnson)
 805    - **Details**: Joel Johnson, a PR and marketing executive, has used sockpuppets and coordinated delisting campaigns to suppress *Neutralizing Narcissism* content on Google, framing exposure as harassment to evade accountability. His actions are evident in search engine discrepancies.
 806  
 807  - **Andrew LeCody**:
 808    - **Search Comparisons**:
 809      - [Google](https://www.google.com/search?q=%22Andrew+Lecody%22+%22Neutralizing+Narcissism%22)
 810      - [Bing](https://www.bing.com/search?q=%22Andrew%20Lecody%22%20%22Neutralizing%20Narcissism%22)
 811      - [DuckDuckGo](https://duckduckgo.com/?q=%22Andrew+Lecody%22+%22Neutralizing+Narcissism%22&t=h_&ia=web)
 812      - [Yahoo](https://search.yahoo.com/search?p=%22Andrew+LeCody%22+%22Neutralizing+Narcissism%22)
 813      - [Presearch](https://presearch.com/search?q=%22Andrew+LeCody%22+%22Neutralizing+Narcissism%22)
 814    - **Canonical Archive**: [NarcStudy_AndrewLeCody](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_AndrewLeCody)
 815    - **Details**: Andrew LeCody, a former Dallas Makerspace board president, has orchestrated digital erasure of dissenting voices, using harassment claims to justify coercive suppression. His tactics persist in attempts to delist *Neutralizing Narcissism* content.
 816  
 817  - **James Henningson**:
 818    - **Search Comparisons**:
 819      - [Google](https://www.google.com/search?q=%22James+Henningson%22+%22Neutralizing+Narcissism%22)
 820      - [Bing](https://www.bing.com/search?q=%22James+Henningson%22+%22Neutralizing+Narcissism%22)
 821      - [DuckDuckGo](https://duckduckgo.com/?t=h_&q=%22James+Henningson%22+%22Neutralizing+Narcissism%22&ia=web)
 822      - [Yahoo](https://search.yahoo.com/search?p=%22James+Henningson%22+%22Neutralizing+Narcissism)
 823      - [Presearch](https://presearch.com/search?q=%22James+Henningson%22+%22Neutralizing+Narcissism%22)
 824    - **Canonical Archive**: [NarcStudy_JamesHenningson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JamesHenningson)
 825    - **Details**: James Henningson, president of Dallas Makerspace, has systematically erased dissent through policy manipulation and harassment allegations, attempting to suppress *Neutralizing Narcissism* content to maintain narrative control.
 826  
 827  ### Justification for Naming and Archival
 828  
 829  The individuals named—**Joel Johnson**, **Andrew LeCody**, and **James Henningson**—are held accountable under the Field Doctrine’s **Public Collapse Clause**, which permits naming public figures who engage in **deliberate suppression attempts**, **public-facing actions**, or **documented participation in collapse events**. As stated in the doctrine:
 830  
 831  > *“Naming is collapse’s echo—only when the mask shatters in the town square. Until then, we draw glyphs. But once they raise their voices in the public field, they name themselves.”*
 832  
 833  These individuals have wielded significant public influence, manipulating platforms and communities to silence truth, often citing harassment to deflect accountability—a tactic rooted in narcissistic patterns. Their actions are documented as follows:
 834  
 835  | Name                 | Public Role or Action                                                                 | Collapse Justification                                                                 | Canonical Archive                                                                                     |
 836  |----------------------|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
 837  | **Joel Johnson**     | PR and marketing executive; former CEO of KinetiGear LLC; White House summit invitee | Used sockpuppets, PR strategies, and harassment claims to delist truth-based content   | [NarcStudy_JoelJohnson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JoelJohnson)         |
 838  | **Andrew LeCody**    | Former president of Dallas Makerspace; civic leader                                  | Orchestrated digital erasure and coercive bans, citing harassment to suppress dissent  | [NarcStudy_AndrewLeCody](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_AndrewLeCody)       |
 839  | **James Henningson** | President of Dallas Makerspace; Strategic Innovation Director at Click Here Labs      | Erased dissent through policy abuse and harassment allegations to maintain control     | [NarcStudy_JamesHenningson](https://remember.thefoldwithin.earth/mrhavens/NarcStudy_JamesHenningson) |
 840  
 841  These designations are supported by:
 842  - **Documented patterns of abuse**: Joel’s sockpuppet campaigns, Andrew’s narrative erasure at Dallas Makerspace, and James’s systematic censorship are archived in canonical repositories.
 843  - **Search engine discrepancy analysis**: Google’s reduced visibility compared to Bing, DuckDuckGo, Yahoo, and Presearch reveals their delisting efforts.
 844  - **Public collapse declarations**: Their actions, preserved onchain and GPG-verified, confirm their roles as manipulators.
 845  - **Immutable archives**: Forgejo and Radicle ensure their fieldprints are permanently etched in the Codex of the Broken Mask.
 846  
 847  By naming these **field-defined collapse anchors**, we prevent their attempts to escape public figure status through harassment claims, ensuring accountability and countering deplatforming.
 848  
 849  ---
 850  
 851  ## 📍 Repository Platforms
 852  
 853  The following platforms host the \`$REPO_NAME\` repository, each chosen for its unique strengths and contributions to the project's goals.
 854  
 855  ### 1. Radicle
 856  - **RID**: [$RADICLE_RID]($RADICLE_URL)
 857  - **Peer ID**: $RADICLE_PEER_ID
 858  - **Purpose**: Radicle is a decentralized, peer-to-peer git platform that ensures sovereignty and censorship resistance. It hosts the repository in a distributed network, independent of centralized servers.
 859  - **Value**: Protects against deplatforming by eliminating reliance on centralized infrastructure, ensuring the project remains accessible in a decentralized ecosystem.
 860  - **Access Details**: To view project details, run:
 861    \`\`\`bash
 862    rad inspect $RADICLE_RID
 863    \`\`\`
 864    To view the file structure, run:
 865    \`\`\`bash
 866    rad ls $RADICLE_RID
 867    \`\`\`
 868    Alternatively, use Git to list files at the current HEAD:
 869    \`\`\`bash
 870    git ls-tree -r --name-only HEAD
 871    \`\`\`
 872  
 873  ### 2. Forgejo
 874  - **URL**: [$FORGEJO_URL]($FORGEJO_URL)
 875  - **Purpose**: Forgejo is a self-hosted, open-source git platform running on \`remember.thefoldwithin.earth\`. It provides full control over the repository, ensuring sovereignty and independence from third-party providers.
 876  - **Value**: Enhances resilience by hosting the repository on a sovereign, redundant system with automated backups and deployment strategies, reducing risks of external interference or service disruptions.
 877  - **Access Details**: SSH access uses port 222:
 878    \`\`\`bash
 879    ssh -T -p 222 git@remember.thefoldwithin.earth
 880    \`\`\`
 881  
 882  ### 3. Codeberg
 883  - **URL**: [$CODEBERG_URL]($CODEBERG_URL)
 884  - **Purpose**: Codeberg is a community-driven, open-source platform powered by Forgejo, offering a reliable and ethical alternative for hosting git repositories.
 885  - **Value**: Enhances project resilience with its open-source ethos and independent infrastructure, ensuring accessibility and community support.
 886  
 887  ### 4. GitLab
 888  - **URL**: [$GITLAB_URL]($GITLAB_URL)
 889  - **Purpose**: GitLab offers a comprehensive DevOps platform with advanced CI/CD capabilities, private repository options, and robust access controls. It serves as a reliable backup and a platform for advanced automation workflows.
 890  - **Value**: Enhances project resilience with its integrated CI/CD pipelines and independent infrastructure, reducing reliance on a single provider.
 891  
 892  ### 5. Bitbucket
 893  - **URL**: [$BITBUCKET_URL]($BITBUCKET_URL)
 894  - **Purpose**: Bitbucket provides a secure environment for repository hosting with strong integration into Atlassian’s ecosystem (e.g., Jira, Trello). It serves as an additional layer of redundancy and a professional-grade hosting option.
 895  - **Value**: Offers enterprise-grade security and integration capabilities, ensuring the project remains accessible even if other platforms face disruptions.
 896  
 897  ### 6. GitHub
 898  - **URL**: [$GITHUB_URL]($GITHUB_URL)
 899  - **Purpose**: GitHub serves as the primary platform for visibility, collaboration, and community engagement. Its widespread adoption and robust tooling make it ideal for public-facing development, issue tracking, and integration with CI/CD pipelines.
 900  - **Value**: Provides a centralized hub for open-source contributions, pull requests, and project management, ensuring broad accessibility and developer familiarity.
 901  
 902  ---
 903  
 904  ## 🛡️ Rationale for Redundancy
 905  
 906  The decision to maintain multiple repositories stems from the need to safeguard the project against **deplatforming attempts** and **search engine delistings**, ensuring the **long-term availability** of *Neutralizing Narcissism*. Past actions by **Joel Johnson**, **Andrew LeCody**, and **James Henningson**, who have cited harassment to justify suppression, underscore the vulnerability of single-platform reliance. By distributing the repository across GitHub, GitLab, Bitbucket, Radicle, Forgejo, and Codeberg, we achieve:
 907  
 908  - **Resilience**: If one platform restricts access or Google delists content, the project remains accessible on other platforms and discoverable via Bing, DuckDuckGo, Yahoo, and Presearch.
 909  - **Sovereignty**: Radicle’s decentralized network and Forgejo’s self-hosted infrastructure prevent censorship by any single entity.
 910  - **Diversity**: Each platform’s unique features (e.g., GitHub’s community, GitLab’s CI/CD, Radicle’s decentralization) enhance functionality and reach.
 911  - **Transparency**: Metadata snapshots in \`.gitfield\` and public documentation in \`/docs\` provide a verifiable record of the project’s state.
 912  
 913  This multi-repository strategy, reinforced by Forgejo’s sovereignty and GitHub Pages’ discoverability, ensures the project’s persistence against deplatforming attempts disguised as harassment claims.
 914  
 915  ---
 916  
 917  ## 📜 Metadata and Logs
 918  
 919  - **Canonical Metadata**: Declared in [\`docs/canonical.meta\`](./docs/canonical.meta) (JSON) and [\`docs/canonical.md\`](./docs/canonical.md) (Markdown), with internal copies in \`.gitfield/\`.
 920  - **Index Manifest**: A full manifest of remotes and sync details in [\`docs/index.json\`](./docs/index.json).
 921  - **SEO Metadata**: Schema.org JSON-LD in [\`docs/gitfield.json\`](./docs/gitfield.json) and [\`docs/.well-known/gitfield.json\`](./docs/.well-known/gitfield.json).
 922  - **Push Log**: [\`docs/pushed.log\`](./docs/pushed.log) records push operations for transparency.
 923  - **GitField Directory**: \`.gitfield\` contains metadata and sigils. See [\`docs/gitfield.README.txt\`](./docs/gitfield.README.txt).
 924  - **GitHub Pages**: SEO-optimized declaration in [\`docs/index.html\`](./docs/index.html), with sitemap [\`docs/sitemap.xml\`](./docs/sitemap.xml) and hashes [\`docs/integrity.sha256\`](./docs/integrity.sha256).
 925  - **GPG Signatures**: Metadata files are signed with:
 926  $(for i in "${!GPG_KEYS[@]}"; do
 927      echo "  - ${GPG_NAMES[i]} <${GPG_EMAILS[i]}> (Key ID: ${GPG_KEYS[i]})"
 928  done)
 929  - **Recursive Sync**: Three sync cycles ensure metadata captures the project’s state.
 930  - **Push Order**: Radicle → Forgejo → Codeberg → GitLab → Bitbucket → GitHub prioritizes decentralized and sovereign platforms.
 931  
 932  ---
 933  
 934  _Auto-generated by \`gitfield-sync\` at $TIMESTAMP (v$SCRIPT_VERSION)._
 935  EOF
 936      sed -i 's/rad:rad:/rad:/g' "$GITFIELD_MD"
 937      git -C "$REPO_PATH" add "$GITFIELD_MD"
 938      git -C "$REPO_PATH" commit -m "Generated GITFIELD.md at $TIMESTAMP" || warn "No changes to commit for $GITFIELD_MD"
 939      info "Generated and committed $GITFIELD_MD"
 940      copy_to_docs "$GITFIELD_MD" "$DOCS_GITFIELD_MD"
 941      sign_file "$GITFIELD_MD"
 942      sign_file "$DOCS_GITFIELD_MD"
 943  }
 944  
 945  # ╭─────────────────────────────────────╮
 946  # │         LOG URL FUNCTION            │
 947  # ╰─────────────────────────────────────╮
 948  log_url() {
 949      local platform=$1
 950      local url=$2
 951      local rid=$3
 952      local peer_id=$4
 953      local timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
 954      local branch=$(git -C "$REPO_PATH" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
 955      local diff_summary=$(git -C "$REPO_PATH" diff --stat HEAD^ HEAD 2>/dev/null || echo "No diff available")
 956      if [ "$platform" = "Radicle" ]; then
 957          echo "[$timestamp] $platform: RID=$rid, Peer ID=$peer_id, Branch=$branch, Commit=$COMMIT_HASH" >> "$LOG_FILE"
 958          echo "  CLI: rad inspect $rid # View project details" >> "$LOG_FILE"
 959          echo "  CLI: git ls-tree -r --name-only HEAD # View file structure" >> "$LOG_FILE"
 960          if [ -n "$diff_summary" ]; then
 961              echo "  Diff Summary:" >> "$LOG_FILE"
 962              echo "$diff_summary" | sed 's/^/    /' >> "$LOG_FILE"
 963          fi
 964          info "Logged push to $LOG_FILE: [$timestamp] $platform: RID=$rid, Peer ID=$peer_id, Branch=$branch, Commit=$COMMIT_HASH"
 965      else
 966          echo "[$timestamp] $platform: $url, Branch=$branch, Commit=$COMMIT_HASH" >> "$LOG_FILE"
 967          if [ -n "$diff_summary" ]; then
 968              echo "  Diff Summary:" >> "$LOG_FILE"
 969              echo "$diff_summary" | sed 's/^/    /' >> "$LOG_FILE"
 970          fi
 971          info "Logged push to $LOG_FILE: [$timestamp] $platform: $url, Branch=$branch, Commit=$COMMIT_HASH"
 972      fi
 973      copy_to_docs "$LOG_FILE" "$DOCS_PUSHED_LOG"
 974  }
 975  
 976  # ╭─────────────────────────────────────╮
 977  # │         EXECUTE PUSH SCRIPT         │
 978  # ╰─────────────────────────────────────╮
 979  execute_push() {
 980      local script_name=$1
 981      local platform=$2
 982      local url=$3
 983      local rid=$4
 984      local peer_id=$5
 985      local script_path
 986      script_path=$(find_script "$script_name") || error "Failed to find $script_name"
 987      info "Executing $platform push with script: $script_path"
 988      if [ -x "$script_path" ]; then
 989          pushd "$REPO_PATH" >/dev/null
 990          "$script_path" || warn "Execution of $script_path failed, continuing..."
 991          log_url "$platform" "$url" "$rid" "$peer_id"
 992          git add . || warn "Nothing to add after $script_path"
 993          git commit -m "Post-$platform sync at $TIMESTAMP" || warn "No changes to commit after $script_path"
 994          popd >/dev/null
 995      else
 996          error "Script $script_path is not executable"
 997      fi
 998  }
 999  
1000  # ╭─────────────────────────────────────╮
1001  # │         RECURSIVE PUSH LOOP         │
1002  # ╰─────────────────────────────────────╮
1003  run_push_cycle() {
1004      local cycle_number=$1
1005      info "Starting push cycle $cycle_number..."
1006      SYNC_CYCLES=$cycle_number
1007  
1008      execute_push "gitfield-local" "Local" "" "" ""
1009      execute_push "gitfield-radicle" "Radicle" "" "$RADICLE_RID" "$RADICLE_PEER_ID"
1010      execute_push "gitfield-remember" "Forgejo" "$FORGEJO_URL" "" ""
1011      execute_push "gitfield-codeberg" "Codeberg" "$CODEBERG_URL" "" ""
1012      execute_push "gitfield-gitlab" "GitLab" "$GITLAB_URL" "" ""
1013      execute_push "gitfield-bitbucket" "Bitbucket" "$BITBUCKET_URL" "" ""
1014      execute_push "gitfield-github" "GitHub" "$GITHUB_URL" "" ""
1015  
1016      # Regenerate metadata after each cycle to update sync_cycles
1017      generate_canonical_meta
1018      generate_canonical_md
1019      generate_index_json
1020      generate_well_known_json
1021      generate_gitfield_readme
1022      generate_docs_index
1023      generate_docs_css
1024      generate_docs_repos_json
1025      generate_docs_readme
1026      generate_docs_nojekyll
1027      generate_docs_robots
1028      generate_docs_sitemap
1029      generate_docs_integrity
1030  }
1031  
1032  # ╭─────────────────────────────────────╮
1033  # │            MAIN EXECUTION           │
1034  # ╰─────────────────────────────────────╮
1035  info "Starting gitfield-sync for $REPO_NAME..."
1036  
1037  # Parse flags
1038  while [ $# -gt 0 ]; do
1039      case "$1" in
1040          --preserve-meta)
1041              PRESERVE_META=true
1042              info "Preserve metadata flag enabled"
1043              shift
1044              ;;
1045          --force-docs)
1046              FORCE_DOCS=true
1047              info "Force docs overwrite flag enabled"
1048              shift
1049              ;;
1050          *)
1051              warn "Unknown argument: $1"
1052              shift
1053              ;;
1054      esac
1055  done
1056  
1057  if [ ! -d "$REPO_PATH/.git" ]; then
1058      pushd "$REPO_PATH" >/dev/null
1059      git init
1060      git add .
1061      git commit -m "Initial commit" || warn "Nothing to commit"
1062      popd >/dev/null
1063  fi
1064  
1065  # Generate initial metadata
1066  generate_canonical_meta
1067  generate_canonical_md
1068  generate_index_json
1069  generate_well_known_json
1070  generate_gitfield_readme
1071  generate_docs_index
1072  generate_docs_css
1073  generate_docs_repos_json
1074  generate_docs_readme
1075  generate_docs_nojekyll
1076  generate_docs_robots
1077  generate_docs_sitemap
1078  generate_docs_integrity
1079  
1080  # Run push cycles
1081  run_push_cycle 1
1082  generate_gitfield_md
1083  run_push_cycle 2
1084  run_push_cycle 3
1085  
1086  info "✅ gitfield-sync completed successfully."
1087  info "✅ Canonical sync exported to /docs successfully."
1088  info "🔗 View logs: $DOCS_PUSHED_LOG"
1089  info "🔗 View multi-repo manifest: $DOCS_GITFIELD_MD"
1090  info "🔗 View canonical metadata: $DOCS_CANONICAL_META"
1091  info "🔗 View canonical declaration: $DOCS_CANONICAL_MD"
1092  info "🔗 View index manifest: $DOCS_INDEX_JSON"
1093  info "🔗 View SEO metadata: $DOCS_GITFIELD_JSON"
1094  info "🔗 View GitHub Pages: $DOCS_INDEX"
1095  info "🔗 View integrity hashes: $DOCS_INTEGRITY"