tasks.md 18 KB

任务拆分 — Forge AI 中枢能力底座

变更名:forge-ai-hub-foundation 执行原则:HARD-GATE Spike → 协议无关契约 → Registry → 静态能力 → MCP 适配 → 身份与目录验证 → UI 收敛 → 全量验证 每个任务先写 Red 测试,再写最小实现;禁止自动 commit/push

前置条件

  • 用户明确执行 /apply forge-ai-hub-foundation
  • 完整读取本变更 spec.mdtasks.mdtest-spec.mdexecution-log.md
  • code-copilot/rules/automated-testing-standard.md 复用历史验证基线;
  • 保持 Spring AI 1.1.2、Spring AI Alibaba 1.1.2.3、Java 17 和 Spring Boot 3.5.13 基线;
  • 不覆盖当前工作区中用户已有的 AI 路由、供应商、前端和归档改动;
  • 不新增 Nacos、数据库表、高风险工具、Agent Framework 或 SSE transport。

Review Fix 结果

  • 新增启动期协议硬闸门,MCP enabled 时只接受 STREAMABLE,拒绝 SSESTATELESS 和 stdio;
  • 新增 /mcp 身份过滤器,身份缺失/解析失败在进入 SDK 前返回 HTTP 401,并统一传播 requestId;
  • 授权策略返回结构化决策,调用链可区分未认证、禁止、跨租户和跨组织错误码;
  • 游标绑定快照、查询条件与调用方,并使用进程内 HMAC-SHA256 签名,拒绝位置篡改、跨查询复用和不可见能力游标;
  • MCP Schema Projector 只接受 ValidatedCapabilitySchema,补齐关键字/类型组合、边界和 enum 类型一致性校验;
  • 增加失败关闭安全审计日志,且不记录 arguments、data、Header、Token 或 Throwable;
  • 补齐协议覆盖、HTTP 401、requestId 传播、未知工具、静态发布闸门及授权/游标/Schema P0 测试。

Archive 结果

  • 用户明确执行归档,四份变更文档状态和验证证据一致;
  • AI 中枢路线图更新为阶段 0 已完成,并保留 SDK 动态 tools/list 限制;
  • Streamable HTTP、能力内核安全边界和可复用踩坑沉淀到长期记忆;
  • 归档目标为 code-copilot/changes/archive/2026-07-11-forge-ai-hub-foundation/

Task 1: 完成 MCP Streamable HTTP 依赖与装配 Spike(HARD-GATE)

  • 目标:在不实现能力业务的前提下,证明 WebMVC Streamable HTTP starter 能与 Forge Admin/Undertow 共存且不会装配旧 SSE。
  • 涉及文件
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-mcp/pom.xml — 新建最小 MCP 插件,只引入 WebMVC MCP Server starter 与测试依赖;
    • forge-server/forge-framework/forge-plugin-parent/pom.xml — 临时/正式聚合新模块;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-mcp/src/test/java/com/mdframe/forge/plugin/mcp/McpStreamableTransportCompatibilityTest.java — 最小 ApplicationContext 装配测试;
    • code-copilot/changes/forge-ai-hub-foundation/execution-log.md — 记录依赖树、Bean、端点和失败证据;
    • docs/Forge-AI中枢落地架构与阶段路线图.md — 回填经过验证的 transport ADR 结论。
  • 关键断言java assertThat(context).hasSingleBean(WebMvcStreamableServerTransportProvider.class); assertThat(context).doesNotHaveBean(WebMvcSseServerTransportProvider.class);
  • Red/Green 步骤
    • 先写装配测试,缺少模块/starter 时 testCompile 或 Context 启动 Red;
    • 只加入 org.springframework.ai:spring-ai-starter-mcp-server-webmvc,显式配置 protocol=STREAMABLEstdio=falsemcp-endpoint=/mcp
    • 执行 mvn -pl forge-framework/forge-plugin-parent/forge-plugin-mcp -am dependency:tree -Dincludes=org.springframework.ai,io.modelcontextprotocol.sdk,org.springframework.boot
    • 断言只存在 Streamable transport provider,不存在 SSE provider/route;
    • 用测试客户端完成 initialize,验证协商协议版本和 /mcp 单端点;
    • 运行 Admin 最小装配,确认 WebApplicationType 与 Undertow 未变化;
    • 失败时停止 Task 2–8,记录升级/独立进程隔离方案,禁止切回 SSE。
  • 验收标准:HARD-GATE 六项全部有命令和断言证据;依赖树无版本冲突;旧 SSE Bean 与端点均不存在。

Task 2: 创建 forge-plugin-capability 与核心契约

  • 目标:建立完全协议无关的能力定义、调用、结果、执行器和来源接口。
  • 涉及文件
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/pom.xml — 新模块,只依赖 forge-starter-core 与必要 JSON 类型;
    • forge-server/forge-framework/forge-plugin-parent/pom.xml — 聚合 capability 模块;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/model/CapabilityDefinition.java — 定义 code/toolName/version/behavior/risk/schema;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/model/CapabilityInvocation.javaCapabilityCallerContext.javaCapabilityResult.java — 不可变调用契约;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/spi/CapabilityExecutor.javaCapabilitySource.javaCapabilityAuthorizationPolicy.java — 执行、来源和授权 SPI。
  • 关键签名: ```java public interface CapabilityExecutor { boolean supports(CapabilityDefinition definition); CapabilityResult invoke( CapabilityDefinition definition, CapabilityInvocation invocation); }

public interface CapabilitySource {

  Collection<CapabilityDefinition> load(CapabilityQuery query);

}

- **Red/Green 步骤**:
  - [x] 编写架构 Red 测试,扫描 capability 模块不得引用 `org.springframework.ai`、`io.modelcontextprotocol`、`forge.plugin.ai`;
  - [x] 编写 record 构造校验测试:必填、不可变 scopes、duration 非负、安全 errorCode;
  - [x] 实现 `CapabilityBehavior`、`CapabilityRiskLevel`、`CapabilityResultStatus` 和稳定错误码;
  - [x] 明确 `JsonNode` 只表示 JSON 契约,不引入 MCP Schema;
  - [x] 执行 capability 模块测试 Green 和 `jdeps/rg` 禁止依赖扫描。
- **验收标准**:核心类型可被 MCP 之外的调用方独立使用;无 Spring AI/MCP/AI 插件依赖;调用结果不包含 Throwable。

## Task 3: 实现名称、Schema 校验和 MCP 公共子集投影

- **目标**:让能力在注册前拥有稳定名称和可验证的 Draft 2020-12 输入输出契约。
- **涉及文件**:
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/naming/CapabilityToolNameMapper.java` — code 与 toolName 恒等映射及格式校验;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/schema/CapabilitySchemaValidator.java` — Draft 2020-12 公共子集校验;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/exception/CapabilityDefinitionException.java` — 带安全路径和错误码的定义异常;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/test/java/com/mdframe/forge/plugin/capability/naming/CapabilityToolNameMapperTest.java`;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/test/java/com/mdframe/forge/plugin/capability/schema/CapabilitySchemaValidatorTest.java`。
- **关键签名**:
  ```java
  public String toProtocolToolName(String capabilityCode) { }

  public ValidatedCapabilitySchema validate(
      JsonNode inputSchema,
      JsonNode outputSchema) { }
  • Red/Green 步骤
    • Red 覆盖合法点分编码、非法字符、空分段、大写、首字符数字、129 字符和恒等稳定性;
    • Red 覆盖重复 toolName 冲突,禁止截断/替换产生碰撞;
    • Red 覆盖 $schema、required、additionalProperties=false、enum、nested object、array/items、nullable 联合类型;
    • $ref、递归/条件/动态关键字和无法投影的 nullable 明确失败,异常指出 JSON path;
    • forge-plugin-mcp 增加 McpToolSchemaProjector 时只消费 ValidatedCapabilitySchema,不得重新猜测语义;
    • 运行名称与 Schema 测试 Green。
  • 验收标准:相同定义跨进程得到相同名称与 Schema;不支持语义不会被静默删除。

Task 4: 实现内存 Registry、过滤与稳定游标

  • 目标:聚合静态来源形成不可变能力快照,并提供与协议无关的授权发现和调用入口。
  • 涉及文件
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/registry/CapabilityRegistry.javaInMemoryCapabilityRegistry.java
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/registry/CapabilityRegistryFactory.java — 启动期聚合并校验 Source/Executor;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/model/CapabilityQuery.javaCapabilityPage.javaCapabilityCursor.java
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/registry/CapabilityInvoker.java — 输入/输出校验、requestId 与安全结果;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/test/java/com/mdframe/forge/plugin/capability/registry/InMemoryCapabilityRegistryTest.java
  • 关键签名: ```java public CapabilityPage list( CapabilityQuery query, CapabilityCallerContext caller) { }

public CapabilityResult invoke(CapabilityInvocation invocation) { }

- **Red/Green 步骤**:
  - [x] Red 覆盖重复 code+version、重复 toolName、缺 Executor、无效 Schema 启动失败;
  - [x] Red 覆盖 `canDiscover` 和 `canInvoke` 分离,未授权项不出现在内核列表且不能调用;
  - [x] Red 覆盖排序 `toolName/version`、pageSize 边界、nextCursor、非法/过期/跨快照游标;
  - [x] Red 覆盖无 caller、跨租户、跨组织和缺 scope 失败关闭;
  - [x] 使用不可变 Map/List 快照,禁止调用期间修改全局工具集合;
  - [x] 输入校验后执行、输出校验后返回;异常转安全错误,不返回原始 Throwable message;
  - [x] 运行 Registry 并发与确定性测试 Green。
- **验收标准**:相同快照与 query 得到稳定分页;发现和执行均按 caller 过滤;注册冲突不会后写覆盖。

## Task 5: 注册并验证静态 `capability.ping`

- **目标**:用无业务依赖的只读能力打通 Registry 执行闭环。
- **涉及文件**:
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/builtin/PingCapabilitySource.java` — 提供 `capability.ping@1.0.0` 定义;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/builtin/PingCapabilityExecutor.java` — 返回固定状态、requestId、Clock 时间;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/main/java/com/mdframe/forge/plugin/capability/config/CapabilityAutoConfiguration.java` — 聚合 Source/Executor 构建 Registry;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/test/java/com/mdframe/forge/plugin/capability/builtin/PingCapabilityExecutorTest.java`;
  - `forge-server/forge-framework/forge-plugin-parent/forge-plugin-capability/src/test/java/com/mdframe/forge/plugin/capability/config/CapabilityAutoConfigurationTest.java`。
- **关键签名**:
  ```java
  public CapabilityResult invoke(
      CapabilityDefinition definition,
      CapabilityInvocation invocation) { }
  • Red/Green 步骤
    • Red 断言输入只允许空 object,任意额外字段为 INVALID_ARGUMENT;
    • Red 断言输出只含 status/requestId/serverTime,requestId 原样关联;
    • 注入 Clock,禁止测试 sleep;
    • 使用依赖/Bean 断言证明 Executor 不访问 DataSource、Redis、WebClient、ChatModel、文件系统;
    • 自动配置重复定义或无 Executor 时启动失败;
    • 运行 capability 模块完整测试 Green。
  • 验收标准:ping 无网络、数据库、模型和文件副作用;结果可复现且不回显客户端数据。

Task 6: 实现 MCP 适配、可信身份与动态目录 Spike

  • 目标:通过 Streamable HTTP 暴露 ping,并如实验证当前 SDK 的身份传递、动态工具目录和分页能力。
  • 涉及文件
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-mcp/src/main/java/com/mdframe/forge/plugin/mcp/config/ForgeMcpServerConfiguration.java — 仅 Streamable WebMVC 配置;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-mcp/src/main/java/com/mdframe/forge/plugin/mcp/security/McpCallerContextResolver.javaMcpTransportContextExtractor.java — 可信主体到 caller context;
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-mcp/src/main/java/com/mdframe/forge/plugin/mcp/adapter/McpCapabilityAdapter.javaMcpToolSchemaProjector.javaMcpCapabilityResultMapper.java
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-mcp/src/test/java/com/mdframe/forge/plugin/mcp/McpStreamableProtocolIntegrationTest.java
    • forge-server/forge-framework/forge-plugin-parent/forge-plugin-mcp/src/test/java/com/mdframe/forge/plugin/mcp/security/McpCallerContextIsolationTest.java
  • 关键签名: ```java public interface McpCallerContextResolver { CapabilityCallerContext resolve(McpTransportContext context); }

public McpSchema.CallToolResult call(

  McpSyncServerExchange exchange,
  McpSchema.CallToolRequest request) { }

```

  • Red/Green 步骤
    • 先写 Streamable HTTP initialize/list/call Red 集成测试;
    • contextExtractor 只携带已验证主体,不信任裸 X-Tenant-Id/X-User-Id;测试 Resolver 只放 test scope;
    • 无 Resolver、无身份、跨租户/组织、arguments 伪造身份字段全部失败关闭;
    • tools/call 每次重新检查 canInvoke,并映射安全 requestId/errorCode/isError;
    • 检查 SDK 公开扩展点能否按 exchange 调用 Registry.list 并设置 nextCursor;禁止反射和全局 add/remove 竞态方案;
    • 若仍是 SDK 0.17 静态列表,记录“仅 ping 可发布”的强制限制,并增加测试阻止第二个差异授权工具注册到 MCP;
    • 执行禁止 SSE Bean/端点/config 扫描。
  • 验收标准/mcp 完成三段协议闭环,身份不可伪造;动态目录能力与限制都有可执行证据,不虚报支持。

Task 7: 接入 Admin 并收敛 Agent 页面预留项

  • 目标:只在 Admin 服务可控启用 MCP,并移除前端尚未实现的高风险工具假象。
  • 涉及文件
    • forge-server/forge-framework/forge-dependencies/pom.xml — 管理两个 Forge 插件依赖版本;
    • forge-server/forge-admin-server/pom.xml — 仅 Admin 聚合 forge-plugin-mcp
    • forge-server/forge-admin-server/src/main/resources/application.ymlapplication-dev.example.yml — 默认关闭并显式 STREAMABLE;
    • forge-admin-ui/src/views/ai/agent.vue — 隐藏硬编码高风险 MCP 选项或显示只读预留提示;
    • forge-server/forge-admin-server/src/test/java/com/mdframe/forge/admin/ForgeMcpAdminAssemblyTest.java — 默认禁用/显式启用装配测试。
  • 实施步骤
    • Red 断言 Admin 默认无 /mcp,启用但缺 Resolver 时启动失败;
    • 显式启用 + test Resolver 时只出现 /mcp,Flow/Report/App 不因 AI 插件依赖被动出现端点;
    • 配置示例不包含真实 Token、client secret 或可信 Header 旁路;
    • Agent 页面不再允许保存 database_query/http_request/file_reader/code_executor 等未实现值;历史值只读显示“预留/不可用”,不自动丢失或映射成 ping;
    • 执行目标 ESLint 与前端 build;不做额外 UI 重设计。
  • 验收标准:MCP 暴露范围只在 Admin 且默认关闭;页面不承诺不存在的工具;历史 extraConfig 不被静默改写。

Task 8: 完成自动化验证、ADR 与 Review 准备

  • 目标:形成可复跑的阶段 0 证据,并明确是否允许进入下一阶段。
  • 涉及文件
    • code-copilot/changes/forge-ai-hub-foundation/spec.mdtasks.mdtest-spec.mdexecution-log.md
    • docs/Forge-AI中枢战略与技术选型方案.md
    • docs/Forge-AI中枢落地架构与阶段路线图.md
    • code-copilot/memory/decisions.md
    • code-copilot/memory/pitfalls.md(只有产生可复用踩坑时更新)。
  • 实施步骤
    • 复跑 capability/mcp 定向测试并确认真实 Tests run;
    • 运行两个新插件 -am test/package 和 Admin -am package -DskipTests
    • 输出 dependency:tree 并检查 Spring AI/MCP SDK/Boot 单版本;
    • 扫描 SseServerTransportWebMvcSseServerTransportProvider/ssesse-message-endpoint、旧 SSE starter/config;
    • 扫描 Nacos MCP、AgentScope、数据库/HTTP/文件/代码执行工具和新增 Flyway,确保范围未漂移;
    • 执行前端目标 lint/build;
    • git diff --check,记录全部命令、输出摘要、警告、跳过项和服务清理;
    • 对照 Spec 先做 Compliance Review,再做 Code Quality Review;
    • 只有 transport、身份、Schema 和统一 ping 全部通过才允许阶段 0 标记完成;动态目录未完成时必须保留“禁止异构业务工具”的下一阶段闸门。
  • 验收标准:文档、代码和测试一致;没有 SSE/Nacos/高风险工具范围漂移;下一阶段允许项和阻断项清晰。