feat: 固化卡点处理工具
This commit is contained in:
parent
2372b682a5
commit
74ee4877ba
@ -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`,先看专项禁区。
|
||||||
|
|||||||
@ -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',
|
||||||
|
|||||||
@ -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',
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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
74
src/tools/blocker.ts
Normal 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
12
src/types.ts
12
src/types.ts
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user