feat: 固化卡点处理工具

This commit is contained in:
sunlei 2026-06-07 03:23:02 +08:00
parent 2372b682a5
commit 74ee4877ba
6 changed files with 119 additions and 0 deletions

View File

@ -13,6 +13,7 @@
- 生成页面测试用例:内置“先写用例、可视化证据、事不过三”的测试闭环。 - 生成页面测试用例:内置“先写用例、可视化证据、事不过三”的测试闭环。
- 生成接口测试计划:接口改动后输出真实调用命令和统一返回结构断言。 - 生成接口测试计划:接口改动后输出真实调用命令和统一返回结构断言。
- 生成业务链路测试计划:固化 Admin 登录、博客 CRUD、QQBot 扫码/自动回复、更新登录 SSE、FFLogs 命令、系统日志可视化、Web/Playground 回跳。 - 生成业务链路测试计划:固化 Admin 登录、博客 CRUD、QQBot 扫码/自动回复、更新登录 SSE、FFLogs 命令、系统日志可视化、Web/Playground 回跳。
- 生成卡点固化记录:把超时、卡进程、远程命令误写、重复失败整理成“问题点 / 稳定解法 / 后续入口 / 验证证据”,避免原样重试。
- 生成多仓库提交/推送计划:按仓库分组、建议提交信息、列出提交和推送前检查。 - 生成多仓库提交/推送计划:按仓库分组、建议提交信息、列出提交和推送前检查。
- 生成远程只读健康检查和数据库同步安全向导:覆盖飞牛 NAS 服务探测、GTID、备份和行数校验。 - 生成远程只读健康检查和数据库同步安全向导:覆盖飞牛 NAS 服务探测、GTID、备份和行数校验。
- 生成专项组件工作流KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 的防踩坑清单和验证点。 - 生成专项组件工作流KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 的防踩坑清单和验证点。
@ -79,6 +80,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
| `kt_commit_plan` | 生成多仓库提交计划、建议 commit message 和检查项 | | `kt_commit_plan` | 生成多仓库提交计划、建议 commit message 和检查项 |
| `kt_push_plan` | 生成多仓库推送计划和远程异常提醒 | | `kt_push_plan` | 生成多仓库推送计划和远程异常提醒 |
| `kt_business_test_plan` | 生成固化业务链路测试计划,包含 QQBot SSE、FFLogs 和系统日志 | | `kt_business_test_plan` | 生成固化业务链路测试计划,包含 QQBot SSE、FFLogs 和系统日志 |
| `kt_blocker_resolution` | 生成或写入卡点固化记录,提醒停止原样重试 |
| `kt_remote_health_check` | 生成或执行远程只读健康检查命令 | | `kt_remote_health_check` | 生成或执行远程只读健康检查命令 |
| `kt_db_sync_plan` | 生成数据库同步安全向导 | | `kt_db_sync_plan` | 生成数据库同步安全向导 |
| `kt_component_workflow` | 输出专项组件/链路防踩坑工作流,包含 FnosK8s | | `kt_component_workflow` | 输出专项组件/链路防踩坑工作流,包含 FnosK8s |
@ -124,6 +126,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
- 文件改动完成并验证后调用 `kt_global_code_review`,或运行 `pnpm run global-review`;它只读扫描,不删除文件、不提交代码。`findings` 先判定真实风险或工具误报,真实风险修业务代码,误报修 `mcp/ktWorkflow/src/tools/review.ts` 并复跑。 - 文件改动完成并验证后调用 `kt_global_code_review`,或运行 `pnpm run global-review`;它只读扫描,不删除文件、不提交代码。`findings` 先判定真实风险或工具误报,真实风险修业务代码,误报修 `mcp/ktWorkflow/src/tools/review.ts` 并复跑。
- 要提交或推送时先调用 `kt_commit_plan` / `kt_push_plan`,按仓库分组确认范围。 - 要提交或推送时先调用 `kt_commit_plan` / `kt_push_plan`,按仓库分组确认范围。
- 要测真实业务链路时调用 `kt_business_test_plan`,选择 `admin-login`、`qqbot-auto-reply`、`qqbot-login-sse`、`fflogs-command`、`system-log-visualization` 等 flow。 - 要测真实业务链路时调用 `kt_business_test_plan`,选择 `admin-login`、`qqbot-auto-reply`、`qqbot-login-sse`、`fflogs-command`、`system-log-visualization` 等 flow。
- 遇到同一命令或同一远程步骤重复卡住时调用 `kt_blocker_resolution`;第二次仍失败时先写入 `TASKS.md` 或补成脚本,再继续。
- 远程服务排查先调用 `kt_remote_health_check`,默认只生成只读命令;需要执行时显式传 `execute=true` - 远程服务排查先调用 `kt_remote_health_check`,默认只生成只读命令;需要执行时显式传 `execute=true`
- 数据库同步前调用 `kt_db_sync_plan`,先确认源库、目标库、备份库和校验点。 - 数据库同步前调用 `kt_db_sync_plan`,先确认源库、目标库、备份库和校验点。
- 改 KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 前调用 `kt_component_workflow`,先看专项禁区。 - 改 KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 前调用 `kt_component_workflow`,先看专项禁区。

View File

@ -56,6 +56,7 @@ export const registeredToolNames = [
'kt_commit_plan', 'kt_commit_plan',
'kt_push_plan', 'kt_push_plan',
'kt_business_test_plan', 'kt_business_test_plan',
'kt_blocker_resolution',
'kt_remote_health_check', 'kt_remote_health_check',
'kt_db_sync_plan', 'kt_db_sync_plan',
'kt_component_workflow', 'kt_component_workflow',

View File

@ -2,6 +2,7 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod'; import { z } from 'zod';
import type { McpTextResponse } from './types.js'; import type { McpTextResponse } from './types.js';
import { buildBlockerResolution } from './tools/blocker.js';
import { defaultHistoryRoots, taskTypeValues } from './core/constants.js'; import { defaultHistoryRoots, taskTypeValues } from './core/constants.js';
import { createCleanupProcessPlan, cleanupHistoryArtifacts } from './tools/cleanup.js'; import { createCleanupProcessPlan, cleanupHistoryArtifacts } from './tools/cleanup.js';
import { buildEnvPolicy, scanTaskRisk } from './tools/envRisk.js'; import { buildEnvPolicy, scanTaskRisk } from './tools/envRisk.js';
@ -291,6 +292,26 @@ export function registerTools(server: McpServer): void {
async (input) => response(buildBusinessTestPlan(input)), async (input) => response(buildBusinessTestPlan(input)),
); );
server.registerTool(
'kt_blocker_resolution',
{
description: '生成或写入卡点固化记录:问题点、稳定解法、后续入口、验证证据,并给出停止原样重试的下一步动作。',
inputSchema: {
attempts: z.number().int().min(0).max(20).default(1),
command: z.string().optional(),
dryRun: z.boolean().default(true),
evidence: z.string().optional(),
nextEntry: z.string().optional(),
problem: z.string().optional(),
project: z.string().default('root'),
solution: z.string().optional(),
title: z.string().optional(),
},
title: 'KT Blocker Resolution',
},
async (input) => response(buildBlockerResolution(input)),
);
server.registerTool( server.registerTool(
'kt_remote_health_check', 'kt_remote_health_check',
{ {

View File

@ -3,6 +3,7 @@ import path from 'node:path';
import { parseGlobalReviewCliArgs } from './core/cli.js'; import { parseGlobalReviewCliArgs } from './core/cli.js';
import { registeredToolNames } from './core/constants.js'; import { registeredToolNames } from './core/constants.js';
import { buildBlockerResolution } from './tools/blocker.js';
import { resolveInsideRoot } from './core/workspace.js'; import { resolveInsideRoot } from './core/workspace.js';
import { buildGuardrails } from './tools/guardrails.js'; import { buildGuardrails } from './tools/guardrails.js';
import { cleanupHistoryArtifacts } from './tools/cleanup.js'; import { cleanupHistoryArtifacts } from './tools/cleanup.js';
@ -77,6 +78,13 @@ export async function runSelfTest(): Promise<void> {
businessTestPlan: buildBusinessTestPlan({ businessTestPlan: buildBusinessTestPlan({
flow: 'system-log-visualization', flow: 'system-log-visualization',
}), }),
blockerResolution: buildBlockerResolution({
attempts: 2,
evidence: 'self-test',
problem: '重复超时',
project: 'mcp',
solution: '改用固定脚本和 timeout 后再验证',
}),
commitPlan: await buildCommitPlan({ commitPlan: await buildCommitPlan({
projects: ['mcp'], projects: ['mcp'],
}), }),

74
src/tools/blocker.ts Normal file
View File

@ -0,0 +1,74 @@
import { appendTaskRecord, buildTaskRecord } from './task.js';
import { resolveProject } from '../core/workspace.js';
import type { BlockerResolutionInput } from '../types.js';
function formatRecord(
input: Required<Pick<BlockerResolutionInput, 'nextEntry' | 'problem' | 'solution'>> &
Pick<BlockerResolutionInput, 'evidence'>,
): string {
const evidence = input.evidence || '待补充';
return `问题点:${input.problem};稳定解法:${input.solution};后续入口:${input.nextEntry};验证证据:${evidence}`;
}
export function buildBlockerResolution(input: BlockerResolutionInput = {}): Record<string, unknown> {
const attempts = input.attempts ?? 1;
const project = resolveProject(input.project || 'root');
const problem = input.problem || '待填写卡住的命令、接口、进程或远程阶段';
const solution = input.solution || '待填写已经验证或下一轮要验证的稳定解法';
const nextEntry = input.nextEntry || 'TASKS.md 或 docs/kt-testing-workflows.md';
const record = formatRecord({
evidence: input.evidence,
nextEntry,
problem,
solution,
});
const title = input.title || '卡点固化记录';
const taskRecord = buildTaskRecord({
content: record,
scope: [project.relativePath],
title,
verification: input.evidence || '待补充。',
});
const shouldStopBlindRetry = attempts >= 2;
const nextActions = shouldStopBlindRetry
? [
'停止原样重复执行同一条命令。',
'把问题点、稳定解法、后续入口和证据写入 TASKS.md、docs 或脚本。',
'下一轮只能改变一个可验证变量,例如缩短范围、增加 timeout、拆分 Pod 内外步骤或改用固定脚本。',
]
: [
'先采集命令、输入、PID 或 Pod、最后有效日志和已生成产物。',
'只清理本轮启动的进程、临时目录或 Pod 文件。',
'第二次尝试前必须改变一个可验证变量,不能原样等待。',
];
const writeResult =
input.dryRun === false
? appendTaskRecord({
content: record,
dryRun: false,
scope: [project.relativePath],
title,
verification: input.evidence || '待补充。',
})
: null;
return {
command: input.command || '',
dryRun: input.dryRun !== false,
nextActions,
project,
record,
safeCommandRules: [
'本地或远程长命令必须有外层 timeout 或固定脚本内置超时。',
'远程 here-doc、awk、kubectl jsonpath 和 Node 片段不能直接塞进双引号 ssh 命令。',
"PowerShell 多行 Node 片段使用单引号 here-string@' ... '@ | node -。",
'同一卡点最多两次原样尝试;第二次仍卡住先固化再继续。',
'只清理本轮启动的进程或临时文件,不批量杀未知进程。',
],
shouldStopBlindRetry,
taskRecord,
writeResult,
};
}

View File

@ -176,6 +176,18 @@ export interface BusinessTestPlanInput {
flow?: BusinessFlow | 'all'; flow?: BusinessFlow | 'all';
} }
export interface BlockerResolutionInput {
attempts?: number;
command?: string;
dryRun?: boolean;
evidence?: string;
nextEntry?: string;
problem?: string;
project?: string;
solution?: string;
title?: string;
}
export interface RemoteHealthCheckInput { export interface RemoteHealthCheckInput {
execute?: boolean; execute?: boolean;
host?: string; host?: string;