用户已确认使用这台 Mac。当前入口为 scripts/run-nightly-direct-sync.mjs,通过新系统的专用鉴权网关 xiaoshu/sync/direct-v1 读取此前成功使用的旧系统 WXAPP 接口。不经过同步桥,也不要求发布旧站程序。旧接口凭据由服务端配置读取,本机只持有专用超级管理员会话,不保存主密钥。
安装命令:npm run sync-worker:install-mac。安装器校验 Mac 时区为 Asia/Shanghai、凭据文件为 0600,并将独立运行文件复制到 ~/Library/Application Support/XiaoshuSync/,安装 ~/Library/LaunchAgents/cn.xiaoshu.legacy-direct-sync-nightly.plist。每天北京时间 23:00 运行;登录加载时补跑最近一个已到达的 23 点业务日期;休眠错过日历触发会在唤醒时补跑。失败每 5 分钟重试。电脑须开机并登录该用户,Codex 和聊天窗口可关闭。电脑关机不能按时同步。
node --env-file=/Users/mac/.config/xiaoshu/legacy-sync-nightly.env scripts/run-nightly-direct-sync.mjs --check
node --env-file=/Users/mac/.config/xiaoshu/legacy-sync-nightly.env scripts/run-nightly-direct-sync.mjs
launchctl print gui/$(id -u)/cn.xiaoshu.legacy-direct-sync-nightly
--check 只确认鉴权和同步服务身份。手工命令执行今天;系统任务使用 --scheduled,23 点前补上一业务日,23 点后执行今天。同一帐套、业务日期已成功时直接读取成功回执;失败沿用运行编号、缓存的源分页和写入计划续跑。目录锁和服务端租约共同防止重复并发。残留目录锁只有在确认 owner.json 中的进程已退出后才自动清理;进程仍存活或无法确认时停止,避免并发。
账号来源保护(2026-10-13):已删除及 SyncExcluded 账号跳过;reading-* 账号的数字编号不视为旧系统身份。发现编号冲突时记录冲突并停止后续业务投影,不能把真实学员的课程挂到阅读账号。阅读合并只接收显式核实为小树的来源;未核实、乍兔、未匹配及有歧义的账号保留待核验,不再自动生成小树编号。详见 账号清理验收。
同步范围:账号只新增并匹配旧用户编号、栏目只补缺;业务数据依次为专项训练、词库、课程绑定、每日学习、练习、抗遗忘、预约、上课、测评。现有账号资料和余额、人工开课分类、已准备的排课、新系统教学记录、已生成的复习计薪凭据均保留。新增账号需旧角色明确为学员、门店或陪练,不能隐式创建管理员;新密码随机生成,不迁移旧密码散列。
服务端保存真实读取页的编号和内容校验和,核对每条业务编号恰有一份主表及关联附表。写入为主附表与批次回执的同一事务,写后校验字段。保存完整投影指纹;只在新系统未修改时更新,指纹或微秒版本变化均记录冲突。网络重试复用批次结果。源数据分页期间变化时重新扫描该数据集。成功回执基于服务器再次核验,不以计数或客户端标志替代验证。冲突意味着有意保留新数据,不表示源内容与目标完全相同。
本机报告、分页缓存和 launchagent 日志保存在 ~/.local/state/xiaoshu/legacy-sync/,目录 0700、报告 0600。已成功运行的原始分页缓存保留 7 天后自动清理,报告继续保留,失败运行的断点不清理。凭据保存在 ~/.config/xiaoshu/legacy-sync-nightly.env(0600),不得提交或输出。线上函数备份保存于私有 state 目录。发布命令 scripts/deploy-direct-sync.mjs 只在发布进程内使用主密钥;定时任务不需要主密钥。
这是一日一次同步,不能代替工资结算所需的新鲜度和专项核验;不会设置 settlementReady,不会自动解决既有冲突。Codex 自动任务 23 仅核查 Mac 任务和真实回执,不再执行另一套桥同步。系统任务安装、同入口实跑、未来首次 23 点触发是三个不同验收项目;实际结果以私有运行报告和服务端回执为准。
本次安装与实跑结果见 2026-10-12 夜间同步验收:新增 53、更新 181、保留冲突 1,330、失败 0;同入口重复触发已验证。
时区固定 Asia/Shanghai,每晚 23:00 从旧系统读取并同步到新系统。客户继续使用旧站;保留新系统修改,记录冲突,不自动覆盖冲突、删除新系统记录或修改账户课时余额。
此前没有启用 23 点调度:本机 crontab 为空,没有小树 LaunchAgent 或已保存的 Codex 定时任务;仓库只有默认每 5 秒运行的 worker service 示例,不代表生产已经安装。不能读取远程服务器的调度器,因此不能断言所有服务器上都没有任务。
当日生产复查:旧同步桥健康接口仍 HTTP 404,当前帐套 LegacySyncCheckpoint 为 0,未解决冲突为 684,失败队列为 0。普通管理员访问同步状态返回 403;普通管理员不能作为同步执行账号。上次手动补同步和本地脚本验证不等于夜间任务上线。
随后使用已有有效超级管理员会话查询成功,云端明确返回 configured=false、bridgeReachable=false,所有数据集最近尝试和成功时间均为空。当前已将该执行会话保存到本机专用环境文件 /Users/mac/.config/xiaoshu/legacy-sync-nightly.env(0600),不包含主密钥;会话到期时间为 2027-09-09T04:36:34.414Z。账户权限不再是本次阻塞,桥部署与云端配置仍未就绪。不要把该环境文件提交或复制进报告。
已通过应用工具创建并回读当前聊天的每日 23:00 自动任务,ID 为 23。它检查正式任务运行结果;尚未上线时核查同步条件,满足后执行 npm run sync-worker:nightly,不满足就持久保存失败原因。此聊天任务依赖电脑开机和应用运行,不能替代服务器调度。
2026-10-11 首次夜间调度已触发:23:02 查询生产状态,仍未配置且当晚成功数据集为 0;正式运行入口返回 blocked / bridge_http_404,报告已保存。用户已选择由托管方代部署同步桥,交接要求见 托管方代部署工单。该工单和发布包已经准备,可直接交给托管方;尚未发送给外部联系人,也未取得托管方执行回执。
npm run sync-worker:nightly -- --check 仅验收前提;npm run sync-worker:nightly 执行一轮。运行报告默认保存在 ~/.local/state/xiaoshu/legacy-sync/,使用北京时间业务日期和唯一运行 ID,每次记录起止、状态、原因及各数据集计数;文件权限 0600。缺配置或接口故障也必须留下失败报告。
本机聊天任务使用支持 --env-file 的 Node.js 20.6+:node --env-file=/Users/mac/.config/xiaoshu/legacy-sync-nightly.env scripts/run-nightly-legacy-sync.mjs,不要把凭据写到命令行参数或输出中。2026-10-11 已实跑 --check,得到 blocked / bridge_http_404,失败报告已保存。8 项自动测试验证了 404/凭据过期/未配置/保护缺失时不写数据、多轮分页和依赖顺序、未追平不报成功、冲突保留及缺少对账证据不报成功。
运行器先检查健康服务身份、超级管理员凭据、签名 manifest 和冲突保护,再按固定依赖顺序分页,直到每个数据集 hasMore=false。最多 45 分钟、每数据集 200 轮。只读请求最多重试三次;写请求超时不盲目重发,下次通过服务器 checkpoint 续跑。并发运行由目录锁阻止;进程被强制杀死后的残留锁必须先确认原进程已退出再人工移除,不能直接强制并发。
当前云端代码只对部分教学记录有保护,尚未验收所有数据集“保留新修改”,不能仅凭健康恢复就启动覆盖同步。网关需实现并通过并发更新、主附表原子性、冲突保留、重跑幂等验证后,才可在 ops/sync/status 返回 syncProtection: { conflictPolicy: 'preserve-new', atomicProjection: true }。运行器缺少这一证据即停止,不能在客户端设置标记绕过。
同步后再次检查签名 manifest、失败和冲突;服务端须对各数据集做同水位业务 ID 集合与校验和核验,实际一致后返回每数据集 reconciled=true。仅计数相同或有检查点不足以通过。未解决冲突保留新数据并报告 completed_with_conflicts;没有对账证据报告 awaiting_reconciliation,均不宣称全部成功。
默认范围为栏目、词库、专项训练、课程绑定、每日学习、练习、抗遗忘、测评、预约、上课,共 10 个数据集。账户/余额/课时归新系统管理,当前网关明确拒绝 users 同步;旧站新增用户须另做只新增、身份匹配、禁止财务覆盖的接口验收后才能加入任务,不能直接放开原 users 全字段覆盖。
/xiaoshu-sync 独立应用;按桥 README 备份、预检。在桥和消费端准备就绪后安装 SQL 变更日志,验证健康、签名 manifest 和 11 个 changes 查询。--check 后执行一次真实同步。对 684 条现存冲突保留并分别复核,禁止自动标记解决。将仓库放到 /opt/xiaoshu-angular,环境放 /etc/xiaoshu/legacy-sync-worker.env,文件权限 0600,执行用户 xiaoshu 必须能读取。环境需含 XIAOSHU_SYNC_OPERATOR_TOKEN、XIAOSHU_SYNC_COMPANY_ID、XIAOSHU_FUNCTION_URL、XIAOSHU_LEGACY_SYNC_BASE_URL。执行:
sudo install -m 0644 deployment/systemd/xiaoshu-legacy-sync-nightly.service /etc/systemd/system/
sudo install -m 0644 deployment/systemd/xiaoshu-legacy-sync-nightly.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl start xiaoshu-legacy-sync-nightly.service
sudo systemctl enable --now xiaoshu-legacy-sync-nightly.timer
systemctl list-timers xiaoshu-legacy-sync-nightly.timer
journalctl -u xiaoshu-legacy-sync-nightly.service --since today
人工运行失败时先处理报告,不把 timer 已启用视为同步已成功。Persistent=true 允许主机恢复后补触发错过的运行;服务器必须支持该带时区的 OnCalendar 表达式,并以服务器实际 list-timers 输出验收。
直接同步新增四类会员流水(user_point_list 的 stype=1/2/3/4)。原九个业务数据集成功后,执行器按会员续跑财务分组,服务端保存原始分页、来源 ID、数量和校验和。完成回执必须同时通过九个业务数据集和财务分组的实际存储回读;缺少任何一个分组不得报成功。
补导只补流水,不重放充值、扣费和工资,不覆盖账户余额及新系统体验资格。旧接口存在 score/Score 字段差异,均保留原始行。原始 score_before 原样展示;旧接口未提供可靠的调整后余额时显示“未记录”,不从当前余额倒推。已有来源记录内容不一致时记录冲突并保留新库。
此次上线已更新独立 LaunchAgent 使用的 worker。许诺初中四账户人工核验完成,其中两类各 5 条,重复补导为 0,余额和工资未改变;这不代表当晚全量成功。原有账号身份冲突仍然是全量同步阻塞,必须继续按实际日志报告,不能以财务补导回执替代。