deviant/scripts/snapshot.mjs
walerikus 518a3ce174 chore: initial project baseline — full Deviant codebase under version control
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>
2026-06-13 20:38:07 +02:00

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}`);