Scaffold a fixture project with the bins + scripts the cathedral needs.
(prefix: string)
| 40 | |
| 41 | /** Scaffold a fixture project with the bins + scripts the cathedral needs. */ |
| 42 | function scaffoldFixture(prefix: string): { workDir: string; stateRoot: string; slug: string } { |
| 43 | const workDir = fs.mkdtempSync(path.join(os.tmpdir(), prefix)); |
| 44 | const stateRoot = path.join(workDir, '.gstack-state'); |
| 45 | fs.mkdirSync(stateRoot, { recursive: true }); |
| 46 | |
| 47 | // git init so gstack-slug resolves a deterministic slug. |
| 48 | spawnSync('git', ['init', '-b', 'main'], { cwd: workDir, stdio: 'pipe' }); |
| 49 | spawnSync('git', ['config', 'user.email', 't@t.com'], { cwd: workDir, stdio: 'pipe' }); |
| 50 | spawnSync('git', ['config', 'user.name', 'T'], { cwd: workDir, stdio: 'pipe' }); |
| 51 | fs.writeFileSync(path.join(workDir, 'README.md'), '# cathedral fixture\n'); |
| 52 | spawnSync('git', ['add', '.'], { cwd: workDir, stdio: 'pipe' }); |
| 53 | spawnSync('git', ['commit', '-m', 'init'], { cwd: workDir, stdio: 'pipe' }); |
| 54 | |
| 55 | // Copy bins. |
| 56 | const binDir = path.join(workDir, 'bin'); |
| 57 | fs.mkdirSync(binDir, { recursive: true }); |
| 58 | for (const script of [ |
| 59 | 'gstack-slug', |
| 60 | 'gstack-config', |
| 61 | 'gstack-paths', |
| 62 | 'gstack-question-log', |
| 63 | 'gstack-question-preference', |
| 64 | 'gstack-developer-profile', |
| 65 | 'gstack-codex-session-import', |
| 66 | 'gstack-distill-free-text', |
| 67 | 'gstack-distill-apply', |
| 68 | ]) { |
| 69 | const src = path.join(ROOT, 'bin', script); |
| 70 | if (fs.existsSync(src)) { |
| 71 | fs.copyFileSync(src, path.join(binDir, script)); |
| 72 | fs.chmodSync(path.join(binDir, script), 0o755); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | // Copy scripts that the bins import. |
| 77 | const scriptsDir = path.join(workDir, 'scripts'); |
| 78 | fs.mkdirSync(scriptsDir, { recursive: true }); |
| 79 | for (const f of [ |
| 80 | 'question-registry.ts', |
| 81 | 'psychographic-signals.ts', |
| 82 | 'archetypes.ts', |
| 83 | 'one-way-doors.ts', |
| 84 | 'declared-annotation.ts', |
| 85 | ]) { |
| 86 | const src = path.join(ROOT, 'scripts', f); |
| 87 | if (fs.existsSync(src)) fs.copyFileSync(src, path.join(scriptsDir, f)); |
| 88 | } |
| 89 | |
| 90 | // Copy hooks dir. |
| 91 | copyDirSync(path.join(ROOT, 'hosts', 'claude', 'hooks'), path.join(workDir, 'hosts', 'claude', 'hooks')); |
| 92 | |
| 93 | const slug = path.basename(workDir).replace(/[^a-zA-Z0-9._-]/g, ''); |
| 94 | return { workDir, stateRoot, slug }; |
| 95 | } |
| 96 | |
| 97 | function cleanupFixture(workDir: string): void { |
| 98 | try { |
no test coverage detected