范围 = 本线(插件投放与分库线)产物 + 记忆类,共 27 件:
- 接续入口_插件投放与分库线(1 件):§0 新增 22:44 拍板行;§2 第 36 棒范围改 5 步、条件步转无条件
- 交付物(22 件):MCN 数据面接入阶段一/阶段二系列(含 B 案落地与 shadow 读数)、
P0 修通与移动端真机验收、pnpm-EPERM、两机 lib 差异、共享层台账语义、
基础插件身份与回滚、插件接入验收、插件数据面取数口、移动端迁包与字号扩面、跨机错误消息
- 记忆(4 件):2026-09-24 / 2026-09-25 日志、MEMORY.md、本棒 automation 执行记录
⛔ 未含他线在途改动(只报告、不代提交):机制层 CODEBUDDY.md / state.py /
.codebuddy/rules/server-ops.md、接续入口_IM线、接续入口_StoryForge验收线、
其余 29 个 automation 目录、docs/规则与载体/、归档/、接续包_*。
30 KiB
MCN 数据面接入 · 阶段二 · B 案落地与 shadow 读数(第 35 棒 · 执行棒)
会话:
p35-exec-plugin-dataline(2026-09-25 21:47 开工 → 22:5x 收口) 工作区:E:/ProgramData/AIProject/aliyun-dsh-server(本件落交付物/) 上游:入口接续入口_插件投放与分库线_20260922.md§0 最新行 + §2「⏭️ 本轮动作(第 35 棒)」 唯一执行单:$DOC/05-交接单/插件投放与分库线-04MCN数据面接入改造-阶段二第三批.md(§五 S0–S8 / §六 A1–A9) 依据件:$WS/交付物/MCN数据面接入-阶段二-第三批接线完成-20260925.md(第 34 棒) 变量:PKG=D:/dshworkspace/plugin_package/dsh-plugin-mcn-suite|WS=E:/ProgramData/AIProject/aliyun-dsh-server|DOC=D:/github/dsh_shenxian/dsh-server-docs
〇 结论(3 行)
- ① – ⑤ 全部达成(处方 (a) 落码 → 出包
0.5.0→ 上池 → 加列迁移 2 条 → 回填),A2(取数口面)达成、A1 两表达成、A3/A4/A6/A7/A9 达成。 - 🔴 ⑥ 未全绿 ⇒ 按执行单 §五 S6/S7 与任务书铁律,停住不切档(⛔ 不带病切换),⑦ 整条留给下一棒;A5 未达成、A1 的
account_video_source一支具名未达成、A8 如实记「两机不一致」。 - 🔴 根因两条已钉死(均非数据丢失,均非本棒引入):甲=本地 5 组重复
aweme_id⇒ 计数 39 ≠ 34(平台主键唯一 ⇒ 必然折叠);乙=平台jsonb重排对象键序 × 插件canonicalJsonText()保留序 ⇒ 逐键比对假阴性(换成「与序无关」比对 ⇒ 34/34 全等)。
归属:本棒已动生产(47 共享层投放 + 平台库 2 条
ADD COLUMN+ 存量回填),未动实例本地库、未重启任何服务、未切任何档。 🔴 本棒不 commit / 不 push —— 用户 2026-09-25 22:44 已拍板「不纳入版本管理」(§5-②)⇒ 本条由"待定"转为长期有效;源码保底改为定期打包到E:/dsh-backups/plugin-src/(见 §5-②、§六)。 ✅ 两条待拍板已于 22:44 全部到手(① ⇒ A 案删本地 5 条旧副本;② ⇒ B 案不纳管 + 定期打包备份,机制已落地)⇒ 第 36 棒 ⑥ 可闭环、⑦ 可执行。
一 本棒动作逐条状态(按序 · 与任务书 ①②③④⑤⑥⑦ 一一对应)
| # | 动作 | 状态 | 一句话读数 |
|---|---|---|---|
| ① | 落 (a) 处方代码(正文列 gzip 编解码落 store.js 的 normalizeRow/rowsOf) |
✅ 达成 | 新增 GZIP_COLUMNS/GZIP_PREFIX="gz1:"/gzipToJsonText/gunzipIfPrefixed/restoreGzipText/restoreGzipColumns/packOversizedRow + jsonbLike() 补正;编解码只在插件侧,调用方零改动。单测 66/66(# pass 66 / # fail 0)、node --check 9 文件全 rc=0 |
| ② | 出包 0.4.0 → 0.5.0 |
✅ 达成 | dist/dsh-plugin-mcn-suite-0.5.0.tgz 2,017,667 B/条目 324/md5 5cbccac1348e5dcb8d11bf400a000498 |
| ③ | 上池 → 发布共享层 | ✅ 达成 | POST /api/plugins/business →200(compat.level=ok)⇒ 迁移到 state=ready ⇒ POST /api/plugins/business/share →200 action:"replaced" version 0.5.0 |
| ④ | 加列迁移 2 条 ADD COLUMN(hot_accounts.local_id / account_videos.local_id,可空) |
✅ 达成 | elapsedMs:16、backup:"taken"(/opt/dsh/backups/plugin-db/dsh-plugin-mcn-suite/v1-2026-09-25T14-06-56-401.sql);库读数 hot_accounts 17 列/5 行、account_videos 20 列/362 行、account_video_source 9 列/18 行;台账 state: ready、对账 clean:true;⛔ 不删库、不重灌 |
| ⑤ | 重跑迁移回填 local_id |
✅ 达成 | dry-run DRY_WRITE_CALLS=0;apply:account_video_source ins=16/skip=23、account_videos skip=362/backfill=362、hot_accounts skip=10/backfill=5、失败 0;幂等重跑 ins=0;本地库 sha256 b37f8aab… 前后逐字一致、mtime 未变 |
| ⑥ | 三表 shadow 读数(全 match=true 才允下一步) |
🔴 未全绿 | account_videos match=true(362/362)/hot_accounts match=true(5/5)/account_video_source match=false(platform 34 / local 39)⇒ 停住不切档 |
| ⑦ | 切档 + 重启验收(三表 → platform;47 实例 + 106 合并窗口;A2 E2E + A5 真机读数) |
⛔ 未执行(整条留下一棒) | 前置 ⑥ 未全绿 ⇒ ⛔ 未切任何表、⛔ 未重启 47、⛔ 未触碰 106;实例 data-plane.json 仍 4 表 platform(account_persona/creative_log/account_analysis/video_analysis),三表仍 local |
⚠️ 本棒未按任务书原意走到 ⑦ —— 依据是任务书自己写的判据:「⛔ 若 ⑥ 未全绿 ⇒ 停住不切档(⛔ 不带病切换),如实上抛,⑦ 整条留给下一棒。」
二 判据表 A1–A9(命令 + 输出原文 + 退出码 · 可被第三方复现)
探针环境:
ssh [email protected];node =/usr/local/bin/node(--experimental-sqlite);探针包/tmp/p35/pkg(指纹逐字等于本机与共享层)。 🔴 R10 说明:实例 uid(dsh-cce6d1cdb376430480f0)被平台网络隔离(实测连127.0.0.1:3080都ECONNREFUSED,而 rootcurl= 200)⇒ 探针只能以 root 跑,故一律DSH_HOME重定向到/tmp/p35/dshhome(实例 home 零写入)+ 本地库readOnly打开。
A1 存量迁移一致性
# [真机 47] root + DSH_HOME 重定向;探针 run-p35.mjs §4
node --experimental-sqlite /tmp/p35/run-p35.mjs # 退出码 0(RUN_RC=0)
A1 [account_video_source] 本地键=39 平台行=34 onlyLocal=[] onlyPlatform=[] truncated=false match=true
A1 [account_videos] 本地键=362 平台行=362 onlyLocal=[] onlyPlatform=[] truncated=false match=true
A1 [hot_accounts] 本地键=5 平台行=5 onlyLocal=[] onlyPlatform=[] truncated=false match=true
☝️ 这是探针自算的「主键集合」判据(
onlyLocal/onlyPlatform皆空 ⇒ 唯一键集合逐字一致)。
# [真机 47] 插件自身的影子读口径(compareRows:计数 + 主键集合)
node --experimental-sqlite /tmp/p35/run-p35.mjs # 退出码 0
[mcn-store] shadow what=probe35.account_video_source platform=34 local=39 match=false onlyPlatform=[] onlyLocal=[]
[mcn-store] shadow what=probe35.account_videos platform=362 local=362 match=true
[mcn-store] shadow what=probe35.hot_accounts platform=5 local=5 match=true
判定:🔴 部分达成 —— 两表 本地 n == 平台 n ✅;account_video_source 本地 39 ≠ 平台 34 ⇒ 未达成(具名:5 组重复 aweme_id,见 §三-甲)。
badRows:三表 全 0(⛔ 无空键、无坏行);空 aweme_id 行数 0(执行单 §附录 C-2 预计"非零" ⇒ 实测为零,具名纠正)。
A2 三表读写 E2E(平台取数口)
# [真机 47] 临时会话(mksess.cjs 直插,TTL 600s)+ Host/Cookie 垫片
bash -s < tmp/p35/remote-09-a2.sh # 退出码 0(A2_DONE)
### 0) 取数口就绪态
{"ok":true,"pluginId":"dsh_plugin_mcn_suite","available":true,"reason":null,
"dbName":"dshs_pl_dsh_plugin_mcn_suite",
"tables":["hot_accounts","hot_account_ext","account_videos","video_analysis","account_video_source",
"account_persona","account_analysis","creative_log","rewrite_log","storyboard_log","script_review"]}
=== ① hot_accounts(PK=account_name) === 7 步 全 HTTP=200(读空→建→读回→改→读回→删→读空)
=== ② account_videos(PK=aweme_id) === 7 步 全 HTTP=200
=== ③ account_video_source(PK=aweme_id,两个 json 列) === 7 步 全 HTTP=200
3 读回 ⇒ {"content_json":"正文 E2E","analysis_json":"分析 E2E", ...} # jsonb 脱一层引号,存储形态假设成立
=== ④ 负例(应全 bad-args) ===
N1 写他人 user_id HTTP=200 {"ok":false,"reason":"bad-args","detail":"不得写入他人的 user_id(归属列由内核注入)"}
N2 缺主键列 HTTP=200 {"ok":false,"reason":"bad-args","detail":"缺少主键列「account_name」(它是本表的行标识)"}
N3 带内核审计列 HTTP=200 {"ok":false,"reason":"bad-args","detail":"审计列「created_at」由内核维护,⛔ 不可自写"}
N4 未知表 HTTP=200 {"ok":false,"reason":"bad-args","detail":"未知表「nosuch_table」"}
N5 未知列(过滤) HTTP=200 {"ok":false,"reason":"bad-args","detail":"未知列「nosuchcol」(表「account_videos」)"}
N6 未知列(写入) HTTP=200 {"ok":false,"reason":"bad-args","detail":"未知列「nosuchcol」"}
⚠️ 该脚本尾段(PG 残留核查)首轮因内嵌
node -e的引号/反引号被 bash 吃掉而报语法错误未执行(bash: line 79: syntax error near unexpected token ')')—— 已按「把 node 脚本抽成独立.mjs上传执行」重做,本轮补齐(见 A2-附)。
A2-附 PG 侧残留核查(补齐 · 退 0)
node --experimental-sqlite /tmp/p35/diag-src3.mjs # 退出码 0(DIAG3_RC=0)
### J) A2 收尾:PG 侧残留核查(应全 0)
PG_RESIDUE hot_accounts (cols=account_name,local_id) = 0
PG_RESIDUE account_videos (cols=aweme_id,local_id,account_id) = 0
PG_RESIDUE account_video_source(cols=aweme_id,video_id) = 0
PG_TOTALS={"a":"5","b":"362","c":"34"}
判定:✅ 达成(平台取数口面) —— 三表 7 步读写 全 200、6 个负例全 bad-args、0 行返回 {ok:true,value:[]}、写入残留 0。
⚠️ 「实例内」那一半仍未达成(执行单 A2 原注:「实例内读数需 47 重启 ⇒ 未重启则该条未达成」)⇒ 随 ⑦ 留给下一棒。
A3 结构改写面处置完毕
grep -rniE "\bJOIN\b" lib | grep -v "\.join(" # 残留全落在 local() 回调 / 本地专属分支 / 第四批主表 rewrite_log(具名豁免)
grep -rn "LIMIT ? OFFSET ?" lib
grep -rnE "ROW_NUMBER|OVER\s*\(" lib
判定:✅ 达成(第 34 棒已验并复扫;平台档路径零命中;本棒未改任何调用点 ⇒ 读数逐字不变)。
A4 表名对齐彻底
cd "$PKG"
grep -rE "account_video_analysis" . | grep -v /node_modules/ | wc -l # → 0
grep -c "hot_account_ext" lib/host/mcn/store.js # → 10
判定:✅ 达成(0 / 10 > 0)。
A5 已按表切档(三张表)
# [真机 47] 读该用户 <home>/.dsh/data-plane.json
cat /var/lib/dshs/users/cce6d1cd-b376-4304-80f0-0e1c58c9ffde/home/.dsh/data-plane.json
INSTANCE_DP_UNCHANGED={"tables":{"account_persona":{"writeMode":"platform","mode":"platform"},
"creative_log":{"writeMode":"platform","mode":"platform"},
"account_analysis":{"writeMode":"platform","mode":"platform"},
"video_analysis":{"writeMode":"platform","mode":"platform"}},"updatedAt":"2026-09-25T09:07:28.440Z"}
PLANE={"tables":{"account_video_source":{"mode":"shadow"},"account_videos":{"mode":"shadow"},
"hot_accounts":{"mode":"shadow"}},"updatedAt":"2026-09-25T14:12:06.586Z"}
☝️ 第一个是实例真档(仍 4 表);第二个是探针档(
DSH_HOME重定向到/tmp,只用来取 shadow 读数)—— ⛔ 探针档不是实例档,两处别混。
判定:🔴 未达成 —— 三表仍 local(总数仍 4 表 platform,非 A5 要求的 7 表)。原因 = ⑥ 未全绿(依铁律停住)。
A6 旧库备份在位 + 零数据损失可回滚
# [真机 47]
sha256sum "$HOME/.dsh/mcn-plugin.db" | cut -d' ' -f1 # 迁移前后各取一次
tar -tzf /opt/dsh/backups/plugin-data/dsh-plugin-mcn-suite/cce6d1cd-…-mcn-plugin-db-20260925-141436.tar.gz
b37f8aab51a90f7481eb321e50456ca347635bcf2bfce567ea4200d88c18277a # 迁移前
b37f8aab51a90f7481eb321e50456ca347635bcf2bfce567ea4200d88c18277a # 迁移后(逐字一致)
DB owner=dsh-cce6d1cdb376430480f0 mtime=2026-09-20 23:05:05.178301565 +0800 # mtime 未变
判定:✅ 达成 —— 备份在位可解出;本地旧库未被删、未被改(sha256 + mtime 双证)。
🔴 本棒新增一处 R10 修复(必须记):<home>/.dsh/data-plane.json 属主为 root:root(第 32 棒 root 探针遗留)⇒ 切档前必须先修,否则实例 uid 写不动档位。已 find "$UHOME" -user root -exec chown "$UOWNER:$UOWNER" {} + ⇒
ROOT_OWNED /var/lib/dshs/users/…/home/.dsh/data-plane.json root:root 644
ROOT_OWNED_AFTER_CHOWN=0
… data-plane.json owner=dsh-cce6d1cdb376430480f0:dsh-cce6d1cdb376430480f0 mode=644
ROOT_OWNED_FINAL=0
A7 移动端五条
判定:✅ 免跑 —— 本棒未改任何 UI 代码(lib/client.js 零改动;改动面恰 6 件:store.js/package.json/tests/mcn-store.test.mjs/(出包物)dist/*.tgz;调用方 0 处)。
A8 两机一致(代码面 / 运行面分开记)
# [47]
grep -m1 '"version"' /var/lib/dshs/bundled-plugins/dsh-plugin-mcn-suite/package.json
md5sum /var/lib/dshs/bundled-plugins/dsh-plugin-mcn-suite/lib/host/mcn/store.js | cut -d' ' -f1
grep -c "gz1:" /var/lib/dshs/bundled-plugins/dsh-plugin-mcn-suite/lib/host/mcn/store.js
"version": "0.5.0",
bc02c23c080eee58d8873508badc1c5b # 与本地 PKG 逐字一致
4 # 处方 (a) 已进共享层
# [47] 节点登记表(查 106 端点)
SELECT * FROM dsh_hosts;
HOST {"id":"w-47","endpoint":"http://127.0.0.1:19100",…,"status":"up","via":"local"}
HOST {"id":"w-106","endpoint":"http://127.0.0.1:19000",…,"status":"up","via":"relay"}
判定:🔴 不一致(如实记,⛔ 不得写「一致」) —— 47 共享层 = 0.5.0(本棒投放,已取证);106 本棒未触碰、未取证(w-106 仅经中继可见、端点是回环隧道,本棒无 106 作业面)⇒ 106 侧同步随重启窗口在下一棒做。
A9 红线零新增
cd "$PKG"
grep -rEn "CREATE TABLE|ALTER TABLE|DROP TABLE|better-sqlite3|from 'pg'|require\('pg'\)" . | grep -v /node_modules/ | wc -l
23
判定:✅ 达成(23,与第 27/28/29/33/34 棒同值;处方 (a) 只加运行时编解码,零新增 DDL / 驱动)。
产物指纹(report §八-6 要求)
| 件 | 指纹 |
|---|---|
lib/host/mcn/store.js |
md5 bc02c23c080eee58d8873508badc1c5b / 117,808 B / 纯 LF |
tests/mcn-store.test.mjs |
64,299 B / 纯 LF / # tests 66 / # pass 66 / # fail 0 |
dist/dsh-plugin-mcn-suite-0.5.0.tgz |
2,017,667 B / 324 条目 / md5 5cbccac1348e5dcb8d11bf400a000498 / npm shasum 4e025aba87a4c3edf6cb36e389c6f7ca1bcf873e |
package.json |
"version": "0.5.0"(仅 version + description 两字段与 0.4.0 桶不同) |
| 共享层(47) | …/bundled-plugins/dsh-plugin-mcn-suite/ version 0.5.0/store.js md5 同本机 |
三 🔴 ⑥ 未全绿的根因(两条 · 逐条取证 · 均非数据丢失)
甲|计数 39 ≠ 34 = 本地 5 组重复 aweme_id(平台主键唯一 ⇒ 必然折叠)
node --experimental-sqlite /tmp/p35/diag-src.mjs # 退出码 2(尾段平台读撞会话过期;甲段已跑完)
LOCAL_TOTAL=39
DUPKEY aweme_id=7658997937279683855 rows=2 ids=[20,40] 正文全同=false 分析全同=true
DUPKEY aweme_id=7648947073131625905 rows=2 ids=[27,28] 正文全同=false 分析全同=true
DUPKEY aweme_id=7667477088350044069 rows=2 ids=[29,44] 正文全同=true 分析全同=true
DUPKEY aweme_id=7631176055600527729 rows=2 ids=[31,42] 正文全同=true 分析全同=true
DUPKEY aweme_id=7629803455813243043 rows=2 ids=[32,46] 正文全同=true 分析全同=true
DUP_SUMMARY 组数=5 冗余行数=5 组内完全一致=3/5 唯一键数=34
- 本地
account_video_source39 行 = 34 个唯一aweme_id+ 5 个历史副本;平台主键(user_id, aweme_id)唯一 ⇒ 平台只能有 34 行。 - 5 组里 3 组两个副本逐字全同;2 组(
…9683855、…625905)只有正文差 2 字节(分析列全同)。 - 🔴 本表按
id累积历史版本、读路径取最新(store.js注释与本地 SQL 一致:… WHERE video_id=? OR (aweme_id IS NOT NULL AND aweme_id=?) ORDER BY id DESC LIMIT 1;另有两处是IN集合索引/COUNT(*)>0布尔)⇒ 旧副本对读取不可见;平台档下findVideoSources亦按主键取单行 ⇒ 行为等价。 - ⚠️ 但这不等于可以自决删数据:要与 A1 判据(
本地 n == 平台 n)对齐,只能删本地 5 行冗余副本(不可逆)或改判据(须回规划棒)⇒ 见 §5-①(待拍板)。
乙|逐键内容 23/34 不等 = jsonb 键序重排 × canonicalJsonText() 保留序(假阴性)
node --experimental-sqlite /tmp/p35/diag-src3.mjs # 退出码 0(DIAG3_RC=0)
### H) 与序无关的深度相等(本地该键 **最新一行** vs 平台读回)
### H_SUMMARY 唯一键=34 正文+分析 序无关全等(最新一行)=32 序无关全等(任一本地副本)=34 仍有差异=0
### I) 交叉表:`gz1` 形态 vs 与序无关相等
FM aweme_id=7642280101581146850 PG_content[type=string gz1=true ] 序无关相等=true PG_analysis[type=null …]
FM aweme_id=7648968851887115563 PG_content[type=object gz1=false] 序无关相等=true PG_analysis[type=null …]
FM aweme_id=7628138993386034792 PG_content[type=object gz1=false] 序无关相等=true PG_analysis[type=object …]
# [真机 47] PG 地面真值:jsonb 值类型分布
SELECT jsonb_typeof(content_json), jsonb_typeof(analysis_json), count(*) FROM p_…_account_video_source GROUP BY 1,2;
PG_TYPE content=string analysis=string rows=6
PG_TYPE content=object analysis=null rows=3
PG_TYPE content=string analysis=null rows=3
PG_TYPE content=object analysis=object rows=20
PG_TYPE content=string analysis=object rows=2
gz1=true(落成 jsonbstring)的行 ⇒ 逐键match;gz1=false(落成 jsonb 对象)的行 ⇒ 逐键match=false,11 / 23 两侧完全对得上(jsonb_typeof=string的行数恰为 11)。- 换成与序无关的深度比对 ⇒ 34/34 全等、仍有差异 = 0 ⇒ 平台侧内容与本地逐字段完全一致,不存在内容丢失。
- 🔴 机制:PostgreSQL
jsonb会按"键长度+字母序"重排对象键;而插件canonicalJsonText()是JSON.stringify(保留键序)⇒ 只要值以 jsonb 对象形态落库,读回后 canon 必然与本地文本不等。 - 🔴 这是真缺陷(不是验收口径问题):
canonicalJsonText()还被- 迁移幂等 / 稳定键生成、
imports.js的**「同视频+同内容 ⇒ 去重」**判据(… AND content_json=?的平台档对应实现)、imports.js的预览判据(sr.ok分支) 共用 ⇒ 切到platform档后,同内容会被判成不同内容(倾向于重复写入,R11 净变差)⇒ 必须在切档前修(修法 = 递归按键排序后再序列化;技术项 ⇒ 自决)。
丙|附带纠正与澄清(防止后棒按错记开工)
| 项 | 旧记 | 实测纠正 |
|---|---|---|
account_video_source 空 aweme_id 行数 |
执行单 §附录 C-2「预计非零」 | 0(badRows 三表全 0) |
CONTENT … 同=12 异=27(第 35 棒中途读数) |
疑似内容丢失 | 假阴性 —— 该读数的 analysis 长度打印串是 String(obj) ⇒ 恒为 "[object Object]"(15 字),是探针自身的量测坑,⛔ 后棒别拿它当结论(已在本件用 PG 地面真值 + 与序无关比对推翻) |
| 会话 TTL | — | mksess.cjs 的临时会话 TTL = 600 s ⇒ 长探针必须现场新建,否则处处 401(本次撞过一次,报 not-registered / unauthorized) |
四 未闭合项(逐条「现象 / 归属 / 下一步」)
| # | 现象 | 归属 | 下一步 |
|---|---|---|---|
| 1 | account_video_source shadow match=false(34 vs 39,5 组重复键) |
规划面判据 + 本地数据(⛔ 非平台侧、⛔ 非插件逻辑) | 待拍板(§5-①)⇒ 定后由下一棒执行 |
| 2 | canonicalJsonText() 键序敏感 ⇒ 平台档判据假阴性 |
插件侧(store.js) |
技术项 · 自决 ⇒ 下一棒修 + 出包 0.5.1 + 重投 + 重取影子读数 |
| 3 | ⑦ 切档 + 重启验收整条未执行(47 实例 + 106 合并窗口) | 本棒(有意停住) | 下一棒(窗口已获用户批准,见 §0 21:33 行) |
| 4 | A2「实例内」那一半未达成 · A5 未达成 | 同 3 | 同 3 |
| 5 | 106 共享层仍为旧版(两机不一致) | 部署面 | 下一棒随重启窗口同步 |
| 6 | hot_accounts / account_videos 的 local_id 回填已到位,但「映射改优先平台」未做 |
插件侧(第 31/32 棒遗留 ㈦ 的部分缓解) | 下一棒(restoreLocalId 已让 row.id 在平台档可用) |
| 7 | 插件包源码仍未纳入版本管理(?? 未跟踪) |
用户拍板项 ㈣ | 待拍板(§5-②) |
| 8 | 共享锁目录曾出现非本线遗留物(.exec-lock/OWNER = __st_other_1879;.locks/修域锁释放缺陷-…) |
他人 lane | 按 R9 ⛔ 不删锁、不接管;本棒收口时 .exec-lock 已自然消失(本会话已复核) |
五 待拍板(自包含 · 一轮一问 · 每条带优缺点 · ⛔ 不在接续棒内自决)
✅ 两条均已于 2026-09-25 22:44 由用户拍板(原提问与优缺点保留在下方,供追溯):
- ① ⇒ A 案:删掉本地那 5 条旧副本(不可逆 · 已授权)。执行要求(已写入第 36 棒):先原样导出留档(
tmp/p36/)+ 打印清单 → 再删 → 删后本地account_video_source应 = 34 行;⛔ 只删行、⛔ 绝不删本地库文件mcn-plugin.db、⛔ 不删db.js、⛔ 不重建库。- ② ⇒ B 案:不纳入版本管理,改为定期打压缩包备份到固定目录。已由第 35 棒会话落地:固定目录
E:/dsh-backups/plugin-src/(backup.sh+ 基线包mcn-suite-src-20260925-2246-v0.5.0.tgz/6,065,179 B/330 文件/md5247dd1456597e5496a695f4e91d695dc/内容摘要9c38cdb4…)+ 每周自动备份 automation1e3c9070-a75d-4ae4-b81e-06e2eb20a5b4(周日 03:30 · 内容摘要去重「未变则跳」· 保留最近 26 份)。⚠️ 该机制只防误删,不防同一块盘损坏(要防盘坏需再复制一份到别的机器/盘)。 ⇒ 第 36 棒起按已定执行,⛔ 不再重问这两条。
① 平台上「一个视频只能存一条来源记录」,本地却存了 5 组重复(同一视频两条)。要不要删掉本地那 5 条旧副本,好让两边数量对齐?
为什么得由你定:这一步要么动实例里的真实数据(删 5 行,不可逆),要么放宽这条验收判据。两条路都对「这台机器上那位用户的资料」有实际影响,且没有客观更优的一方 ⇒ 属边界外。现在不决定也可以 —— 现象已具名,平台侧内容 34/34 与本地逐字段一致(已实测),没有数据丢失;只是「切换开关」这一步卡住不动,第三批就到不了终点。
- A 案|删本地 5 条旧副本(保留每条视频最新那一份) 优点:一次做完、验收判据如实达成;对读用户无可见影响(读路径本来就只取最新那一份,多出来的旧副本从来读不到)。 缺点:不可逆(只能靠备份回滚);其中 2 组的旧副本正文与最新副本差 2 个字符,删了就没了。
- B 案|不删数据,改判据为「同一视频只算一次 + 逐条内容比对」
优点:零数据变更,风险最低。
缺点:改的是规划棒定死的判据(
本地 n == 平台 n),按规矩要回规划棒再改一次单子;且今后每台机器都得靠这条新口径解释。 - C 案|保持现状不动(继续停在
local档) 优点:今天什么风险都不担。 缺点:第三批永远到不了终点,本地库与平台库长期并存、两处结论会越走越远。
我的倾向:A 案(可推翻)—— 5 条旧副本对读取不可见、删除前有备份 + 我会先出逐条清单;⚠️ 但它不可逆,所以必须你点头我才动。
② 这次改的插件源码(近一个月、十几个文件)要不要纳入版本管理?
为什么得由你定:这决定「以后回滚靠什么」—— 是靠 git 记录,还是只能靠备份包。属影响面偏好,不是技术优劣。
- A 案|现在就纳入(把该目录加进仓库并提交) 优点:改动有版本留痕、可逐笔回滚、后续多会话协作可对账。 缺点:要动仓库与提交动作;该包目前形态(大文件+出包产物)需先定「哪些进、哪些不进」。
- B 案|暂不纳入(继续只靠 sha256 + 交付件留痕) 优点:不动仓库,零额外动作。 缺点:近一个月改动零版本留痕;一旦误删/误改,只能靠备份整包回退,无法定位到某一笔改动。
我的倾向:A 案(可推翻)—— 本线已连续 8 棒在同一批文件上改,留痕收益已超过成本。
⚠️ 其余存量待拍板项(㈠ 47 实例重启窗口 ✅ 已于 21:33 批准;㈡ 106 重启窗口 ✅ 已批准「可以合并那是 worker」;㈢
json列是否改声明 —— 本批不需要,留档)本棒一项未新增、未改动。
六 卫生声明
- ⛔ 未改
D:/github/dsh_shenxian/src/**(平台侧零改动)· ⛔ 未改im.ts· ⛔ 未改装配协议。 - ⛔ 未删 本地旧库
mcn-plugin.db(sha256 + mtime 双证未变)· ⛔ 未删db.js· ⛔ 平台库未删未重建。 - ⛔ 未重启任何服务(47 实例 / 106 全未触碰)· ⛔ 未逐表切档。
- ⛔ 未 commit / 未 push(见 §5-②)。
- ⛔ 未改
D:/dshworkspace/plugin_package/dsh-plugin-mcn-suite/以外任何工作区文件(本棒另动的三处均为本线自有文档:本工作区交付物 + 本线入口 + 文档库05-交接单/README.md)。 - ✅ R4 卫生:临时会话已清理(
DELETE FROM sessions WHERE user_agent='poc-curl2'⇒SESSIONS_BEFORE=7 / SESSIONS_DELETED=7 / SESSIONS_AFTER=0)。 - ✅ 真机产物已清:
/tmp/p35*、/tmp/mksess-guest.cjs全删(TMP_P35_CLEAN);本机证据与探针脚本留在$WS/tmp/p35/(tmp 保留期 7 天)。 - ✅ R10 修复:实例 home 下
root:root属主配置已 chown 回实例 uid(ROOT_OWNED_FINAL=0)。
域锁
- 抢锁:
bash $DOC/07-scripts/handoff-guard.sh --claim-exec "p35-exec-plugin-dataline" --domains <9 键>⇒rc=0;复读断言:
OWNER: p35-exec-plugin-dataline / 开始:09-25 21:47 / ME:p35-exec-plugin-dataline
DOMAINS: mcn/store.js, dsh-plugin-mcn-suite/package.json, tests/mcn-store.test.mjs,
dsh-plugin-mcn-suite/dist, mcn/index.js,
aliyun-dsh-server/接续入口_插件投放与分库线_20260922.md,
aliyun-dsh-server/交付物, dsh-server-docs/05-交接单, aliyun-dsh-server/.workbuddy
- 开工门禁如实记账:
preflight-lock.sh对本棒 8 个目标路径全判【D】未归类 ⇒ 按字面rc=1;依第 26–34 棒既有惯例开工并报告,⛔ 未改那个跨库脚本。 - 释放:22:38 已带会话名释放(
ME="p35-exec-plugin-dataline" … --release-exec⇒RC=0;复核.locks/p35-exec-plugin-dataline/.exec-lock均已移除、find -name OWNER零命中、.locks/仅余空容器.migrations/)。随后为落两条拍板 22:44 二次抢锁(3 域:入口/交付物/.workbuddy,rc=0,OWNER 归属已断言),改完即再次带会话名释放。 - 备份(拍板②):固定目录
E:/dsh-backups/plugin-src/已建(脚本backup.sh+pkgs/+backup.log+.last.sha256);基线包mcn-suite-src-20260925-2246-v0.5.0.tgz6,065,179 B/330 文件/md5247dd1456597e5496a695f4e91d695dc;幂等实测:二次运行输出RESULT=SKIP_UNCHANGED且包数仍为 1(未新增)。每周日 03:30 自动执行(automation1e3c9070-a75d-4ae4-b81e-06e2eb20a5b4)。⚠️ 同盘备份只防误删,不防盘坏。
七 下一棒(第 36 棒)范围(已按上表登记)
✅ 本节已于 2026-09-25 22:44 按用户拍板改写(原为条件式;现两条拍板到手 ⇒ 条件步转无条件,范围见入口 §2「⏭️ 本轮动作(第 36 棒)」)。
- 🔴 修
canonicalJsonText()键序敏感性(技术项 · 自决;修法 = 递归按键排序后序列化)+ 补一条单测(jsonb 键序被打乱后仍判相等);node --test tests/mcn-store.test.mjs必须全过。 - 出包
0.5.1→ 上池 →(结构迁移到state=ready)→ 发布共享层(记条目 / 字节 / md5)。 - 删本地 5 条旧副本(执行拍板①):先原样导出留档(
tmp/p36/)+ 打印清单(表名/主键值/保留哪份/删哪份)→ 再删 → 删后本地account_video_source应 = 34 行。⛔ 只删行、⛔ 绝不删本地库文件mcn-plugin.db、⛔ 不删db.js、⛔ 不重建库。 - 重取
account_video_source影子读数 ⇒ 应转 两面对齐 34 = 34 + 内容判据全绿。 - 闭环 ⑥ + 执行 ⑦:三表逐表切
platform→ 47 实例 + 106 合并同一次窗口重启(窗口已批)→ 三表 E2E(A2 实例内面)+ 真机读数验 A5/A8。 - 收口:释放域锁(
ME=)· automation 置 PAUSED + 排期(⑤ 完成 ⇒ 不登记下一棒)· 入口§0/§2·05-交接单/README.md §一· 当日日志 · 交付件(A1–A9 附命令 + 输出 + 退出码)。⛔ 仍不 commit / 不 push。
变更记录:2026-09-25 22:5x 第 35 棒(执行棒 · 会话 p35-exec-plugin-dataline)落盘;纯 LF。