diff --git a/README.md b/README.md index d021c02..a18add4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # KT Workflow MCP -`ktWorkflow` 是 KT 工作区的可复用 MCP 能力包,用 TypeScript 封装工具入参、项目别名和返回结构,用来把根目录 `AGENTS.md` 的硬规则、`SKILLS.md` 的工作流索引、`TASKS.md` 的上下文记录和 `docs/` 的详细流程变成可调用工具。 +`ktWorkflow` 是 KT 工作区的可复用 MCP 能力包,用 TypeScript 封装工具入参、项目别名和返回结构,用来把根目录 `AGENTS.md` 的硬规则、`SKILLS.md` 的工作流索引、`TASKS.md` 的上下文记录和 `docs/` 的详细流程变成可调用工具。当前版本:`0.6.1`。 ## 能力边界 @@ -15,11 +15,11 @@ - 生成业务链路测试计划:固化 Admin 登录、博客 CRUD、QQBot 扫码/自动回复、更新登录 SSE、FFLogs 命令、系统日志可视化、Web/Playground 回跳。 - 生成多仓库提交/推送计划:按仓库分组、建议提交信息、列出提交和推送前检查。 - 生成远程只读健康检查和数据库同步安全向导:覆盖飞牛 NAS 服务探测、GTID、备份和行数校验。 -- 生成专项组件工作流:KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger 的防踩坑清单和验证点。 +- 生成专项组件工作流:KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 的防踩坑清单和验证点。 - 生成验证进程清理计划:按项目路径和端口给出 PowerShell 检查命令,不直接杀进程。 - 清理历史产物:统一治理 `.kt-workspace` 下的测试/验证产物,按目录最近修改时间只保留最近 3 轮,模板目录永久保留。 - 检查 env 策略和变更风险:区分后端真实 env 与前端客户端 `.env*`,提醒锁文件、核心表格组件、部署链路和 Vue TSX 插槽写法等高风险改动。 -- 全局 CodeReview 只读扫描:汇总全部 KT 子仓库的 Git 状态、敏感文件跟踪、冲突标记、运行时调试输出、疑似凭据字面量、根目录生成产物和当前变更风险;默认只对变更文件做内容扫描,避免历史误报污染上下文;任何文件改动后都要跑一遍。 +- 全局 CodeReview 只读扫描:汇总全部 KT 子仓库的 Git 状态、敏感文件跟踪、冲突标记、运行时调试输出、疑似凭据字面量、根目录生成产物和当前变更风险;默认只对变更文件做内容扫描,并放过短中文显示标签,避免历史误报污染上下文;任何文件改动后都要跑一遍。 - 生成或写入 `TASKS.md` 最近记录:默认 `dryRun=true`,确认后再落盘。 - 生成提交前检查清单:校验 KT commit message 约定。 @@ -81,7 +81,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login | `kt_business_test_plan` | 生成固化业务链路测试计划,包含 QQBot SSE、FFLogs 和系统日志 | | `kt_remote_health_check` | 生成或执行远程只读健康检查命令 | | `kt_db_sync_plan` | 生成数据库同步安全向导 | -| `kt_component_workflow` | 输出专项组件/链路防踩坑工作流 | +| `kt_component_workflow` | 输出专项组件/链路防踩坑工作流,包含 FnosK8s | | `kt_append_task_record` | 预览或写入 `TASKS.md` 最近记录 | | `kt_commit_checklist` | 生成提交前检查清单并校验 commit message | @@ -90,7 +90,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login | 脚本 | 用途 | | --- | --- | | `pnpm run admin-login` | 使用可见 Edge 打开 Admin 登录页,填写账号密码,拖动滑块,保存登录态和截图。默认账号来自初始化数据 `admin/123456`,生产或个人账号用 `KT_ADMIN_USERNAME` / `KT_ADMIN_PASSWORD` 或 CLI 参数覆盖。 | -| `pnpm run global-review` | 对 KT 全部子仓库做只读全局 CodeReview 扫描,默认仅对变更文件做内容深扫,输出 JSON 复审报告。 | +| `pnpm run global-review` | 对 KT 全部子仓库做只读全局 CodeReview 扫描,默认仅对变更文件做内容深扫,输出 JSON 复审报告;确认误报时优先升级 `src/tools/review.ts`,不要把误报沉积到上下文。 | ## 项目别名 @@ -121,12 +121,12 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login - 写代码前先调用 `kt_prepare_task`;只需要单项信息时再调用 `kt_read_context` 或 `kt_inspect_project`。`kt_read_context` 默认紧凑输出,只有确实需要完整 `TASKS.md` 时再传 `includeFullDocs=true`。 - 多项目联动时先调用 `kt_inspect_all_projects`。 - 要收尾时调用 `kt_finish_task`,默认只生成计划和 review;需要执行验证时显式传 `runValidation=true`。 -- 文件改动完成并验证后调用 `kt_global_code_review`,或运行 `pnpm run global-review`;它只读扫描,不删除文件、不提交代码。 +- 文件改动完成并验证后调用 `kt_global_code_review`,或运行 `pnpm run global-review`;它只读扫描,不删除文件、不提交代码。`findings` 先判定真实风险或工具误报,真实风险修业务代码,误报修 `mcp/ktWorkflow/src/tools/review.ts` 并复跑。 - 要提交或推送时先调用 `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_remote_health_check`,默认只生成只读命令;需要执行时显式传 `execute=true`。 - 数据库同步前调用 `kt_db_sync_plan`,先确认源库、目标库、备份库和校验点。 -- 改 KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger 前调用 `kt_component_workflow`,先看专项禁区。 +- 改 KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s 前调用 `kt_component_workflow`,先看专项禁区。 - 不确定任务边界时调用 `kt_guardrails`,先拿到“能做什么、不能做什么、怎么验证”。 - 验证前调用 `kt_suggest_verification`,避免盲跑全量构建。 - 页面测试前调用 `kt_create_page_test_case`,再执行 Playwright/浏览器测试。 diff --git a/package.json b/package.json index 076ecc8..a772a1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kt/mcp-kt-workflow", - "version": "0.6.0", + "version": "0.6.1", "private": true, "type": "module", "description": "Reusable MCP workflow tools for the KT workspace.", diff --git a/src/registerTools.ts b/src/registerTools.ts index 9872a7d..4d1b2b7 100644 --- a/src/registerTools.ts +++ b/src/registerTools.ts @@ -324,13 +324,14 @@ export function registerTools(server: McpServer): void { server.registerTool( 'kt_component_workflow', { - description: '按 KT 专项组件/链路输出防踩坑工作流:KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger。', + description: '按 KT 专项组件/链路输出防踩坑工作流:KtTable、BlogArgon、AdminAuth、QQBot、FF14Plugin、NapCatLogin、SystemLog、Knife4jSwagger、FnosK8s。', inputSchema: { target: z .enum([ 'AdminAuth', 'BlogArgon', 'FF14Plugin', + 'FnosK8s', 'Knife4jSwagger', 'KtTable', 'NapCatLogin', diff --git a/src/selfTest.ts b/src/selfTest.ts index 3cca7dc..eb07a3c 100644 --- a/src/selfTest.ts +++ b/src/selfTest.ts @@ -7,11 +7,19 @@ import { buildGuardrails } from './tools/guardrails.js'; import { cleanupHistoryArtifacts } from './tools/cleanup.js'; import { inspectProject } from './tools/inspect.js'; import { prepareTask, readWorkflowContext } from './tools/task.js'; -import { buildGlobalCodeReview } from './tools/review.js'; +import { buildGlobalCodeReview, isBenignCredentialReviewValue } from './tools/review.js'; import { buildBusinessTestPlan } from './tools/testing.js'; import { buildVerificationPlan } from './tools/verification.js'; import { buildCommitPlan, buildComponentWorkflow, buildDbSyncPlan, buildFinishTask, buildPushPlan, buildRemoteHealthCheck } from './tools/workflow.js'; export async function runSelfTest(): Promise { + const reviewClassifier = { + localizedSecretLabelAllowed: isBenignCredentialReviewValue('密钥'), + realTokenRejected: !isBenignCredentialReviewValue('eqc2Sbp8ufP2AcS6I2YReLqxnu3XJKC6D7C6PUcx'), + }; + if (!reviewClassifier.localizedSecretLabelAllowed || !reviewClassifier.realTokenRejected) { + throw new Error('review credential classifier self-check failed'); + } + const data = { context: readWorkflowContext({ taskRecordCount: 2 }), guardrails: buildGuardrails({ @@ -37,6 +45,7 @@ export async function runSelfTest(): Promise { maxFindingsPerProject: 10, projects: ['mcp'], }), + reviewClassifier, businessTestPlan: buildBusinessTestPlan({ flow: 'system-log-visualization', }), diff --git a/src/server.ts b/src/server.ts index a9b0474..2d4a13e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -25,7 +25,7 @@ if (process.argv.includes('--cleanup-history')) { } else { const server = new McpServer({ name: 'kt-workflow', - version: '0.4.0', + version: '0.6.1', }); registerTools(server); await server.connect(new StdioServerTransport()); diff --git a/src/tools/guardrails.ts b/src/tools/guardrails.ts index 45478be..bc446e9 100644 --- a/src/tools/guardrails.ts +++ b/src/tools/guardrails.ts @@ -39,7 +39,7 @@ export function buildGuardrails(input: GuardrailsInput): GuardrailsResult { } guardrails.verification.notes.push( - '改动后的 review 是硬步骤,优先用 kt_global_code_review 或 pnpm run global-review。', + '改动后的 review 是硬步骤,优先用 kt_global_code_review 或 pnpm run global-review;findings 先判定真实风险或误报,误报应修 ktWorkflow 规则。', ); if (taskType === 'page' || input.includePageTest) { diff --git a/src/tools/review.ts b/src/tools/review.ts index 9a9f91c..d1f0acc 100644 --- a/src/tools/review.ts +++ b/src/tools/review.ts @@ -112,6 +112,7 @@ function isBenignCredentialValue(value: string): boolean { if (normalized.startsWith('$') || normalized.startsWith('${')) return true; if (normalized.startsWith('<') || normalized.includes('example')) return true; if (/^\*+$/.test(normalized)) return true; + if (isLocalizedDisplayLabelValue(normalized)) return true; return [ 'false', 'hidden', @@ -129,6 +130,18 @@ function isBenignCredentialValue(value: string): boolean { ].includes(normalized); } +export function isBenignCredentialReviewValue(value: string): boolean { + return isBenignCredentialValue(value); +} + +function isLocalizedDisplayLabelValue(value: string): boolean { + return ( + value.length <= 24 && + /[\u3400-\u9fff]/.test(value) && + !/[a-z0-9_$./\\:=]/i.test(value) + ); +} + function isRuntimeDebugAllowed(projectAlias: ProjectAlias | null, file: string): boolean { const normalized = file.replaceAll('\\', '/'); if (/^(README|skills\/|.*\.md$)/.test(normalized)) return true; @@ -401,7 +414,7 @@ export async function buildGlobalCodeReview( notes: [ '本工具只读扫描,不会修改文件、删除文件或提交代码。', 'P1 优先处理:冲突标记、被跟踪的真实 env/部署凭据文件。', - '默认 contentScanMode=changed,只对当前变更文件做 P2/P3 内容扫描,避免历史误报污染上下文;需要全仓库深扫时传 all。', + '默认 contentScanMode=changed,只对当前变更文件做 P2/P3 内容扫描,并放过短中文显示标签,避免历史误报污染上下文;需要全仓库深扫时传 all。', 'P2 需要人工确认:疑似凭据字面量、旧部署文件、调试断点。', 'P3 为清洁度问题:运行时 console.log 等。', ], diff --git a/src/tools/task.ts b/src/tools/task.ts index e630a1a..865e87a 100644 --- a/src/tools/task.ts +++ b/src/tools/task.ts @@ -38,7 +38,7 @@ export async function prepareTask(input: PrepareTaskInput): Promise>; diff --git a/src/types.ts b/src/types.ts index 2938028..d753b66 100644 --- a/src/types.ts +++ b/src/types.ts @@ -194,6 +194,7 @@ export interface ComponentWorkflowInput { | 'AdminAuth' | 'BlogArgon' | 'FF14Plugin' + | 'FnosK8s' | 'Knife4jSwagger' | 'KtTable' | 'NapCatLogin'