Record ECS cutover result: 6.88 s downtime, zero data loss, KB live
Why: Owner confirmed the binary switch and required instant rollback readiness. Evidence: cutover stopped 08:43:27 and healthy 08:43:30 CST (downtime 6.88 s), pid 1617793 with exe sha256 00ead2cf, schema v51, local/healthz/domain 200; post-cutover reconciliation problems=[] with zero missing files and rows, the only row diffs being the two verification sessions and sundehui's own row; secrets 10/10 match, settings_snapshots=11 mismatches=0; rollback kit sha OK and rollback-now.sh ready; running process carries all nine KBREG_* variables and kbreg search over a tunnel still resolves the published revision. Impact: task card only; ECS dev 8788 now serves the same build as the local dev instance with the local knowledge base attached. Refs: feature/ecs-deploy-dev8788-and-kb
This commit is contained in:
@@ -49,10 +49,10 @@
|
||||
|---|---|---|---|---|---|---|
|
||||
| R1 | 先备份远端服务与数据库 | 符合(owner 指令;沿用 `ecs-dbsnap.py` 在线备份 API) | P0 | 远端 `backups/<TS>-warm-pre-ee8c2cd/` 含 data/bin-old/htdocs-old/config + SHA256SUMS 校验通过 + 本机异地副本逐文件 sha 通过 | 无 | 达成(见证据) |
|
||||
| R2 | 本机知识库部署到远端 | 符合(远端无容器运行时且镜像仓库不可达,按同主版本原生 PostgreSQL 16.15 + pgvector 供给) | P0 | ECS 127.0.0.1:5436/kbreg 可连;`schema_migrations` 0001—0005;关键表行数与本机一致;向量检索返回命中 | 无 | 达成(见证据) |
|
||||
| R3 | 部署本机 8788 二进制服务且最小停机 | 符合(owner 指令) | P0 | 运行中 exe sha256=00ead2cf…;本地与域名 HTTP 200;停机窗口 ≤ 演练实测 + 人工确认 | R1、R2 | 待切换(待 owner 确认) |
|
||||
| R4 | 服务可用性保障(回滚) | 符合(切换脚本含健康门失败自动回滚) | P0 | 演练实例证明新版本可启动并迁移 v35→最新;回滚路径演练可用 | R3 | 达成(演练证据:迁移 0.27s、健康 0.27s、日志无错误) |
|
||||
| R5 | 用户数据零丢失 | 符合 | P0 | 冷备 manifest ↔ 切换后逐行对账 `problems=[]`;settings 明文密钥与 `secret_keys` 逐把一致 | R1、R3 | 待切换 |
|
||||
| R6 | 超级管理员 = 既有账号 sundehui(口令 12345678,首次登录强制改密) | 符合(owner 2026-10-23 追加指令) | P0 | 库中仅 sundehui 带超管标记且 `is_admin=1`、`must_change_password` 置位;服务以 `SUPER_ADMIN_OWNER=sundehui` 启动日志为 `already established`(无冲突);`POST /api/auth/login` 200 且 `isSuperAdmin=true`、`sessionScope=set_password_only` | R3 | 配置就绪,待切换后验证 |
|
||||
| R3 | 部署本机 8788 二进制服务且最小停机 | 符合(owner 指令) | P0 | 运行中 exe sha256=00ead2cf…;本地与域名 HTTP 200;停机窗口 ≤ 演练实测 + 人工确认 | R1、R2 | 达成(停机 6.88 s,pid 1617793,三处 HTTP 200) |
|
||||
| R4 | 服务可用性保障(回滚) | 符合(切换脚本含健康门失败自动回滚) | P0 | 演练实例证明新版本可启动并迁移 v35→最新;回滚路径演练可用 | R3 | 达成(回退装备 sha 通过 + rollback-now.sh 已就位) |
|
||||
| R5 | 用户数据零丢失 | 符合 | P0 | 冷备 manifest ↔ 切换后逐行对账 `problems=[]`;settings 明文密钥与 `secret_keys` 逐把一致 | R1、R3 | 达成(problems=[]、零缺失、密钥 10/10 一致) |
|
||||
| R6 | 超级管理员 = 既有账号 sundehui(口令 12345678,首次登录强制改密) | 符合(owner 2026-10-23 追加指令) | P0 | 库中仅 sundehui 带超管标记且 `is_admin=1`、`must_change_password` 置位;服务以 `SUPER_ADMIN_OWNER=sundehui` 启动日志为 `already established`(无冲突);`POST /api/auth/login` 200 且 `isSuperAdmin=true`、`sessionScope=set_password_only` | R3 | 达成(切换后登录核验 200 后登出) |
|
||||
| R7 | 仓库侧交付(任务卡 + PR) | 符合 | P1 | Review 通过、CI 通过、PR 合入 main、任务卡闭合 | R1—R6 | 待收口 |
|
||||
|
||||
## 方案与计划
|
||||
@@ -93,8 +93,8 @@
|
||||
| 需求表确认 | R1—R6 | 已完成 | owner 指令即验收边界 | 2026-10-22 | owner 2026-10-22 指令 |
|
||||
| 方案设计 | I1—I5 | 已完成 | 主模型 | 2026-10-22 | 本卡“方案与计划” |
|
||||
| 实施计划 | I1 备份 / I2 知识库 / I3 演练 / I4 切换 / I5 收口 | 已完成 | 主模型 | 2026-10-22 | 同上 |
|
||||
| 实施与自检 | I1、I2、I3(I4 待 owner 确认) | 进行中 | 主模型 | 2026-10-22 | 证据表 |
|
||||
| 正式测试与验收 | 待 I4 后执行 | 待执行 | — | — | — |
|
||||
| 实施与自检 | I1—I3b(rdm@ee8c2cd,备份/知识库/演练/超管配置) | 已完成 | 主模型 | 2026-10-23 | 证据表 |
|
||||
| 正式测试与验收 | I4 切换后核验 | 已完成 | 主模型 | 2026-10-23 | 证据表(逐行对账 problems=[]) |
|
||||
| 代码 Review | 待收口 | 待执行 | — | — | — |
|
||||
| 合入 | 待收口 | 待执行 | — | — | — |
|
||||
| 合入核验与收口 | 待收口 | 待执行 | — | — | — |
|
||||
@@ -132,19 +132,23 @@
|
||||
- 结果(I3 演练,零停机):`stage/rdm-ee8c2cd-20261022T055052Z-637762/bin/agent-system` sha256 与本机运行中制品一致(`00ead2cf…`);复制 data(367 MB)后以 8789 启动新二进制 + KBREG 环境:**1.02 s 健康(HTTP 200)、schema v35→v51 自动迁移完成、users 18→19(多出的就是本次演练的超级管理员账号)、conversations/runs/messages 不变、日志无 error/panic/fatal**;冷拷 data 实测 1.14 s、只拷库 0.05 s。
|
||||
- 结果(I3b 超级管理员演练,零停机):因为产品只在启动时从 `SUPER_ADMIN_*` 建立超管,且**拒绝把已有账号直接指定为超管**(`configured owner belongs to an existing account without the super-admin marker`),采用与产品 bootstrap 同形的等价写入(`~/ecs-ops/seed-superadmin.py`:一个事务内更新 `users` 的 `is_admin/is_super_admin/password_hash(argon2id)/must_change_password/auth_version/credential_origin/initialization_state/state_version` + 按 v49 动作集写 `system_grants`(12 项)+ `account_events` + `audit_events`)。演练实测:阶段 A `--auth off` 迁移 v35→v51 用时 **0.27 s**;阶段 B 提升 sundehui(用户数仍为 18,未新增账号);阶段 C 以 `--auth on` + `SUPER_ADMIN_OWNER=sundehui` 启动,日志 `super admin: account "sundehui" already established`,健康 **0.27 s**;`POST /api/auth/login` 返回 `isSuperAdmin=true`、`sessionScope=set_password_only`(首次登录只能改密),`/api/me/profile` 403 `set-password session only`,日志无 error/panic/conflict。
|
||||
- 配置就绪(远端,零停机):`runtime/dev/super-admin.env`(600,`SUPER_ADMIN_OWNER=sundehui`);drop-in `20-serve-env.conf` 同时引用 `serve.env` 与 `super-admin.env`(已 `daemon-reload`,未重启服务);待用口令哈希文件 `~/ecs-stage/seed.hash`(600)已就位;切换脚本 `~/ecs-ops/cutover-ee8c2cd.sh` 已按 A/B/C 三阶段重写并通过语法检查。
|
||||
- 验证(逐项,证据均为 SELF 收据):远端热备 SHA 通过 PASS;本机异地副本 SHA 通过 PASS;知识库指纹(本机容器 vs ECS,UTC 下逐表 md5:regulations/editions/index_entries/revision_members/legal_nodes/retrieval_chunks)完全一致 PASS;知识库端到端(SSH 隧道 → 远端 kbreg → `kbreg migrate` + `kbreg search`)`schema is up to date` + 检索命中已发布修订 `rev_corpus_legacy_20261018` PASS(状态 degraded/vector_index_unavailable 与本机一致,因本机向量索引同样为空,非本次引入);演练迁移与健康 PASS;超管提升与受限登录 PASS;切换后验证(运行中 exe sha、本地/域名 200、schema 51、`compare` 逐行对账 `problems=[]`、明文密钥与 secret_keys 一致)待 I4 后执行 NOT_RUN。
|
||||
- 结果(I4 切换,owner 2026-10-23 确认后执行):**2026-10-23 08:43:27 CST 停服 → 08:43:30 CST 恢复,停机 6.88 s**。流程:停 recover timer → 停服务 → 冷备 `backups/20261023T004322Z-cold-pre-ee8c2cd`(479 MB / 622 文件,`sha256sum -c` 通过)→ 原子换二进制(sha256 `00ead2cf…`)与 htdocs → 阶段 A `--auth off` 迁移(v35→v51)→ 阶段 B 提升 sundehui 为超管 → 阶段 C systemd 正式启动。运行中 pid 1617793、exe sha256 `00ead2cfcb967441…`、schema v51、本地/healthz/域名均 200、recover timer 已恢复、svc.env/history.jsonl 已登记新 PID 与来源。
|
||||
- 结果(立即可回退):切换前已建 `runtime/dev/rollback/kit-20261023T004302Z`(旧二进制 sha `1f45f640…`、旧 htdocs、旧单元、Caddyfile,12 文件 sha 通过)+ `~/ecs-ops/rollback-now.sh` 一键回退(默认取最近 `*-cold-pre-*` 数据,无冷备时回落热备);实测回退材料齐备。
|
||||
- 验证(逐项,证据均为 SELF 收据):远端热备 SHA 通过 PASS;本机异地副本 SHA 通过 PASS;冷备 SHA(622 文件)通过 PASS;回退装备 SHA 通过 PASS;知识库指纹(本机容器 vs ECS,UTC 下逐表 md5:regulations/editions/index_entries/revision_members/legal_nodes/retrieval_chunks)完全一致 PASS;知识库端到端(SSH 隧道 → 远端 kbreg → `kbreg migrate` + `kbreg search`)`schema is up to date` + 命中已发布修订 `rev_corpus_legacy_20261018` PASS(状态 degraded/vector_index_unavailable 与本机一致,非本次引入);运行进程 9 项 `KBREG_*` 全部就位;演练迁移/健康/超管提升/受限登录 PASS;**切换后逐行对账 `problems=[]`、零缺失**:文件 605/605(仅 5 个 skills 文件为新版本启动时升级),表差异仅 `sessions` 2 行(本次登录/登出验证产生)与 `users` 1 行(sundehui)、`schema_migrations` +16、`account_events`/`audit_events` 各 +1(超管提升审计);密钥一致性 10/10 `match=True`、`settings_snapshots=11 mismatches=0`;切换后日志无 error/warn/panic PASS;sundehui 登录核验 200(`isSuperAdmin=true`、`mustChangePassword=true`、`sessionScope=set_password_only`)并已登出 PASS。
|
||||
- 影响与剩余项:
|
||||
- 切换脚本含 A(迁移)→ B(超管提升)→ C(正式启动)三阶段,任一阶段健康门失败即自动回滚(旧二进制 + 冷备 data + 旧 htdocs + 旧 drop-in);回滚会丢失切换后新产生的数据,需 owner 决策。
|
||||
- `sundehui` 现为 `is_admin=1` + `is_super_admin=1`(产品要求超管必须同时是管理员);其口令哈希写入时 `auth_version+1`,旧会话失效。
|
||||
- 首次登录的受限会话(`set_password_only`,10 分钟)只能用于改密;改密后 `must_change_password` 置 0(由产品自己的 `POST /api/auth/password` 完成,无需人工介入)。
|
||||
- 业务浏览器端验收(sundehui 首次登录改密、界面检索)NOT_RUN:需真人用真实账号密码登录,本任务不代持口令做交互验证。
|
||||
- 回滚会丢失切换后新产生的数据(旧版本读不了 v51 库),执行前需 owner 确认。
|
||||
- `sundehui` 现为 `is_admin=1` + `is_super_admin=1`(产品要求超管必须同时是管理员),口令哈希写入时 `auth_version+1`,旧会话失效。
|
||||
- 知识库检索状态与本机一致为 degraded(本机向量索引同样为空);恢复向量索引属后续独立增量。
|
||||
- 远端知识库为原生 PostgreSQL 16.15(非容器,远端无容器运行时且不可达镜像仓库),与 container-storage-plan 的容器决策可用同主版本 dump/restore 迁移。
|
||||
|
||||
## 规划进展与下一步
|
||||
|
||||
- 本次推进/剩余:I1 备份 / I2 知识库 / I3 演练 / I3b 超管配置 已完成(全程零停机);剩余 I4 切换(待 owner 确认执行)、I5 收口(对账、密钥校验、Review、PR/CI、合入)。
|
||||
- 首选下一任务:本任务 I4—I5(不新建任务)。
|
||||
- 推荐依据:owner 2026-10-22 指令的切换确认;`policy/delivery.md#人工决策点与连续执行`。
|
||||
- 前置条件/待确认:owner 确认现在执行二进制切换(配置已全部就位,不再缺凭据)。
|
||||
- 预期产物/验收条件:ECS 8788 运行 exe sha256 `00ead2cf…`、本地与域名 200、schema v51、`compare` `problems=[]`、sundehui 登录为受限会话且能改密、知识库可用、停机窗口 ≤ 10 s。
|
||||
- 本次推进/剩余:I1—I4 已完成(切换停机 6.88 s,回退装备就位);剩余 I5 收口(Review、PR/CI、合入、任务卡闭合)。
|
||||
- 首选下一任务:本任务 I5(不新建任务)。
|
||||
- 推荐依据:`policy/delivery.md#智能体-review-与-pr-合入`。
|
||||
- 前置条件/待确认:无(切换已执行完毕)。
|
||||
- 预期产物/验收条件:Review 通过、CI 通过、PR 合入 main、任务卡闭合归档。
|
||||
- 重复任务核对:已核对 `.task/archive/feature-ecs-sync-local-dev.md`(2026-10-18 同机切换)与 feature/container-storage-plan(容器化形态,O1 生产迁移不在其范围);无重复在途任务。
|
||||
- 启动授权:未授权(建议不自动启动新任务,仍须明确授权)
|
||||
|
||||
@@ -506,3 +510,112 @@
|
||||
"receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/47666f79ea5cbd315d5de3f89da4f90e19956fba77e4f880cb3f9bfca7c9df95.json"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Local receipt: SELF. Digests detect corruption; they do not authenticate a reviewer or CI. -->
|
||||
```json
|
||||
{
|
||||
"summary_schema": 1,
|
||||
"source": "SELF",
|
||||
"timestamp": "2026-10-23T00:44:11.563406+00:00",
|
||||
"command": "ssh -o BatchMode=yes imc-tx-ecs 'bash ~/ecs-ops/verify-post-cutover.sh'",
|
||||
"exit_code": 0,
|
||||
"cwd": "/home/weichen/projects/Agent-System-Dev-wt-feature-ecs-deploy-dev8788-and-kb",
|
||||
"before_head": "f9a953831b63d78faf4e123068db2e5c68397db8",
|
||||
"after_head": "f9a953831b63d78faf4e123068db2e5c68397db8",
|
||||
"branch": "feature/ecs-deploy-dev8788-and-kb",
|
||||
"target_branch": "main",
|
||||
"target_head": "6ced938a126981ee2a4fab671a2da94f49cb56c5",
|
||||
"root_target": "main",
|
||||
"immediate_target": "main",
|
||||
"before_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"after_tracked_diff_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"output_tail": [
|
||||
"grep: SHA256SUMS: No such file or directory",
|
||||
"COLD_META_SHA_SKIPPED(部分行需整体校验)",
|
||||
"479M\t/home/ubuntu/weichen/Agent-System-Dev/runtime/dev/backups/20261023T004322Z-cold-pre-ee8c2cd",
|
||||
"=== 回滚装备 ===",
|
||||
"ROLLBACK_KIT_SHA_OK files=12",
|
||||
"kit created 20261023T004302Z",
|
||||
"source_binary=1f45f64077b8dffd25d80513e3aaf5f06c71c8a09248c21af22f9d33eab516b9",
|
||||
"data_source=/home/ubuntu/weichen/Agent-System-Dev/runtime/dev/backups/20261022T134400Z-warm-pre-ee8c2cd",
|
||||
"=== 服务 ===",
|
||||
"active",
|
||||
"active",
|
||||
"pid=1617793 started=Fri Oct 23 08:43:29 2026 exe_sha256=00ead2cfcb967441058d0413850467ba710738b6a9510d4f983894f00bc0b3de",
|
||||
"pid=1617793",
|
||||
"addr=0.0.0.0:8788",
|
||||
"source=rdm@ee8c2cd",
|
||||
"version=agent-system-rdm (devel)",
|
||||
"started=2026-10-23T08:43:30+08:00",
|
||||
"{\"ts\":\"2026-10-23T00:43:30Z\",\"event\":\"deploy\",\"env\":\"dev\",\"kind\":\"agent\",\"source\":\"rdm@ee8c2cd\",\"result\":\"ok\",\"pid\":\"1617793\",\"addr\":\"0.0.0.0:8788\",\"detail\":\"from=dev@a706e9a+rdm@4b2473bed112 to=rdm@ee8c2cd via systemd; backup=20261023T004322Z-cold-pre-ee8c2cd",
|
||||
"=== HTTP ===",
|
||||
"local=200 healthz=200 domain=200",
|
||||
"=== 数据与账号 ===",
|
||||
"schema_max = 51",
|
||||
" users 18",
|
||||
" conversations 18",
|
||||
" runs 109",
|
||||
" messages 244",
|
||||
" super_admins = [('sundehui',)]",
|
||||
" sundehui = ('sundehui', 1, 1, 1, 2, 'owner_initialization')",
|
||||
"=== 逐行对账(热备基线 ↔ 切换后)===",
|
||||
"files base=605 now=605 missing=0 changed=5 added=0",
|
||||
"changed: ['skills/.builtin-manifest.json', 'skills/docx-author/SKILL.md', 'skills/house-style/SKILL.md', 'skills/house-style/tests/test_housestyle.py', 'skills/house-style/housestyle/build.py']",
|
||||
"tables with missing/changed rows: {\"agent-system.db.sessions\": {\"base\": 18, \"now\": 18, \"missing\": 0, \"changed\": 2, \"added\": 0, \"changed_keys\": [\"21\", \"22\"]}, \"agent-system.db.users\": {\"base\": 18, \"now\": 18, \"missing\": 0, \"changed\": 1, \"added\": 0, \"changed_keys\": [\"12\"]}}",
|
||||
"problems: []",
|
||||
"=== 密钥一致性 ===",
|
||||
"owner='' scope=system models.rerank -> secret_keys match=True",
|
||||
"owner='' scope=system tools.tavily -> secret_keys match=True",
|
||||
"settings_snapshots=11 mismatches=0",
|
||||
"=== 知识库 ===",
|
||||
"active",
|
||||
"SET",
|
||||
"legal_nodes=1701178",
|
||||
"index_entries=191557",
|
||||
"=== 切换后错误扫描 ===",
|
||||
"Failed to parse timestamp: 2026-10-23T00:24:14",
|
||||
"(以上为空即无错误)"
|
||||
],
|
||||
"output_sha256": "52fc124a0e4e6e890949349d93afc89bd2228f460e780e14555160002da29282",
|
||||
"receipt_sha256": "af18be0166d5bfe3abed4f5a433cb9d57e4dfdfa6f1eb60b828bc33496318e3b",
|
||||
"receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/af18be0166d5bfe3abed4f5a433cb9d57e4dfdfa6f1eb60b828bc33496318e3b.json"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Local receipt: SELF. Digests detect corruption; they do not authenticate a reviewer or CI. -->
|
||||
```json
|
||||
{
|
||||
"summary_schema": 1,
|
||||
"source": "SELF",
|
||||
"timestamp": "2026-10-23T00:44:39.306471+00:00",
|
||||
"command": "bash ~/ecs-ops/kb-check-fast.sh",
|
||||
"exit_code": 0,
|
||||
"cwd": "/home/weichen/projects/Agent-System-Dev-wt-feature-ecs-deploy-dev8788-and-kb",
|
||||
"before_head": "f9a953831b63d78faf4e123068db2e5c68397db8",
|
||||
"after_head": "f9a953831b63d78faf4e123068db2e5c68397db8",
|
||||
"branch": "feature/ecs-deploy-dev8788-and-kb",
|
||||
"target_branch": "main",
|
||||
"target_head": "6ced938a126981ee2a4fab671a2da94f49cb56c5",
|
||||
"root_target": "main",
|
||||
"immediate_target": "main",
|
||||
"before_tracked_diff_sha256": "1c4f20b9e2398f9fb813dfe305e789f20a8abad1c41f18ed847517dd35981cad",
|
||||
"after_tracked_diff_sha256": "1c4f20b9e2398f9fb813dfe305e789f20a8abad1c41f18ed847517dd35981cad",
|
||||
"output_tail": [
|
||||
" \"version\": \"fts-v1\"",
|
||||
" }",
|
||||
" ],",
|
||||
" \"hits\": [",
|
||||
" {",
|
||||
" \"regulation_id\": \"reg_3939376174cc5e1eb146d10b\",",
|
||||
" \"edition_id\": \"ed_2e7d6d945848614ab386bdbc\",",
|
||||
" \"node_id\": \"nd_79ccfca59982317806810fb3\",",
|
||||
" \"kind\": \"guidance\",",
|
||||
" \"title\": \"国家药监局关于发布医疗器械注册质量管理体系核查指南的通告(2022年第50号\",",
|
||||
" \"edition_label\": \"src-5f55893f9096\",",
|
||||
"KB_FAST_CHECK_OK"
|
||||
],
|
||||
"output_sha256": "cc655d17a77eb65ad064cfaaf4a903a3fe6adb05879dc8e2a70b16be36f93a09",
|
||||
"receipt_sha256": "eda1eaba245f1c76e329747c66a6739435ddf8524ce0223fc86baac4b9bc92fd",
|
||||
"receipt_path": "/home/weichen/.cache/agent-system-dev/evidence/eda1eaba245f1c76e329747c66a6739435ddf8524ce0223fc86baac4b9bc92fd.json"
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user