File size: 4,937 Bytes
931572e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
 * ARCHIVE SWEEP β€” archive-sweep.mjs
 * Archives all SNAPKITTYWEST repos that are not in the KEEP list.
 * Adds FROZEN badge to README. Updates description.
 * Run: node scripts/archive-sweep.mjs --dry-run (preview)
 * Run: node scripts/archive-sweep.mjs --execute (do it)
 *
 * Author: Ahmad Ali Parr + Claude Sonnet 4.6
 */

import { execSync } from 'child_process';

const DRY_RUN = !process.argv.includes('--execute');

// ── KEEP LIST β€” these stay public and active ──────────────────────────────────
const KEEP = new Set([
  // Production (private β€” not touched by this script)
  // Public active
  'mathlib5',              // TIER 2 β€” only PR-accepting repo
  'SNAPKITTYWEST',         // umbrella
  'SNAPKITTYWEST.github.io', // GitHub Pages β€” router UI lives here
  'snapkitty-chain',       // STELLA + P2P + WORM
  'agentic-arena',         // graveyard crawler
  'cartographer-agent',    // CARTO law engine + MyLaw
  'bob-orchestrator',      // BOB + METATRON + autonomous
  'snap-os',               // sovereign OS
  'kittybrowse',           // desktop shell candidate
  'snapkitty-mcp',         // published npm package
  'seit-institute',        // SEIT NGO public face
  'sovereign-attestation-protocol', // SAP v1.0 standard
  'SNAPKITTY-PROOFS',      // proof corpus
  'snapkitty-resonance-isa', // novel ISA
  'metamine',              // visual programming language
  'bel-esprit-accord',     // trust structure public doc
  'snapkittywest.github.io', // GitHub Pages
  '.github',               // org profile
  // Hackathon (keep visible)
  'bob-hackathon-demo',
  'agentscope-sift',
]);

// ── FROZEN BADGE to prepend to README ────────────────────────────────────────
const FROZEN_BADGE = `> ⚠️ **ARCHIVED β€” TIER 1 (FROZEN)**
> This repository is read-only. No pull requests. No issues.
> Licensed under [Sovereign Source License v3.0](https://github.com/SNAPKITTYWEST/SNAPKITTYWEST/blob/main/SOVEREIGN_SOURCE_LICENSE_V3.md)
> Β© Bel Esprit D'Accord Trust (EIN 41-6630640) Β· SnapKitty Collective LLC (EIN 41-5105572)

---

`;

function ghSync(path) {
  try {
    return JSON.parse(execSync(`gh api "${path}"`, { encoding: 'utf8' }));
  } catch { return null; }
}

function ghPatch(path, body) {
  try {
    const json = JSON.stringify(body);
    return JSON.parse(
      execSync(`gh api "${path}" -X PATCH -f archived=${body.archived} -f description="${body.description}"`,
      { encoding: 'utf8' })
    );
  } catch { return null; }
}

function listRepos() {
  const repos = [];
  let page = 1;
  while (true) {
    const batch = ghSync(`users/SNAPKITTYWEST/repos?per_page=100&page=${page}`);
    if (!batch || batch.length === 0) break;
    repos.push(...batch);
    if (batch.length < 100) break;
    page++;
  }
  return repos;
}

function main() {
  console.log(`\n${'='.repeat(60)}`);
  console.log(`ARCHIVE SWEEP β€” ${DRY_RUN ? 'DRY RUN (preview only)' : 'EXECUTING'}`);
  console.log(`${'='.repeat(60)}\n`);

  const repos = listRepos();
  console.log(`Found ${repos.length} repos on SNAPKITTYWEST\n`);

  const toArchive = repos.filter(r =>
    !KEEP.has(r.name) &&
    !r.archived &&
    !r.private
  );

  const alreadyArchived = repos.filter(r => r.archived);
  const kept = repos.filter(r => KEEP.has(r.name));

  console.log(`KEEP (${kept.length} repos):`);
  kept.forEach(r => console.log(`  βœ… ${r.name}`));

  console.log(`\nALREADY ARCHIVED (${alreadyArchived.length} repos):`);
  alreadyArchived.forEach(r => console.log(`  πŸ“¦ ${r.name}`));

  console.log(`\nTO ARCHIVE (${toArchive.length} repos):`);
  toArchive.forEach(r => console.log(`  ⚠️  ${r.name} β€” ${r.description || 'no description'}`));

  if (DRY_RUN) {
    console.log(`\n${'='.repeat(60)}`);
    console.log(`DRY RUN COMPLETE. Run with --execute to archive ${toArchive.length} repos.`);
    console.log(`${'='.repeat(60)}\n`);
    return;
  }

  console.log(`\nArchiving ${toArchive.length} repos...`);

  let done = 0;
  for (const repo of toArchive) {
    // 1. Mark archived via GitHub API
    const desc = `[ARCHIVED] ${(repo.description || repo.name).slice(0,200)} β€” SSL v3.0`;
    const result = ghPatch(
      `repos/SNAPKITTYWEST/${repo.name}`,
      { archived: true, description: desc }
    );

    if (result) {
      done++;
      console.log(`  πŸ“¦ [${done}/${toArchive.length}] ${repo.name}`);
    } else {
      console.log(`  ❌ FAILED: ${repo.name}`);
    }
  }

  console.log(`\n${'='.repeat(60)}`);
  console.log(`ARCHIVE SWEEP COMPLETE`);
  console.log(`  Archived: ${done}/${toArchive.length}`);
  console.log(`  Active:   ${kept.length} repos`);
  console.log(`  Total:    ${repos.length} repos`);
  console.log(`${'='.repeat(60)}\n`);
  console.log(`Ryan wakes up. 100 repos gone. Only signal remains.`);
}

main();