nightly-legacy-sync-check-2026-11-03.md 12 KB

夜间同步核查记录 · 业务日 2026-11-03

性质:只监测、不重复执行的核查。本轮未启动任何同步、未走同步桥、未 claim、未抢占服务端租约、未删除目录锁、未自动解决冲突、未读取或输出任何凭据内容。凭据文件仅用于 node --env-file= 加载。

一、结论

业务日 2026-11-03(Asia/Shanghai)夜间同步:未完成 / 阻塞,无服务端成功回执。 终态未出现(本轮不宣称终态),验收清单全不满足。

  • 真实 23:00 触发已发生:北京时间 2026-11-03 23:00:07 由 launchd 以 --scheduled 入口拉起,runId 5f2ddc11-0139-4356-a2f6-052e1bfb5c33。
  • 本机主运行报告为 blocked,原因 legacy_account_identity_conflict: resolve reading-generated IDs before syncing business records,identityConflicts=1、failed=1、datasets=[]。
  • 服务端 xiaoshu/sync/direct-v1 只读 status 中该 run 仍为 running,finishedAt=null、summary=null —— 没有成功回执。
  • 9 个业务数据集与财务分组一个都未执行,账号/栏目仅完成前置补缺扫描即被阻断,未产生业务写入与对账证据。
  • 相对上一业务日 2026-11-02(成功回执),本业务日为「由成功转为失败」的重大变化,且新增 1 处身份冲突 → 通知用户。
  • 本轮只记录冲突,不自动解决;阻塞需人工核实处置。

保留新系统修改、账户余额、课时、人工确认与复习计薪凭据的要求未被破坏:本次根本没有进入业务投影阶段。settlementReady 按设计始终为 false,未伪造。

二、LaunchAgent 定义与实际触发

项目 核查结果
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 —— 与预期一致
禁用状态 launchctl print-disabled gui/501 中该 job 为 enabled(非 11-01 的用户停运态)
runs 计数 / last exit code 23:00:53 首次读取 runs=2 / exit=1;23:40 收尾时 runs=10 / exit=1(每 5 分钟一次失败重试)
launchd 状态 spawn scheduled,active count 在重试瞬间为 1;minimum runtime=300

实际触发证据(三重一致):

  1. 主运行报告 startedAt = 2026-11-03T15:00:07.605Z(北京时间 23:00:07),businessDate=2026-11-03,runId=5f2ddc11-…;
  2. 服务端 run 记录 startedAt = 2026-11-03T15:00:11.147Z(北京时间 23:00:11),业务日 2026-11-03;
  3. launchagent.log 尾部出现 {"status":"blocked","reason":"legacy_account_identity_conflict: …","runId":"5f2ddc11-…"},且 23:05/23:15/23:25/23:35 的 5 分钟重试报告均为 blocked。

环境前提: 机器开机且该用户已登录控制台会话(launchctl print gui/501 可用),不是关机/未登录导致的「未运行」。这是真实 23:00 日历触发,不是唤醒补跑;Codex/聊天窗口是否关闭不影响 LaunchAgent。

launchagent-error.log: 文件 mtime 为 2026-10-17,尾部 ERR_MODULE_NOT_FOUND sync-alerts.mjs 与「同步通知发送失败」均为 10-17 历史残留,与本轮无关;该模块当前存在。本轮真实失败原因以 launchagent.log 的 blocked 行为准。direct-alert-state.json 为 {"failed":true,"lastKey":"failure","notifiedAt":1793718015856(23:00:15),"conflicts":3872,"lastSuccessAt":1793710469429(20:54:29)} —— 告警状态由 23:00 的失败运行置位,非新的独立故障。

三、本机私有状态目录(业务日 2026-11-03)

主报告:~/.local/state/xiaoshu/legacy-sync/2026-11-03-direct-5f2ddc11-0139-4356-a2f6-052e1bfb5c33.json(0600)。该文件在每 10 分钟的主重试中被同一 runId 覆写,末次内容:

项目 值
businessDate / runId 2026-11-03 / 5f2ddc11-0139-4356-a2f6-052e1bfb5c33
status blocked
末次起止(UTC / 北京) 15:40:10.906Z → 15:40:16.227Z / 23:40:10 → 23:40:16
reason legacy_account_identity_conflict: resolve reading-generated IDs before syncing business records
failed / datasets 1 / [](0 个数据集)
source / bridgeUsed old-api/WXAPP / false
accounts 前置扫描 source 750 / created 0 / matched 745 / missing 0 / conflicts 172 / excluded 4 / identityConflicts 1
nodes 前置扫描 source 461 / created 0 / matched 461 / missing 0
existingAccountBalancesUntouched true
settlementReady 未设置(按设计为 false)

5 分钟重试序列(全部 blocked,只记录、不干预):

时间(北京) 原因
23:00 / 23:10 / 23:20 / 23:30 / 23:40 legacy_account_identity_conflict(主 runId 报告被覆写)
23:05 / 23:15 / 23:25 / 23:35 another_sync_running(并发/服务端租约占用)

another_sync_running 与服务端租约占用均按约束仅记录,未抢占租约、未删除目录锁。目录锁在运行器各次重试之间自行释放;23:40 观测到一次仍在运行的重试进程与短暂存在的锁目录,未对其做任何处置。

排除在终态判定之外的记录(不把下午/凌晨人工批次当 23 点运行):

文件 / runId 时间(北京) 状态 排除理由
2026-11-02-direct-22a1d53e-4943-4902-934e-85d8e0e60006.json 11-03 20:54 already_completed 傍晚补跑/人工批次,业务日仍为 2026-11-02,仅回读既有成功回执,不是当晚 23:00 运行
12f01ee1-90b8-46d5-8f5a-73fe95515ee0 11-02 23:00–23:39 completed-with-preserved-conflicts 上一业务日成功回执,仅作基线比对

四、服务端只读回执(仅 action:'status')

查询方式:node --env-file=<凭据文件> tmp/direct-v1-status-check.mjs(只发 action:'status',不建锁、不抢租约、不启动同步;输出对 token/secret/key/password/session 类字段脱敏)。全程未读取或输出凭据内容。

项目 服务端 本机
businessDate 2026-11-03 2026-11-03
runId 5f2ddc11-0139-4356-a2f6-052e1bfb5c33 同
status running blocked
startedAt 2026-11-03T15:00:11.147Z 15:00:07.605Z(首次)
finishedAt null 每轮重试有 finishedAt(仅表示单轮退出,非成功回执)
summary null 无(datasets 为空)
9 数据集 / 财务回读 无 无

服务端仅返回 10-29/10-30/10-31、11-01/11-02 与本次 11-03 的 run;11-03 无 finishedAt、无 summary,因此不存在可验收的成功回执。服务端 status=running 与本机 status=blocked 不一致,不满足「终态判定必须基于服务端回执 + 本机报告一致」的条件,故本轮不判定为终态。

五、验收清单逐项核验(全部不满足)

# 验收项 结果 证据
1 9 个业务数据集服务端业务 ID、主表与关联附表、校验和核验 未通过 9/9 未执行;无 reconciled、无 sourceIdChecksum/targetChecksum
2 每个业务编号恰有一份主表 未通过 无 allCapturedSourceIdsReconciled,无对账证据
3 账号只新增并匹配旧用户编号 未通过 前置扫描 identityConflicts=1,身份冲突未解决,业务投影被中断;created=0 但无法核验通过
4 栏目只补缺 未通过 前置扫描 461/461 / created 0 / missing 0,但未进入写入与回读核验
5 财务分组(会员流水 stype=1/2/3/4)回读核对 未执行 datasets=[],无 finance 字段、无 reconciled
6 failed=0 未通过 本机每轮 failed=1
7 锁已释放 未通过(服务端租约仍占用) 服务端 run status=running、finishedAt=null;目录锁在重试间隙释放,本轮未删除任何锁
8 来源 old-api/WXAPP 且 bridgeUsed=false 元数据一致但不构成成功 两份报告均标注该来源与 false,但未走同步桥
9 保留新系统修改、余额、课时、人工确认、复习计薪凭据 未被破坏 existingAccountBalancesUntouched=true;未发生业务写入;冲突仅记录、不自动解决

9 个数据集明细(全部 executed=false / reconciled=false):专项训练、词库、课程绑定、每日学习、练习记录、抗遗忘、预约、上课、测评。

六、监测过程与终态判定

  • 监测窗口:23:07–23:41(北京),按 10 分钟间隔轮询 4 次(23:07 / 23:17 / 23:27 / 23:37),只读检查本机报告、服务端 status 与 launchd 计数。
  • 4 次轮询状态零变化:服务端始终 running/finishedAt=null;主报告始终 blocked / legacy_account_identity_conflict / identityConflicts=1 / failed=1 / datasets=0;runs 由 3→5→7→9(23:40 收尾时为 10),last exit code 恒为 1。
  • 按 2026-10-31 的既有先例(确定性阻塞项、4 次轮询零变化后定论),在 40 分钟观察窗后收尾,未耗尽 120 分钟上限:该阻塞需人工核实处置,自动重试不会自行解除,继续等待不改变「无成功回执」的事实。
  • 终态判定:未出现终态。分类 incomplete_blocked / failure_no_success_receipt;不宣称同步彻底失败(重试仍在进行、租约仍被持有),但按「没有服务端真实回执就报失败/未完成」如实报告未完成。
  • 失败原因已定位到实际日志:legacy_account_identity_conflict,新增 1 处阅读账号生成的编号与旧系统身份冲突(11-02 时 identityConflicts=0)。

七、与上次状态的差异

维度 2026-11-02(上次核查) 2026-11-03(本次)
终态 completed-with-preserved-conflicts(成功回执) 未出现终态,incomplete_blocked
服务端回执 finishedAt 非空、summary 完整 finishedAt=null、summary=null
9 数据集 / 财务 9/9 reconciled=true,财务 rows 42,282 reconciled=true 0/9 执行,财务未执行
failed 0 1(每轮重试)
阻塞项 无 legacy_account_identity_conflict
账号 source / conflicts / identityConflicts 749 / 170 / 0 750 / 172 / 1
runs / last exit code 2 / 0 10 / 1
变化分类 — success_to_failure_new_identity_conflict,严重级别:重大

八、通知与后续

  • 通知:是。 触发条件为「由成功转为失败的重大失败变化」:上一业务日取得完整成功回执,本业务日真实 23:00 触发后即被账号身份冲突阻断、9 个数据集全未执行、服务端无回执;阻塞项由 identityConflicts=0 变为 1,与上次状态不同。
  • 待办(需人工,非本轮执行): 核实并处置 1 处阅读账号编号与旧系统身份冲突,可参照 2026-10-31「撤销伪编号 + 结案冲突」的非破坏性处理路径。冲突只记录、不自动解决。阻塞解除后,同一 runId 可在后续重试中续跑;届时须重新按第一节的验收清单核对服务端回执。
  • 持续风险提示: 该任务依赖这台 Mac 开机并登录该用户;关机或未登录当日不会有运行与回执。服务端租约仍由该 runId 持有,零点后的重试可能因 another_sync_running 继续被阻断;工资结算所需新鲜度高于本任务的一日一次节奏,settlementReady 按设计始终为 false。

九、交付物

  • 本机心跳:~/.local/state/xiaoshu/legacy-sync/heartbeat-23-status-2026-11-03.json(0600,含业务日、runId、终态、失败原因、9 数据集与账号/栏目补缺核验、差异、通知判定,不含任何凭据)
  • 本机运行报告:~/.local/state/xiaoshu/legacy-sync/2026-11-03-direct-5f2ddc11-0139-4356-a2f6-052e1bfb5c33.json(0600)
  • 核查记录:本文件 docs/migration/nightly-legacy-sync-check-2026-11-03.md