Brings the whole project into git (previously only the on-ramp feature and a few parallel files were tracked). Includes: wallet core (src/), CashScript contracts/, the Capacitor shell (shells/), scripts/, tests, and the docs corpus (wiki/, snapshots/, Parameters/, Archive/, KnowledgeBase text). Excluded via .gitignore: node_modules/, dist/, .env (secrets), testnet WIF key files (.chipnet-*.json, devWallets.ts), KnowledgeBase/RAW media (~9.6 GB), transcripts/ (session logs), and machine-local config (.claude/*.local, *.lock). Secret-scanned before commit — no credentials in the tree. Note: src/swapMath.ts, src/swapBuilder.ts, contracts/OpenMintToken.cash are legacy (OP_RETURN era) but still imported; committed as-is, flagged for a separate removal once de-referenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
82 lines
2.5 KiB
JavaScript
82 lines
2.5 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* snapshot.mjs — appends a new numbered snapshot under snapshots/
|
|
*
|
|
* Per CLAUDE.md: "Snapshots, to track progress." Each snapshot captures
|
|
* the working state at a milestone — a compact, append-only ledger.
|
|
*
|
|
* Usage: node scripts/snapshot.mjs "short title here"
|
|
*/
|
|
import { readdirSync, writeFileSync, existsSync, mkdirSync, statSync, readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { execSync } from 'node:child_process';
|
|
|
|
const ROOT = join(import.meta.dirname, '..');
|
|
const DIR = join(ROOT, 'snapshots');
|
|
if (!existsSync(DIR)) mkdirSync(DIR, { recursive: true });
|
|
|
|
const title = process.argv.slice(2).join(' ').trim() || 'untitled';
|
|
const existing = readdirSync(DIR).filter((f) => /^\d{4}-/.test(f));
|
|
// Number by the highest existing number + 1, NOT by file count: this repo has
|
|
// duplicate-numbered snapshots (two parallel tracks were merged), so count-based
|
|
// numbering drifts ahead of the visible sequence. max+1 stays consistent.
|
|
const maxNum = existing.reduce((m, f) => Math.max(m, parseInt(f.slice(0, 4), 10)), 0);
|
|
const next = String(maxNum + 1).padStart(4, '0');
|
|
|
|
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40) || 'snapshot';
|
|
const filename = `${next}-${slug}.md`;
|
|
|
|
let gitRev = '(no git)';
|
|
let gitStatus = '';
|
|
try {
|
|
gitRev = execSync('git rev-parse --short HEAD', { cwd: ROOT, stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
gitStatus = execSync('git status --short', { cwd: ROOT, stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
} catch {
|
|
// not a git repo yet — fine
|
|
}
|
|
|
|
function fileCount(dir) {
|
|
if (!existsSync(dir)) return 0;
|
|
let n = 0;
|
|
const walk = (d) => {
|
|
for (const e of readdirSync(d)) {
|
|
const f = join(d, e);
|
|
if (statSync(f).isDirectory()) walk(f);
|
|
else n++;
|
|
}
|
|
};
|
|
walk(dir);
|
|
return n;
|
|
}
|
|
|
|
const counts = {
|
|
src: fileCount(join(ROOT, 'src')),
|
|
contracts: fileCount(join(ROOT, 'contracts')),
|
|
test: fileCount(join(ROOT, 'test')),
|
|
};
|
|
|
|
const stamp = new Date().toISOString();
|
|
const body = `# Snapshot ${next}: ${title}
|
|
|
|
_Captured ${stamp}_
|
|
|
|
## Git state
|
|
|
|
- Rev: \`${gitRev}\`
|
|
${gitStatus ? `- Working tree:\n\n\`\`\`\n${gitStatus}\n\`\`\`` : '- Working tree: clean'}
|
|
|
|
## File counts
|
|
|
|
| Area | Files |
|
|
|---|---|
|
|
| src/ | ${counts.src} |
|
|
| contracts/ | ${counts.contracts} |
|
|
| test/ | ${counts.test} |
|
|
|
|
## Notes
|
|
|
|
<!-- Fill in: what shipped, what's deferred, what surprised you. -->
|
|
`;
|
|
|
|
writeFileSync(join(DIR, filename), body);
|
|
console.log(`Wrote snapshots/${filename}`);
|