# AGENTS Changelog 多 agent 并行时的共享变更记录。开工前先读本文,避免重复实现或与已变更的接口冲突。 条目按时间倒序排列;破坏性变更(接口签名、协议字段等)会明确标注。 --- ## 2026-08-22 Node SSR 配置与 Nginx 双槽受控区块 ### 已完成 - `deploymentconfig.Config` 新增精确的 `nodeSsr` camel 表。 - Node SSR 仅接受 `container`,槽位固定为宿主端口 `18910`、`28910`。 - 槽位容器名固定为 `node-ssr-18910`、`node-ssr-28910`。 - 健康检查固定为 `http://127.0.0.1:18910/health` 与 `http://127.0.0.1:28910/health`。 - `hostnginx` 新增 Node SSR 受控 upstream 区块解析、活动端口读取和硬切换渲染: `# yms-update managed nodeSsr upstream begin/end`。 - Node SSR Nginx 逻辑入口端口为 `8910`;受控 upstream 后端为 `18910`、`28910`。 - Node SSR upstream 名称冻结为 `ssr`,受控标记为 `# yms-update managed ssr upstream begin/end`。 ### 尚未完成 - Node SSR 容器更新事务执行器、SQLite 部署记录、CLI `--service nodeSsr` 分派尚未实现。 - Node SSR updater 接入后,必须复用上述 Nginx 受控区块,并在健康检查通过后切换活动槽位。 - 执行器接入前,`nodeSsr` 表暂为可选;存在时严格校验,缺失时不影响现有 backend 配置启动。 ### 提交 - `83a1f05 feat: add node SSR dual-slot deployment config` - `a909ecf feat: add Node SSR Nginx upstream switching` - `3f6b1cb fix: keep Node SSR config optional during rollout` - `ed80e2b feat: add Node SSR deployment transaction record` - `40e3147 feat: extend container executor for Node SSR` ### 事务底座 - SQLite schema version 升至 3,新增 `node_ssr_container_deployment` 单例表。 - 新增 `NodeSsrContainerDeployment` 读写与原子提交方法,端口严格限制为 `18910/28910`。 - 通用容器执行器允许 Node SSR 使用 `PORT`、`/health`、18910/28910,并支持无配置文件与无 bind mount 的容器。 ### Sonar 清理 - Node SSR upstream 行解析拆分为单行解析函数,降低主解析函数复杂度。 - Node SSR 部署记录字段校验改为有序字段列表,避免 map 遍历顺序不稳定。 - 容器执行器的可选挂载路径校验提取为 `validateOptionalPathPair`,移除重复分支和单行嵌套判断。 - `go test ./...`、`go vet ./...`、`git diff --check` 通过。 - `d2070c9 refactor: simplify Node SSR parsing and validation` - `99082fd refactor: simplify optional container path validation` - `a81f81e refactor: split deployment configuration validation` - `3f13130 refactor: split container switch and commit steps` --- ## 2026-08-22 对账结果可见性 + 容器镜像 tag 展示 ### 诊断与对账输出 - `ymsctl status/doctor/reconcile` 的状态展示区分 `HEALTHY`、`REPAIRABLE`、`DRIFT`。 - `ymsctl reconcile --service backend` 明确标记为只读修复计划,并提示追加 `--apply`。 - `ymsctl reconcile --service backend --apply` 成功后输出 `APPLIED`、对账事务 ID 和重新核对结果。 - `daemonapi.Diagnosis` 新增 `RepairApplied`、`RepairTransactionID` 字段;自动修复完成后由服务端填充。 - 对账修复仍通过 SQLite 事务与 coordinator 执行,未改变只读命令的行为。 ### 容器镜像显示与校验 - 容器更新创建容器时使用用户提供的 tag 引用,使 `docker ps` / `docker inspect .Config.Image` 显示可读 tag。 - `backendexecutor.Request` 新增 `DisplayImageReference`,仅用于容器显示引用。 - 实际镜像仍使用不可变 digest 引用拉取、校验和事务记录;容器创建阶段继续校验镜像 ID,提交阶段同时接受 digest 引用或对应 tag 引用。 - 现有已创建容器不会被改写;下一次更新对应槽位后显示 tag。 ### 验证与产物 - `go test ./...`、`go vet ./...`、`git diff --check` 通过。 - 生成 x86_64 RPM:`dist/yms-daemon-0.1.0-20260822072334.f536987a.x86_64.rpm`。 - RPM SHA256:`a3df708e54a95dadbf67487b4cd25dfa7599557237241638d00f38d390cf581e`。 --- ## 2026-08-17 容器停止超时配置化 + 示例配置支持 native/container 快速切换 ### 新增配置项 - `deploymentconfig.Backend` 新增 `stop_grace_seconds *int`(`[backend]` 下,可省略)。 - 容器后端停止旧容器时,SIGTERM 后到强制终止前的等待秒数;省略时默认 30。 - 配置值覆盖容器创建时的 9000 秒 StopTimeout;原生后端忽略该字段。 - `validateExactDocumentKeys` 的 backend 允许键新增 `stop_grace_seconds`;`Validate` 要求其为正整数。 - `backendupdate.Updater` 新增 `containerStopGraceSeconds`,由 `NewContainer` 从配置读取(缺省 30)。 - `containerStopOperation` 新增 `stopGraceSeconds` 字段,`switchAndCommitContainer` 与 `rollbackContainer` 传 `u.containerStopGraceSeconds`。 ### 示例配置 - 重写 `packaging/etc/yms-daemon/yms-daemon.toml`:同时展示 native(默认启用)与 container(整体注释)两套 `[backend]` 块,顶部注释说明快速切换步骤与约束(type 必须与现场一致、native↔container 需走迁移事务)。 ### 测试 `deploymentconfig/config_test.go` 新增:`stop_grace_seconds` 合法值接受、非正整数拒绝。全量 build/vet/test 通过。 --- ## 2026-08-17 修复旧容器停不掉与启动日志跟随 ### 破坏性变更 `containerengine.Engine.StopContainer` 签名由 `StopContainer(context.Context, string) error` 改为 `StopContainer(context.Context, string, int) error`(新增超时秒数参数)。 ### 修复旧容器「kill 不掉」 - 根因:`MobyEngine.StopContainer` 用 `ContainerStopOptions{}`(不传超时),Docker 沿用容器创建时设置的 `StopTimeout=9000` 秒,Spring Boot 优雅停机长期不退时旧容器无法停止。 - `internal/containerengine/engine.go` / `moby.go`:`StopContainer` 增加 `timeoutSeconds`,`ContainerStop` 显式传 `Timeout`。 - `internal/backendupdate/container.go`:新增常量 `containerStopGraceSeconds = 30`,`containerStopOperation.Apply` 传入 30 秒,超时后 Docker 强制 SIGKILL。 ### 修复启动日志跟随 - 根因:`ContainerLogs` 用 `Follow:false` 一次性读快照(读于容器刚启动时,Spring Boot 尚未输出),且 `RestartContainer` 的 `StartLog` 为 false。 - `internal/containerengine/moby.go`:`ContainerLogs` 改为 `Follow:true` + `io.Pipe` 持续流式返回。 - `internal/backendexecutor/executor.go`:`startAndCheck` 改为后台 goroutine 跟随读日志(`streamContainerLogs`),健康检查结束后取消跟随。 - `internal/backendupdate/container.go`:`RestartContainer` 的 `StartLog` 改为 true。 ### 测试 三个测试 fake 的 `StopContainer` 签名同步更新。全量 build/vet/test 通过。 --- ## 2026-08-17 实现 container 后端 restart `ymsctl restart --service backend` 的 container 后端此前直接返回「restart is not implemented for container backend」,本次补齐。 ### 变更文件 - `internal/backendexecutor/executor.go`:新增 `ImageAcquisitionPresent = "present"` 模式——镜像已在本地,跳过 pull/load,仅在 `prepare` 核对本地镜像 digest + platform。 - `internal/backendupdate/container.go`:新增 `RestartContainer`;新增 `inputTypeContainerRestart` 常量;`runContainerUpdate` 按 `InputType` 区分 `present`/`pull`;提取 `validateContainerInputs` 复用前置校验。 - `internal/backendupdate/restart.go`:`Restart` 按 `backend.type` 分派,container → `RestartContainer`,native 走原逻辑。 ### 语义(对齐 native restart 决策 50) - 复用本地镜像,不重新 pull,不依赖 registry。 - 每次调用执行一次真实槽位轮转,幂等键用随机 `restart:` 前缀,不复用历史 update 的内容幂等键。 - 无部署记录、gateway 活动端口漂移、活动容器身份不一致时拒绝。 - 未完成 restart 事务由同一命令恢复;复用 `runContainerUpdate` + `switchAndCommitContainer`。 ### 测试 `container_test.go` 新增:正常 restart(轮转 + 不 pull + 提交部署记录)、无部署记录拒绝、gateway 漂移拒绝。全量 build/vet/test 通过。 --- ## 2026-08-17 实现 status / doctor / reconcile 依据 `CLI_NAMING_AND_OPERATIONS_PLAN.md`(已并入 `PLAN.md` 附录)第 3.3 / 4 / 5 节,实现三个诊断与对账子命令。 ### 破坏性变更 1. `daemonserver.New` 签名:由 `New(socketPath, updater, logger)` 改为 `New(socketPath, updater, diagnoser, logger)`。 2. `daemonapi.Request` 新增 `Apply bool`(`json:"apply"`),仅 `OperationReconcile` 使用。 3. `daemonapi.Response` 新增 `Diagnosis *Diagnosis`(`json:"diagnosis,omitempty"`)。 4. `daemonapi` 新增操作常量 `OperationStatus/OperationDoctor/OperationReconcile`,及诊断级别常量 `DiagnosisLevelOK/Fixable/Drift`。 5. `hostnginx.NewController` 已是 2 参数(`configPath, nginxExecutable`),重载走 `nginx -s reload`(并行期间他人改动,本轮按现状接入)。 ### 新增 / 修改文件 - 新增 `internal/backendstatus/`:`diagnoser.go`、`container.go`、`native.go`、`reconcile.go`、`container_test.go`。 - 修改 `daemonapi/protocol.go`、`daemonserver/server.go`、`daemonclient/client.go`、`main.go`、`main_test.go`、`daemonserver/server_test.go`。 ### 诊断模型 - 级别:`ok`(一致)/ `fixable`(可自动修复)/ `drift`(需人工)。 - `Healthy = true` 当且仅当无 `drift` 项。 - 展示过滤:`status` 只展示 drift/fixable,`doctor` 展示全部,`reconcile` 只展示 fixable。 - container 诊断以 `backend_container_deployment` 记录为事实来源;native 只读诊断(无自动修复)。 ### 待办 - native 自动修复未实现(JAR 链接漂移修复需 filestore identity + release 校验)。 - `coverage.out` 未重新生成(不含新包)。