ktworkflow-mcp/src/tools/closeout.ts

165 lines
7.6 KiB
TypeScript
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 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,
};
}