165 lines
7.6 KiB
TypeScript
165 lines
7.6 KiB
TypeScript
import type { WorkstreamCloseoutInput, WorkstreamReusablePattern } from '../types.js';
|
||
import { workstreamReusablePatternValues } from '../core/constants.js';
|
||
import { cleanupEvidenceShowsDeletedZero, normalizeCleanupDeletedCount } from './cleanupEvidence.js';
|
||
import { defaultReviewProjects } from './review.js';
|
||
|
||
interface UpgradeTarget {
|
||
files: string[];
|
||
label: string;
|
||
prompt: string;
|
||
}
|
||
|
||
const upgradeTargets = {
|
||
blocker: {
|
||
files: ['src/tools/blocker.ts', 'src/tools/workflow.ts', 'README.md'],
|
||
label: '卡点固化',
|
||
prompt: '把重复失败的命令、稳定解法、停止条件和后续入口沉淀成 kt_blocker_resolution 或收尾规则。',
|
||
},
|
||
cleanup: {
|
||
files: ['src/tools/cleanup.ts', 'src/tools/verification.ts', 'README.md'],
|
||
label: '清理需求',
|
||
prompt: '把历史产物、验证进程或远程临时目录清理变成可复用命令或验证提醒。',
|
||
},
|
||
'command-template': {
|
||
files: ['src/tools/workflow.ts', 'src/tools/testing.ts', 'scripts/'],
|
||
label: '命令模板',
|
||
prompt: '把反复使用且容易写错的命令模板封装到工作流、业务测试计划或脚本。',
|
||
},
|
||
'deploy-observation': {
|
||
files: ['src/tools/deployObservation.ts', 'src/tools/workflow.ts', 'src/tools/testing.ts', 'README.md'],
|
||
label: '部署观测',
|
||
prompt: '把 Jenkins/K8s build、commit、镜像、Deployment、Pod、/health/runtime、日志和 smoke 观测步骤写成固定计划。',
|
||
},
|
||
none: {
|
||
files: [],
|
||
label: '无可执行升级',
|
||
prompt: '明确说明本轮没有新的可复用流程、误报、清理或命令模板需要沉淀。',
|
||
},
|
||
'review-false-positive': {
|
||
files: ['src/tools/review.ts', 'src/selfTest.ts', 'README.md'],
|
||
label: '复审误报',
|
||
prompt: '把已确认的误报规则沉淀到 review 过滤器和 self-test,避免后续污染上下文。',
|
||
},
|
||
'test-flow': {
|
||
files: ['src/tools/testing.ts', 'scripts/', 'README.md'],
|
||
label: '测试链路',
|
||
prompt: '把新的真实接口、页面、QQBot、部署或业务 smoke 流程加入测试计划或脚本。',
|
||
},
|
||
} satisfies Record<WorkstreamReusablePattern, UpgradeTarget>;
|
||
|
||
function normalizeList(values?: string[]): string[] {
|
||
return (values || []).map((value) => value.trim()).filter(Boolean);
|
||
}
|
||
|
||
function normalizePatterns(values?: WorkstreamReusablePattern[]): WorkstreamReusablePattern[] {
|
||
const validValues = new Set<WorkstreamReusablePattern>(workstreamReusablePatternValues);
|
||
const uniqueValues = Array.from(
|
||
new Set((values || []).filter((value) => validValues.has(value))),
|
||
);
|
||
const patterns: WorkstreamReusablePattern[] = uniqueValues.length > 0 ? uniqueValues : ['none'];
|
||
|
||
return patterns.length > 1 ? patterns.filter((pattern) => pattern !== 'none') : patterns;
|
||
}
|
||
|
||
function buildPhase(name: string, evidence: string[], emptyHint: string): Record<string, unknown> {
|
||
return {
|
||
evidence,
|
||
name,
|
||
status: evidence.length > 0 ? 'ok' : 'missing',
|
||
suggestion: evidence.length > 0 ? undefined : emptyHint,
|
||
};
|
||
}
|
||
|
||
export function buildWorkstreamCloseout(input: WorkstreamCloseoutInput = {}): Record<string, unknown> {
|
||
const title = input.title?.trim() || '';
|
||
const changedProjects = normalizeList(input.changedProjects);
|
||
const cleanupEvidence = normalizeList(input.cleanupEvidence);
|
||
const cleanupFinalDeleted = normalizeCleanupDeletedCount(input.cleanupFinalDeleted);
|
||
const cleanupOk =
|
||
cleanupFinalDeleted === 0 || cleanupEvidenceShowsDeletedZero(cleanupEvidence);
|
||
const docSyncEvidence = normalizeList(input.docSyncEvidence);
|
||
const verificationEvidence = normalizeList(input.verificationEvidence);
|
||
const problemRecords = normalizeList(input.problemRecords);
|
||
const reviewEvidence = normalizeList(input.reviewEvidence);
|
||
const stableSolutions = normalizeList(input.stableSolutions);
|
||
const superpowersReviewEvidence = normalizeList(input.superpowersReviewEvidence);
|
||
const patterns = normalizePatterns(input.reusablePatterns);
|
||
const upgradeNeeded = patterns.some((pattern) => pattern !== 'none');
|
||
const ktWorkflowUpdated = input.ktWorkflowUpdated === true;
|
||
const missingItems = [
|
||
title ? '' : '填写本轮大方向名称或目标。',
|
||
verificationEvidence.length > 0
|
||
? ''
|
||
: '补充测试或 smoke 验证证据;上线功能必须包含线上自测证据,只有计划或 Jenkins/K8s 成功不算闭环完成。',
|
||
docSyncEvidence.length > 0 ? '' : '补充文档同步证据;无需更新时也要显式写明原因。',
|
||
cleanupOk ? '' : '补充历史产物清理证据;至少包含 cleanup-history dry-run deleted=0 或结构化 cleanupFinalDeleted=0。',
|
||
reviewEvidence.length > 0 ? '' : '补充 KT 全局 review 证据。',
|
||
superpowersReviewEvidence.length > 0 ? '' : '补充 Superpowers code review 证据。',
|
||
problemRecords.length > 0 ? '' : '补充问题记录;如无新卡点,显式写“无新卡点”。',
|
||
stableSolutions.length > 0 ? '' : '补充稳定解法;如无新解法,显式写“无新增稳定解法”。',
|
||
upgradeNeeded && !ktWorkflowUpdated
|
||
? '本轮识别到可复用模式,先升级 ktWorkflow 对应规则或脚本,再报告完成。'
|
||
: '',
|
||
].filter(Boolean);
|
||
const targetProjects = changedProjects.length > 0 ? changedProjects : [...defaultReviewProjects];
|
||
const selectedUpgradeTargets = patterns.map((pattern) => ({
|
||
pattern,
|
||
...upgradeTargets[pattern],
|
||
}));
|
||
|
||
return {
|
||
canReportComplete: missingItems.length === 0,
|
||
closeoutOrder: [
|
||
buildPhase('development', title ? [title] : [], '写清本轮完成的开发目标。'),
|
||
buildPhase(
|
||
'test/smoke verification',
|
||
verificationEvidence,
|
||
'补一条可复验的验证证据;上线功能必须补线上自测证据。',
|
||
),
|
||
buildPhase('documentation sync', docSyncEvidence, '补充 kt_change_doc_sync 证据或无需更新说明。'),
|
||
{
|
||
evidence: [
|
||
...cleanupEvidence,
|
||
...(cleanupFinalDeleted === undefined
|
||
? []
|
||
: [`cleanupFinalDeleted=${cleanupFinalDeleted}`]),
|
||
],
|
||
name: 'history cleanup',
|
||
status: cleanupOk ? 'ok' : 'missing',
|
||
suggestion: cleanupOk
|
||
? undefined
|
||
: '补充 cleanup-history dry-run deleted=0 证据或传入 cleanupFinalDeleted=0。',
|
||
},
|
||
buildPhase('KT global review', reviewEvidence, '补充 kt_global_code_review 或 global-review 证据。'),
|
||
buildPhase('Superpowers code review', superpowersReviewEvidence, '补充 Superpowers reviewer 创建/完成/关闭和处理结论证据。'),
|
||
buildPhase('problem record', problemRecords, '记录问题点;没有问题也要显式写明。'),
|
||
buildPhase('stable solution', stableSolutions, '记录稳定解法;没有新增解法也要显式写明。'),
|
||
{
|
||
evidence: upgradeNeeded
|
||
? [
|
||
ktWorkflowUpdated
|
||
? input.upgradeNotes || '已升级 ktWorkflow。'
|
||
: '待升级 ktWorkflow。',
|
||
]
|
||
: [input.upgradeNotes || '无新的可执行 ktWorkflow 升级需求。'],
|
||
name: 'ktWorkflow upgrade',
|
||
status: upgradeNeeded ? (ktWorkflowUpdated ? 'ok' : 'missing') : 'not-needed',
|
||
},
|
||
],
|
||
commands: [
|
||
'git status --short',
|
||
'pnpm run typecheck',
|
||
'pnpm run self-test',
|
||
'pnpm run global-review',
|
||
'pnpm run workstream-closeout -- --superpowers-review "Superpowers reviewer completed; no Critical/Important findings"',
|
||
'git diff --check',
|
||
],
|
||
missingItems,
|
||
patterns,
|
||
targetProjects,
|
||
title: title || '未命名大方向',
|
||
upgradeNeeded,
|
||
upgradeTargets: selectedUpgradeTargets,
|
||
};
|
||
}
|