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