Files
a-share-analysis/tools/governance/feature-record.mjs
T

71 lines
2.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import path from 'node:path';
const FEATURE_ID_PATTERN = /^(?:FEAT-[A-Z]{2,8}|GOV)-\d{3}$/;
const REQUIRED_FEATURE_FILES = Object.freeze([
'manifest.yaml',
'prd.md',
'requirements.md',
'design.md',
'implementation-plan.md',
'test-plan.md',
'gitnexus/before.md',
'gitnexus/impact-plan.md',
'gitnexus/detected-changes.md',
'gitnexus/after.md',
'gitnexus/comparison.md',
'qa/test-results.md',
'qa/visual-qa.md',
'review/code-review.md',
'review/standards-review.md',
'release-notes.md',
'rollback.md',
]);
const REVIEW_FILES = Object.freeze([
'review/code-review.md',
'review/standards-review.md',
]);
/**
* 功能编号是需求、设计、代码提交、测试结果和发布记录之间的主关联键。
* 严格限制格式可以避免路径穿越、临时名称以及后续无法检索的模糊编号。
*/
export function validateFeatureId(featureId) {
return FEATURE_ID_PATTERN.test(featureId);
}
/**
* 功能目录只允许位于 docs/features 下。短名称继续使用英文 kebab-case
* 便于命令行、URL 和跨平台文件系统稳定处理;面向人的名称保存在 manifest 中。
*/
export function getFeatureDirectory(repositoryRoot, featureId, slug) {
if (!validateFeatureId(featureId)) {
throw new Error(`功能编号格式无效:${featureId}`);
}
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug)) {
throw new Error(`功能短名称必须使用 kebab-case:${slug}`);
}
return path.join(repositoryRoot, 'docs', 'features', `${featureId}-${slug}`);
}
/**
* 返回副本,防止调用方修改共享清单后绕过完成门禁。
*/
export function getRequiredFeatureFiles() {
return [...REQUIRED_FEATURE_FILES];
}
/**
* Review 报告不能只靠“文件存在”通过门禁。这里要求报告使用固定的最终结论行,
* 避免 pending、blocked 或 changes_required 被一段其他说明文字意外判定为通过。
*/
export function getUnpassedReviewFiles(reviewReports) {
return REVIEW_FILES.filter((file) => {
const content = reviewReports.get(file) ?? '';
return !/^最终结论:passed$/m.test(content);
});
}