Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/thatstupidcomputer / scripts/package.ts |
| Date | Not specified in source |
| Repository | Janady13/thatstupidcomputer |
| Revision | 57555cde46910102dd25d6c1c1fb2c359e9655bd |
| Branch | main |
| Path or archive member | scripts/package.ts |
| Original SHA-256 | 7c4024705935de75c1825ef9385ae915a929a4388401a7d9110604de08aef64c |
| Git blob SHA | 2b48d619db2931cfbc018276f86cb94cab2d0980 |
| Reading-copy SHA-256 | 7c4024705935de75c1825ef9385ae915a929a4388401a7d9110604de08aef64c |
Recovered source transcript
Download complete source text ↓67 lines · 5.4 KB
import JSZip from 'jszip';
import { createHash } from 'node:crypto';
import { readdir, readFile, writeFile, mkdir, lstat } from 'node:fs/promises';
import { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const root = fileURLToPath(new URL('..', import.meta.url));
const topFiles = ['README.md', 'workshop-cleanup-manifest.json', 'AGENTS.md', 'CLAUDE.md', 'package.json', 'package-lock.json', 'tsconfig.json', 'playwright.config.ts', '.env.example', '.nvmrc', '.npmrc', '.gitignore'];
const trees = ['apps', 'packages', 'scripts', 'tests', 'docs', 'deploy', 'native', 'private/standards'];
const required = ['apps/web/dist/index.html', 'apps/web/dist/404.html', 'apps/api/dist/server.mjs', '.build/build-record.json', 'docs/ACCEPTANCE.md', 'docs/WORKSHOP-CLEANUP-ACCEPTANCE.md', 'docs/WORKSHOP-CLEANUP-INTEGRATION.md', 'docs/UPGRADE-ACCEPTANCE.md', 'docs/DESKTOP-ACCEPTANCE.md', 'docs/DESKTOP-INTEGRATION.md', 'docs/desktop-preview/desktop-proof.json', 'docs/CLAUDE-DEPLOYMENT.md', 'docs/standards/build-integration.json', 'docs/standards/local-verification.json'];
for (const name of required) if (!(await lstat(resolve(root, name))).isFile()) throw new Error(`Required delivery file is missing: ${name}`);
const record = JSON.parse(await readFile(resolve(root, '.build/build-record.json'), 'utf8'));
const lock = await readFile(resolve(root, 'package-lock.json'));
if (record.lockSha256 !== createHash('sha256').update(lock).digest('hex')) throw new Error('Dependency lock changed after the build. Rebuild before packaging.');
const local = JSON.parse(await readFile(resolve(root, 'docs/standards/local-verification.json'), 'utf8'));
const integration = JSON.parse(await readFile(resolve(root, 'docs/standards/build-integration.json'), 'utf8'));
if (local.result !== 'PASS' || integration.status !== 'PASS') throw new Error('Complete local verification must pass before packaging.');
for (const artifact of integration.publicBuild as { path: string; sha256: string }[]) {
if (!artifact.path.startsWith('apps/web/dist/') || artifact.path.split('/').includes('..')) throw new Error('Invalid public build evidence path.');
const digest = createHash('sha256').update(await readFile(resolve(root, artifact.path))).digest('hex');
if (digest !== artifact.sha256) throw new Error(`Tested public artifact changed before packaging: ${artifact.path}`);
}
const excludedDirectoryNames = new Set(['node_modules', '.git', '.tools', 'test-results', 'playwright-report', 'artifacts', '__pycache__']);
function include(path: string): boolean {
if (path.split('/').includes('.build') && !path.startsWith('.build/verification/')) return false;
if (path.split('/').some(part => excludedDirectoryNames.has(part))) return false;
if (path.startsWith('native/reports/canvas/')) return false; // Reproducible intermediate frames; all metrics and reviewed sheets are included.
if (/^native\/reports\/(minimal|.*-cli\.)/.test(path)) return false; // Failed early graphics-environment probes, not acceptance evidence.
if (/(?:^|\/)\.env(?:\.|$)/.test(path) && path !== '.env.example') return false;
if (/\.(?:py|pyc|pyo|pem|key|map|zip|tar|gz)$/i.test(path)) return false;
if (path.endsWith('/runtime.env') || path.endsWith('/build.env')) return false;
return true;
}
async function walk(directory: string): Promise<string[]> {
const result: string[] = [];
for (const entry of await readdir(resolve(root, directory), { withFileTypes: true })) {
const name = `${directory}/${entry.name}`;
if (!include(name)) continue;
if (entry.isSymbolicLink()) throw new Error(`Refusing to package a symlink: ${name}`);
if (entry.isDirectory()) result.push(...await walk(name));
else if (entry.isFile()) result.push(name);
}
return result;
}
const files = [...topFiles, '.build/build-record.json'];
files.push(...await walk('.build/verification'));
for (const tree of trees) files.push(...await walk(tree));
const unique = [...new Set(files)].sort();
const zip = new JSZip();
const manifest: { schema: string; createdAt: string; deployment: string; files: {path: string; bytes: number; sha256: string}[] } = {
schema: 'tsc-release/v1', createdAt: new Date().toISOString(), deployment: record.deployment, files: [],
};
const stableDate = new Date('2026-09-13T00:00:00Z');
for (const name of unique) {
const bytes = await readFile(resolve(root, name));
manifest.files.push({ path: name, bytes: bytes.length, sha256: createHash('sha256').update(bytes).digest('hex') });
zip.file(`TSC-WORKSHOP-CLEANUP-v4/${name}`, bytes, { date: stableDate, unixPermissions: name.endsWith('.sh') ? 0o100755 : 0o100644 });
}
zip.file('TSC-WORKSHOP-CLEANUP-v4/release-manifest.json', JSON.stringify(manifest, null, 2) + '\n', { date: stableDate, unixPermissions: 0o100644 });
const archive = await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE', compressionOptions: { level: 9 }, platform: 'UNIX' });
const output = resolve(root, 'artifacts/TSC-WORKSHOP-CLEANUP-v4.zip');
await mkdir(resolve(root, 'artifacts'), { recursive: true });
await writeFile(output, archive);
const sha256 = createHash('sha256').update(archive).digest('hex');
await writeFile(`${output}.sha256`, `${sha256} TSC-WORKSHOP-CLEANUP-v4.zip\n`);
console.log(JSON.stringify({ archive: output, bytes: archive.length, files: manifest.files.length + 1, sha256, deployment: record.deployment, note: 'Contains complete source and compiled preview; live production bindings are documented in docs/CLAUDE-DEPLOYMENT.md.' }, null, 2));