deviant/scripts/scan-code.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

102 lines
3.4 KiB
JavaScript

#!/usr/bin/env node
/**
* scan-code.mjs — produces wiki/code-map.md
*
* Purpose: cheap, deterministic index of the codebase so future Claude
* sessions can locate symbols without a directory walk. Per CLAUDE.md:
* "Create scripts to navigate source code and reduce claude processing
* time and token burn."
*
* Outputs a single markdown file with:
* - Tree of src/, contracts/, test/, scripts/, wiki/
* - Per-file: exported symbols (TS), pragma + contract names (CashScript),
* line count, first doc-comment line.
*
* Intentionally zero external deps — runs on plain Node.
*/
import { readdirSync, readFileSync, statSync, writeFileSync, existsSync } from 'node:fs';
import { join, relative, extname } from 'node:path';
const ROOT = join(import.meta.dirname, '..');
const TARGETS = ['src', 'contracts', 'test', 'scripts', 'wiki'];
const OUT = join(ROOT, 'wiki', 'code-map.md');
const IGNORE = new Set(['node_modules', 'dist', '.git', 'coverage', '.regtest-data']);
function walk(dir, out = []) {
for (const entry of readdirSync(dir)) {
if (IGNORE.has(entry)) continue;
const full = join(dir, entry);
const st = statSync(full);
if (st.isDirectory()) walk(full, out);
else out.push(full);
}
return out;
}
function describe(file) {
const ext = extname(file);
const src = readFileSync(file, 'utf8');
const lines = src.split('\n');
const lineCount = lines.length;
const summary = { lineCount, symbols: [], doc: '' };
// First non-empty non-shebang line containing a comment marker
for (const line of lines.slice(0, 20)) {
const t = line.trim();
if (!t || t.startsWith('#!')) continue;
if (t.startsWith('//') || t.startsWith('/*') || t.startsWith('*') || t.startsWith('pragma')) {
summary.doc = t.replace(/^[/*\s]+/, '').slice(0, 120);
break;
}
}
if (ext === '.ts' || ext === '.mjs' || ext === '.js') {
const reExport = /^\s*export\s+(?:async\s+)?(?:function|class|const|let|interface|type|enum)\s+([A-Za-z0-9_]+)/gm;
let m;
while ((m = reExport.exec(src)) !== null) summary.symbols.push(m[1]);
}
if (ext === '.cash') {
const reContract = /^\s*contract\s+([A-Za-z0-9_]+)\s*\(/gm;
const reFn = /^\s*function\s+([A-Za-z0-9_]+)\s*\(/gm;
let m;
while ((m = reContract.exec(src)) !== null) summary.symbols.push(`contract:${m[1]}`);
while ((m = reFn.exec(src)) !== null) summary.symbols.push(`fn:${m[1]}`);
}
return summary;
}
const sections = [];
for (const target of TARGETS) {
const targetPath = join(ROOT, target);
if (!existsSync(targetPath)) continue;
const files = walk(targetPath)
.filter((f) => /\.(ts|mjs|js|cash|md)$/.test(f))
.sort();
if (files.length === 0) continue;
const rows = [];
for (const f of files) {
const rel = relative(ROOT, f).replaceAll('\\', '/');
const { lineCount, symbols, doc } = describe(f);
const sym = symbols.length ? symbols.join(', ') : '—';
rows.push(`| \`${rel}\` | ${lineCount} | ${sym} | ${doc || '—'} |`);
}
sections.push(
`### ${target}/\n\n| File | Lines | Exports | First doc line |\n|---|---|---|---|\n${rows.join('\n')}\n`
);
}
const stamp = new Date().toISOString();
const out = `# Code Map
_Auto-generated by \`scripts/scan-code.mjs\` at ${stamp}_
_Do not edit by hand. Regenerate with \`npm run scan\`._
${sections.join('\n')}
`;
writeFileSync(OUT, out);
console.log(`Wrote ${relative(ROOT, OUT)}`);