{
  "tasks": [
    {
      "id": "task-001",
      "title": "修复 ConnectionPoolManager 定时器泄漏",
      "phase": 1,
      "priority": "P0",
      "status": "completed",
      "depends_on": [],
      "files": ["src/pools/pool.ts"],
      "description": "在 ConnectionPoolManager 中添加 healthCheckInterval 和 cleanupInterval 属性，保存 setInterval 返回值，在 destroy() 中清理定时器",
      "reviewer": "reviewer",
      "reviewer_notes": "[P3] src/pools/pool.ts:130 — 注释'定时器引用 - 用于清理'仅说明目的，建议补充防止进程阻塞的意图（结合 .unref() 说明）"
    },
    {
      "id": "task-002",
      "title": "修复 createGrpcConfig 中 channelOptions 赋值错误",
      "phase": 1,
      "priority": "P0",
      "status": "completed",
      "depends_on": [],
      "files": ["src/config/config.ts"],
      "description": "将 channelOptions: options.connectionPool || {} 修改为 channelOptions: options.channelOptions || {}",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — 单行精准修复，正确将 options.connectionPool 改为 options.channelOptions，消除了 gRPC channelOptions 被错误替换为连接池配置的 bug"
    },
    {
      "id": "task-003",
      "title": "修复 BaseServer 构造函数时序 - 移除自动初始化",
      "phase": 1,
      "priority": "P0",
      "status": "completed",
      "depends_on": [],
      "files": ["src/server/base.ts"],
      "description": "在 BaseServer 构造函数中移除 this.initializeServer() 调用，让子类手动调用",
      "reviewer": "orchestrator",
      "reviewer_notes": "配合 task-004 完成，子类已添加手动调用"
    },
    {
      "id": "task-004",
      "title": "修复所有子类构造函数时序 - 手动初始化",
      "phase": 1,
      "priority": "P0",
      "status": "completed",
      "depends_on": ["task-003"],
      "files": ["src/server/http.ts", "src/server/https.ts", "src/server/http2.ts", "src/server/http3.ts", "src/server/grpc.ts", "src/server/ws.ts"],
      "description": "在所有子类构造函数中，配置处理后手动调用 this.initializeServer()",
      "reviewer": "orchestrator",
      "reviewer_notes": "6 个子类已添加 this.initializeServer() 调用"
    },
    {
      "id": "task-005",
      "title": "统一关闭路径 - 移除 terminus.ts 重复信号逻辑",
      "phase": 1,
      "priority": "P0",
      "status": "completed",
      "depends_on": [],
      "files": ["src/utils/terminus.ts"],
      "description": "移除 signalHandlers Map，简化 onSignal 函数，不再触发 appStop 和 process.exit",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — 信号处理逻辑已成功委托给 TerminusManager 单例，process.setMaxListeners(0) 已删除。[P3] src/utils/terminus.ts:19 — TerminusOptions.onSignal 字段已无任何调用方使用（task-005 移除了对应逻辑），属于废弃死接口；建议删除该字段或将整个 TerminusOptions 标记 @deprecated"
    },
    {
      "id": "task-006",
      "title": "统一关闭路径 - 调整 TerminusManager",
      "phase": 1,
      "priority": "P0",
      "status": "rejected",
      "depends_on": ["task-005"],
      "files": ["src/utils/terminus-manager.ts"],
      "description": "修改 shutdownAll 方法，移除直接调用 server.destroy()，仅触发 appStop 事件",
      "reviewer": "reviewer",
      "reviewer_notes": "[P1] src/utils/terminus-manager.ts:129 — asyncEvent(process, 'beforeExit') 调用会通过 removeAllListeners 永久删除 Node.js process 上所有 beforeExit 监听器；若应用其他模块（或第三方库）注册了 beforeExit 钩子，将被静默移除，导致清理逻辑失效；应改为仅触发监听器而不移除，如 process.listeners('beforeExit').forEach(fn => fn()) 或去掉这一整行（appStop 已足够）。[P2] src/utils/terminus-manager.ts:35 — this.servers Map 通过 registerServer 填充，但 shutdownAll 中从未遍历该 Map，注册的 server 引用完全不参与关闭流程，属于死代码；建议删除 servers Map 与 getServerCount()，或补充对应使用逻辑。[P2] src/utils/terminus-manager.ts:154-159 — resetInstance() 将 signalsRegistered 重置为 false 后再置 instance=null，下次 getInstance() 会再次调用 setupSignalHandlers() 注册新的 process 信号监听器，但旧实例（通过闭包被信号 handler 持有）不会被 GC，形成信号 handler 累积泄漏；建议在 resetInstance 中显式移除已注册的 process 信号监听器（需持久化 handler 引用）"
    },
    {
      "id": "task-007",
      "title": "移除 process.setMaxListeners(0)",
      "phase": 1,
      "priority": "P0",
      "status": "completed",
      "depends_on": ["task-005", "task-006"],
      "files": ["src/utils/terminus.ts"],
      "description": "删除 process.setMaxListeners(0) 及其注释",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — 已在 task-005 中完成，terminus.ts 中确认无 process.setMaxListeners 调用"
    },
    {
      "id": "task-008",
      "title": "修复 ConnectionPoolFactory 缓存键不稳定",
      "phase": 2,
      "priority": "P1",
      "status": "completed",
      "depends_on": [],
      "files": ["src/pools/factory.ts"],
      "description": "添加 stableStringify 辅助函数，确保相同配置不同键顺序产生相同缓存键",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — stableStringify 正确对对象键排序，相同配置不同键序产生相同键值，满足缓存稳定性要求。[P3] src/pools/factory.ts:24 — 数组元素经 stableStringify 后再外套 JSON.stringify，导致 [{a:1}] 序列化为 [\"{\\"a\\":1}\"] 而非 [{\"a\":1}]；对缓存功能无影响（相同输入产生相同输出），但输出非标准 JSON 可能造成调试困惑；建议改为 '[' + obj.map(i => stableStringify(i)).join(',') + ']'"
    },
    {
      "id": "task-009",
      "title": "修复 errorRate 只增不减",
      "phase": 2,
      "priority": "P1",
      "status": "completed",
      "depends_on": ["task-001"],
      "files": ["src/pools/pool.ts"],
      "description": "使用 RingBuffer 滑动窗口计算错误率，替代只增不减的逻辑",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — errorWindow RingBuffer(500) 正确实现滑动窗口，recordConnectionEvent 对 'added' 推入 false、对 'error' 推入 true，calculateErrorRate 基于窗口内比例计算，错误率可随时间自然衰减"
    },
    {
      "id": "task-010",
      "title": "修复 gRPC RegisterService 硬编码超时",
      "phase": 2,
      "priority": "P1",
      "status": "completed",
      "depends_on": [],
      "files": ["src/server/grpc.ts"],
      "description": "将硬编码的 30000ms 超时改为从配置读取：this.options.connectionPool?.requestTimeout || 30000",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — src/server/grpc.ts:679 中 const timeoutMs = this.options.connectionPool?.requestTimeout || 30000 正确从配置读取，默认值 30000 保持向后兼容"
    },
    {
      "id": "task-011",
      "title": "移除 HttpConnectionPoolManager 重复清理任务",
      "phase": 2,
      "priority": "P1",
      "status": "completed",
      "depends_on": ["task-001"],
      "files": ["src/pools/http.ts"],
      "description": "移除 httpCleanupInterval、startCleanupTasks() 和 cleanupIdleConnections()，使用父类逻辑",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — httpCleanupInterval/startCleanupTasks/cleanupIdleConnections 已全部移除，清理由父类 ConnectionPoolManager.startPeriodicTasks() 统一处理。[P2] src/pools/http.ts:149 和 :332 — setupConnectionEventHandlers（私有，由 addHttpConnection 调用）与 setupProtocolSpecificHandlers（受保护，由 registerConnection 调用）对同一 Socket 注册了功能高度重叠的 close/error/timeout 处理器，属于代码重复；若两者均被调用则导致重复绑定；建议统一为一个入口或明确互斥调用路径"
    },
    {
      "id": "task-012",
      "title": "修复 startTime falsy 判断",
      "phase": 3,
      "priority": "P2",
      "status": "completed",
      "depends_on": [],
      "files": ["src/server/serve.ts"],
      "description": "将 || 改为 ?? 运算符，正确处理 startTime 为 0 的情况",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — src/server/serve.ts:292 已改为 (this.serverInstance as any)?.startTime ?? Date.now()，?? 运算符正确处理 startTime === 0 的边界情况，uptime 不再永远为 0"
    },
    {
      "id": "task-013",
      "title": "提取 ConfigHelper 公共 SSL 迁移逻辑",
      "phase": 3,
      "priority": "P2",
      "status": "completed",
      "depends_on": [],
      "files": ["src/config/config.ts"],
      "description": "添加 migrateSSLFromExt 私有静态方法，在 5 个 createXxxConfig 方法中复用",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — migrateSSLFromExt 私有静态方法已在 createHttpsConfig/createHttp2Config/createGrpcConfig/createHttp3Config/createWebSocketConfig 5 处复用，符合 DRY 原则，减少约 50 行重复代码"
    },
    {
      "id": "task-014",
      "title": "消除 GraphQL 协议处理重复",
      "phase": 3,
      "priority": "P2",
      "status": "completed",
      "depends_on": [],
      "files": ["src/server/serve.ts"],
      "description": "移除 initializeServerInstance 中的 GraphQL _underlyingProtocol 设置，保留 createServerInstance 中的逻辑",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — initializeServerInstance 中不再设置 _underlyingProtocol，该逻辑集中在 createServerInstance（serve.ts:461-472），消除了重复赋值，符合单一职责原则"
    },
    {
      "id": "task-015",
      "title": "精简 gRPC RegisterService 日志",
      "phase": 3,
      "priority": "P2",
      "status": "completed",
      "depends_on": [],
      "files": ["src/server/grpc.ts"],
      "description": "移除所有 [GRPC_SERVER] 前缀的 debug 日志，保留关键日志",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — RegisterService 中已无 [GRPC_SERVER] 前缀冗余 debug 日志，保留了服务注册、方法调用、错误和超时等关键日志，信噪比合理"
    },
    {
      "id": "task-016",
      "title": "优化 waitingQueue 插入排序",
      "phase": 3,
      "priority": "P2",
      "status": "completed",
      "depends_on": [],
      "files": ["src/pools/pool.ts"],
      "description": "使用有序插入替代全量排序，将 O(n log n) 降为 O(n)",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — src/pools/pool.ts:319-331 采用线性扫描找到第一个优先级低于新项目的位置后 splice 插入，算法正确：相同优先级维持 FIFO（新 normal 插入到最后一个 normal 之后），高优先级正确排在低优先级前面；时间复杂度 O(n) 优于原全量排序 O(n log n)"
    },
    {
      "id": "task-017",
      "title": "添加证书路径安全检查",
      "phase": 3,
      "priority": "P2",
      "status": "completed",
      "depends_on": [],
      "files": ["src/utils/cert-loader.ts"],
      "description": "添加 sanitizeCertPath 函数，防止路径遍历攻击",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — sanitizeCertPath 正确检测空字节注入和 '..' 路径段遍历，并通过 path.resolve() 返回绝对路径；对于来自应用配置的证书路径，该防护级别合理。[P3] src/utils/cert-loader.ts:37 — path.resolve() 后未校验解析路径是否在允许的目录范围内（如应用根目录下的 certs/）；若证书路径源头为用户输入（而非配置文件），攻击者可直接提供 /etc/passwd 绕过遍历检测；建议在高风险场景下添加 allowedBaseDirs 白名单校验"
    },
    {
      "id": "task-018",
      "title": "为 process.exit 添加可配置开关",
      "phase": 4,
      "priority": "P2",
      "status": "completed",
      "depends_on": ["task-006"],
      "files": ["src/utils/terminus-manager.ts"],
      "description": "添加 exitOnShutdown 配置属性和 setExitOnShutdown 方法，使 process.exit 可配置",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — exitOnShutdown 默认 true，通过 setExitOnShutdown() 可配置，向后兼容；关闭成功调用 exit(0)、失败调用 exit(1) 逻辑清晰。[P3] src/utils/terminus-manager.ts:119-133 — timeoutHandle 使用 let 声明但未初始化（let timeoutHandle: NodeJS.Timeout），在 finally 块中使用非空断言 clearTimeout(timeoutHandle!) 绕过 TS 检查；实际不会出现未定义问题（Promise 构造函数同步执行），但建议使用 let timeoutHandle: NodeJS.Timeout | undefined 并改为 if (timeoutHandle) clearTimeout(timeoutHandle) 消除断言"
    },
    {
      "id": "task-019",
      "title": "BaseServer.server 类型改进",
      "phase": 4,
      "priority": "P3",
      "status": "completed",
      "depends_on": ["task-004"],
      "files": ["src/server/base.ts", "src/server/http.ts", "src/server/https.ts", "src/server/http2.ts", "src/server/http3.ts", "src/server/grpc.ts", "src/server/ws.ts"],
      "description": "修改 BaseServer 泛型签名，各子类指定具体服务器类型",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — BaseServer<T, S> 泛型声明正确，GrpcServer extends BaseServer<GrpcServerOptions, Server> 等子类类型具体化符合设计意图。[P2] src/server/base.ts:58 和各子类 createProtocolServer — readonly server!: S 声明后，子类通过 (this as any).server = new Server(...) 的类型断言赋值，绕过了 TypeScript readonly 约束，类型安全意图落空；建议改为 protected server!: S（去掉 readonly）并让 createProtocolServer 直接赋值 this.server = ...，或使用受保护的初始化方法"
    },
    {
      "id": "task-020",
      "title": "ConnectionPoolManager 事件类型安全",
      "phase": 4,
      "priority": "P3",
      "status": "completed",
      "depends_on": ["task-009"],
      "files": ["src/pools/pool.ts"],
      "description": "定义 ConnectionPoolEventMap 类型映射，修改事件方法签名为泛型",
      "reviewer": "reviewer",
      "reviewer_notes": "pass — ConnectionPoolEventMap 类型映射完整定义了 6 个事件的数据结构，on<E>/off<E> 泛型方法在订阅侧提供编译时类型检查。[P3] src/pools/pool.ts:750 — emitEvent(event: ConnectionPoolEvent, data: any) 的 data 参数未使用 ConnectionPoolEventMap 约束，发布侧缺少类型检查，可传入任意数据而不报错；建议改为 emitEvent<E extends ConnectionPoolEvent>(event: E, data: ConnectionPoolEventMap[E])"
    },
    {
      "id": "task-021",
      "title": "完整回归测试",
      "phase": 5,
      "priority": "回归",
      "status": "review_pending",
      "depends_on": ["task-001", "task-002", "task-003", "task-004", "task-005", "task-006", "task-007", "task-008", "task-009", "task-010", "task-011", "task-012", "task-013", "task-014", "task-015", "task-016", "task-017", "task-018", "task-019", "task-020"],
      "files": [],
      "description": "运行全量测试、构建、lint，确保所有修改不破坏现有功能",
      "reviewer": "orchestrator",
      "reviewer_notes": "752 passed, 1 failed（预先存在）, 23 skipped | 构建成功 | Lint: 0 errors, 6 warnings（预先存在）"
    }
  ]
}
