Files

64 lines
2.3 KiB
JavaScript

import { execFileSync } from 'node:child_process';
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
import path from 'node:path';
import { getFeatureDirectory, validateFeatureId } from './feature-record.mjs';
const [featureId, slug] = process.argv.slice(2);
const repositoryRoot = process.cwd();
if (!featureId || !slug || !validateFeatureId(featureId)) {
throw new Error('用法:npm run governance:start -- <功能编号> <英文短名称>');
}
const featureDirectory = getFeatureDirectory(repositoryRoot, featureId, slug);
const gitnexusDirectory = path.join(featureDirectory, 'gitnexus');
const beforeReport = path.join(gitnexusDirectory, 'before.md');
if (existsSync(beforeReport)) {
throw new Error(`开发前报告已存在,为保护历史不会覆盖:${beforeReport}`);
}
mkdirSync(gitnexusDirectory, { recursive: true });
/**
* 开发门禁直接调用参数数组,不拼接 shell 字符串,避免功能名称被解释为命令。
* stdio 使用 pipe 是为了把同一次运行的真实输出固化到功能档案中。
*/
function run(command, args) {
return execFileSync(command, args, {
cwd: repositoryRoot,
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
}).trim();
}
const branch = run('git', ['branch', '--show-current']) || '(尚无分支)';
const commit = run('git', ['rev-parse', '--verify', 'HEAD']).slice(0, 12);
const worktree = run('git', ['status', '--short']) || '(干净)';
run('npx', ['gitnexus', 'analyze']);
const gitnexusStatus = run('npx', ['gitnexus', 'status']);
const createdAt = new Intl.DateTimeFormat('zh-CN', {
dateStyle: 'long',
timeStyle: 'long',
timeZone: 'Asia/Shanghai',
}).format(new Date());
writeFileSync(
beforeReport,
`# GitNexus 开发前基线\n\n` +
`- 功能编号:${featureId}\n` +
`- 记录时间:${createdAt}\n` +
`- 分支:${branch}\n` +
`- 基线提交:${commit}\n\n` +
`## 工作区\n\n\`\`\`text\n${worktree}\n\`\`\`\n\n` +
`## GitNexus 状态\n\n\`\`\`text\n${gitnexusStatus}\n\`\`\`\n\n` +
`## 后续人工分析\n\n` +
`在修改代码前,将 GitNexus query、context、impact 的结论写入 ` +
`\`gitnexus/impact-plan.md\`。高风险结果必须先获得用户确认。\n`,
'utf8',
);
process.stdout.write(`已创建开发前基线:${beforeReport}\n`);