性质:只监测、不重复执行的核查。本轮未启动任何同步、未走同步桥、未 claim、未抢占服务端租约、未删除目录锁(锁由运行器自行释放后核验)、未读取或输出任何凭据内容。凭据文件仅用于
node --env-file=加载。
业务日 2026-11-02(Asia/Shanghai)夜间同步:已完成,取得服务端真实成功回执,终态 completed-with-preserved-conflicts,failed=0。
--scheduled 入口。xiaoshu/sync/direct-v1 只读 status 返回同一 runId 的终态回执,finishedAt 非空,与本机报告逐数据集一致。reconciled=true,来源 ID 校验和与目标校验和逐一相符;财务分组回读核对通过;账号/栏目补缺符合预期;锁已释放。保留冲突 3,872 条:这是「有意保留新系统修改」的结果,不等于源与目标不一致,也不构成失败;其中账号冲突 170 条(身份冲突 identityConflicts=0)。
| 项目 | 核查结果 |
|---|---|
| plist 路径 | /Users/mac/Library/LaunchAgents/cn.xiaoshu.legacy-direct-sync-nightly.plist(存在) |
| ProgramArguments | /usr/local/bin/node + --env-file=/Users/mac/.config/xiaoshu/legacy-sync-nightly.env + ~/Library/Application Support/XiaoshuSync/scripts/run-nightly-direct-sync.mjs + --scheduled —— 与预期一致 |
| EnvironmentVariables.TZ | Asia/Shanghai —— 与预期一致 |
| StartCalendarInterval | Hour=23 / Minute=0 —— 与预期一致 |
| launchd 状态 | 运行期 state = running、pid = 53341;收尾后 state = not running |
| runs 计数 / last exit code | runs = 2、last exit code = 0 |
| 禁用状态 | launchctl print-disabled gui/501 中该 job 为 enabled(11-01 的 disabled 已被撤销) |
实际触发证据(三重一致):
ps 显示 /usr/local/bin/node … run-nightly-direct-sync.mjs --scheduled 于 Mon Nov 2 23:00:00 2026 启动,pid 53341;~/.local/state/xiaoshu/legacy-sync/direct-nightly.lock/owner.json 记录 {"pid":53341,"startedAt":"2026-11-02T15:00:00.397Z"}(北京时间 23:00:00);startedAt = 2026-11-02T15:00:03.138Z(北京时间 23:00:03),业务日 2026-11-02。环境前提: 机器开机且该用户已登录控制台会话,非关机/未登录导致的误判。核查窗口 23:00–23:41(北京时间),轮询间隔 5 分钟观察、10 分钟汇报,运行状态在 23:39 转为终态后收尾,无需延长至 120 分钟。
主报告:~/.local/state/xiaoshu/legacy-sync/2026-11-02-direct-12f01ee1-90b8-46d5-8f5a-73fe95515ee0.json(0600)
| 项目 | 值 |
|---|---|
| businessDate / runId | 2026-11-02 / 12f01ee1-90b8-46d5-8f5a-73fe95515ee0 |
| status | completed-with-preserved-conflicts |
| 起止(UTC / 北京) | 15:00:00.397Z → 15:39:26.413Z / 23:00:00 → 23:39:26 |
| failed | 0 |
| createdBusinessRecords / refreshedBusinessRecords | 159 / 138 |
| 保留冲突 | 3,872(含账号冲突 170) |
| source / bridgeUsed | old-api/WXAPP / false |
| allCapturedSourceIdsReconciled | true |
| settlementReady | false(按设计不设置) |
被排除在终态判定之外的记录(按「不把人工批次当 23 点运行」的要求):
| 文件 / runId | 时间(北京) | 状态 | 排除理由 |
|---|---|---|---|
2026-11-02-direct-47ca3da6-4832-40c6-871d-a8ab94a5db9f.json |
11-02 12:55 | ready,datasets: [] |
白天人工 --check 批次,未执行任何数据集,不计入当晚运行 |
904997ef-4062-4eb5-a50e-1a7e10cb27f7 |
11-01 23:19–23:57 | completed-with-preserved-conflicts |
属于业务日 2026-11-01,仅作基线比对 |
日志侧证:launchagent.log 逐数据集分页推进正常(练习记录 450/450、抗遗忘 204/204、测评 1/1 等),收尾行 {"status":"completed-with-preserved-conflicts","reason":"","runId":"12f01ee1-…","created":159,"updated":138,"conflicts":3872}。launchagent-error.log 尾部仍为 2026-10-17 的 ERR_MODULE_NOT_FOUND sync-alerts 历史残留(该文件当前存在),与本轮无关。告警状态文件 direct-alert-state.json 为 {"failed":false,"lastKey":"recovered","conflicts":3872,...}。
action:'status')查询方式:node --env-file=<凭据文件> tmp/direct-v1-status-check.mjs(只发 action:'status',不建锁、不抢租约、不启动同步;输出对 token/secret/key/password/session 类字段脱敏)。
| 项目 | 服务端 | 本机 | 一致 |
|---|---|---|---|
| businessDate | 2026-11-02 | 2026-11-02 | ✅ |
| runId | 12f01ee1-90b8-46d5-8f5a-73fe95515ee0 |
同 | ✅ |
| status | completed-with-preserved-conflicts |
同 | ✅ |
| startedAt / finishedAt | 15:00:03.138Z / 15:39:13.641Z |
15:00:00.397Z / 15:39:26.413Z |
✅(起停分别为客户端与服务端落库时刻,差值为秒级) |
| failed | 0 | 0 | ✅ |
| 9 个数据集逐项 created/updated/conflicts/reconciled | 见下表 | 同 | ✅ |
| 账号 / 栏目 / 财务 | 见下 | 同 | ✅ |
| # | 验收项 | 结果 | 证据 |
|---|---|---|---|
| 1 | 9 个业务数据集服务端业务 ID、主表与关联附表、校验和核验 | 通过 | 9/9 reconciled=true,sourceIdChecksum === targetChecksum,createdAddon 与主表一致 |
| 2 | 每个业务编号恰有一份主表 | 通过 | allCapturedSourceIdsReconciled=true,各数据集 sourceCount 与 source 相符 |
| 3 | 账号只新增并匹配旧用户编号 | 通过 | source 749 / created 0 / matched 745 / missing 0 / excluded 4 / identityConflicts 0 |
| 4 | 栏目只补缺 | 通过 | source 461 / created 0 / matched 461 / missing 0 |
| 5 | 财务分组(会员流水 stype=1/2/3/4)回读核对 | 通过 | members 550 / streams 2200 / rows 42,282 / reconciled=true |
| 6 | failed=0 |
通过 | 本机报告与服务端回执均为 0 |
| 7 | 锁已释放 | 通过 | direct-nightly.lock 目录已消失,pid 53341 已退出,launchd state = not running |
| 8 | 来源 old-api/WXAPP 且 bridgeUsed=false |
通过 | 两份回执均一致,未使用同步桥 |
| 9 | 保留新系统修改、余额、课时、人工确认、复习计薪凭据 | 通过 | supplement.existingAccountBalancesUntouched=true;冲突仅记录(3,872 条),不自动解决 |
数据集明细(本机与服务端一致):
| 数据集 | 源条数 | 页数 | 新增 | 新增附表 | 更新 | 冲突 | failed | reconciled |
|---|---|---|---|---|---|---|---|---|
| 专项训练 | 19 | 1 | 0 | 0 | 0 | 19 | 0 | ✅ |
| 词库 | 106,520 | 107 | 0 | 0 | 0 | 166 | 0 | ✅ |
| 课程绑定 | 1,542 | 2 | 0 | 0 | 1 | 118 | 0 | ✅ |
| 每日学习 | 19,963 | 20 | 3 | 3 | 0 | 0 | 0 | ✅ |
| 练习记录 | 449,942 | 450 | 121 | 121 | 63 | 536 | 0 | ✅ |
| 抗遗忘 | 203,605 | 204 | 30 | 30 | 73 | 2,297 | 0 | ✅ |
| 预约 | 31,799 | 32 | 2 | 2 | 1 | 564 | 0 | ✅ |
| 上课 | 19,737 | 20 | 3 | 3 | 0 | 0 | 0 | ✅ |
| 测评 | 206 | 1 | 0 | 0 | 0 | 0 | 0 | ✅ |
| 维度 | 2026-11-01(上次核查) | 2026-11-02(本次) |
|---|---|---|
| 终态 | not_run |
completed-with-preserved-conflicts |
| 原因 / 阻塞项 | launchagent_disabled_by_user_request |
无阻塞(legacy_account_identity_conflict 仍为 0) |
| 服务端回执 | 无该业务日记录 | 有,finishedAt 非空 |
| 保留冲突 | 不适用(未运行) | 3,872(上一业务日基线 4,279) |
| 账号冲突 | 不适用 | 170(上一业务日 169) |
| 变化分类 | — | stopped_to_success_after_user_re_enable,严重级别:预期恢复,非故障 |
补充说明:业务日 2026-11-01 在当日 23:19 由人工批次补齐(runId 904997ef…,failed=0,9 数据集与财务均 reconciled),因此停运未造成 11-01 的数据缺口;本次 11-02 运行补齐了当日数据。两个业务日均有有效回执。
settlementReady 按设计始终为 false。~/.local/state/xiaoshu/legacy-sync/heartbeat-23-status-2026-11-02.json(0600,含业务日、runId、终态、9 数据集与账号/栏目/财务核验、差异、通知判定,不含任何凭据)~/.local/state/xiaoshu/legacy-sync/2026-11-02-direct-12f01ee1-90b8-46d5-8f5a-73fe95515ee0.json(0600)docs/migration/nightly-legacy-sync-check-2026-11-02.md