// tests/helpers/artifact-repo.mjs // A throwaway target repo for the artifact-commit tests // (tests/lib/artifact-commit.test.mjs, tests/lib/artifact-commit-trailer.test.mjs): // one commit, no git hooks, a project folder holding brief.md and, unless // `withLog` is false, an approval-log entry for it. import { spawnSync } from 'node:child_process'; import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { childEnv } from './child-env.mjs'; const LOG = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'lib', 'util', 'approval-log.mjs'); const H1 = 'c'.repeat(64); export function git(cwd, ...args) { return spawnSync('git', args, { cwd, encoding: 'utf8', env: childEnv() }); } /** @returns {{ d: string, brief: string }} the repo and its brief.md */ export function artifactRepo({ prefix = 'artifact-commit-', project = '2026-10-06-toggle', withLog = true } = {}) { const d = mkdtempSync(join(tmpdir(), prefix)); git(d, 'init', '-q'); git(d, 'config', 'user.name', 'Test'); git(d, 'config', 'user.email', 'test@example.invalid'); git(d, 'config', 'commit.gpgsign', 'false'); mkdirSync(join(d, '.hooks-none')); git(d, 'config', 'core.hooksPath', '.hooks-none'); writeFileSync(join(d, 'README.md'), 'x\n'); git(d, 'add', 'README.md'); git(d, 'commit', '-q', '-m', 'init'); const proj = join(d, '.claude', 'projects', project); mkdirSync(proj, { recursive: true }); writeFileSync(join(proj, 'brief.md'), '# brief\n'); if (withLog) { spawnSync(process.execPath, [LOG, 'append', '--kind', 'intent', '--subject', join(proj, 'brief.md'), '--sha256', H1], { cwd: d, env: childEnv() }); } return { d, brief: join(proj, 'brief.md') }; }