Files
dsh_ai1net_server/交付物/新包骨架-S2落地与四尺读数-20260926.md
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次)
- .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…),
  目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪
- .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/)
- .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*)
- .gitignore 补:备份件(*.bak-*)
- 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

155 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 新包骨架 · S2「空包两端落地」执行记录与四尺读数
- **线 / 棒次**:插件投放与分库线 · 第 **40** 棒(执行棒)
- **日期**:2026-09-26 | **会话**:`插件投放与分库线-40`
- **状态**:🟡 **S2 骨架已落地,装配/取数/回调三面绿**;🔴 **浏览器级未取到**(需客户端线起真壳)
- **唯一执行依据**:`05-交接单/交接单_包规格书_20260926.md`(§〇 路径约定 / §五 A 冻结规格 / §五 C 指针)
+ `交付物/功能打包到基础插件-分步实施方案-20260926.md` **§3.10.4**(逐步照做唯一权威)
- **判据**:一律调 S0 四把尺子(`交付物/验证脚本/`),**退出码即结论**:`rc=0` 绿 / `rc≠0` 红 / `rc=3` **未取到**(⛔ 3 不是绿)
---
## 一、本轮产出
### 1.1 新包位置与文件清单
**包根** = `E:/ProgramData/AIProject/dsh-plugin-ai1net/`(新建;沿用本机既有插件仓库惯例 `dsh-plugin-*`,
与 `dsh-plugin-carbon` / `-forge` / `-partment` 同级)
| 文件 | 字节 | 作用 |
|---|---|---|
| `package.json` | 1171 | 包身份 + **`dsh.bundle.patch`**(装载补丁)+ `dsh.client`(浏览器端声明) |
| `cordis.patch.yml` | 954 | 装载声明(`insert: { id: ai1net, name: @dsh-local/ai1net }`) |
| `lib/index.js` | 8405 | **host 半**:一条精确路径路由 + 一次事件订阅 |
| `lib/client.js` | 8974 | **client 半**:lazy-CJS 封包 + 一张骨架卡片 |
| `scripts/build.mjs` | — | 门禁/组装(零依赖;`--check-only` 只跑门禁) |
| `README.md` | — | 包自述(含"两端怎么装它"与自检命令) |
### 1.2 冻结口径(照规格书 §五 A4,⛔ 未自行改动)
| 项 | 值 |
|---|---|
| 包名 | `@dsh-local/ai1net` |
| pluginId | `ai1net`(= 装载条目 id = 配置命名空间) |
| 库名 | `dshs_pl_ai1net` —— ⚠️ **S3 才建**,本棒 ⛔ 未碰数据面 |
| 表前缀 | `p_ai1net_` —— 同上,本棒 ⛔ 未建表 |
### 1.3 骨架里**只有**两件事(⛔ 不写业务)
| 半边 | 内容 | 对应扩展点 |
|---|---|---|
| host | `connection.fetch.register({ path:'/api/ai1net/ping', methods:['GET'] })` + `settings/document-updated` 订阅(**骨架占位:只留痕**) | **E1**(交集内唯一服务端扩展点) |
| client | 挂官方 `plugins.item` 槽位的一张卡:一句说明 + 一个打探针的按钮 | **E2**(`dsh.client`) |
⚠️ 五个业务模块(多租户 / 模型管理 / 技能插件管理 / 覆盖网络界面 / IM 插件侧)**一个都没实现** ——
接口清单仍只在规格书 §五 A3,⛔ 本棒未在代码里预埋任何业务路径。
---
## 二、判据读数(原始输出摘要 · 全量见 `tmp/p40/尺读数-20260926.txt`)
| # | 判据(尺子) | 结果 | 原始证据(摘要) |
|---|---|---|---|
| **S2-1a** | `v-plugin.sh 装配` · **端 A 客户端形态**(桌面 profile **实件副本** + 追加本包) | ✅ **绿 rc=0** | `① 声明在 profile bundles:yes(该 profile 共 5 个 bundle)``② 自 profile 目录解析成功:…\dsh-plugin-ai1net\lib\index.js` `③ 装载补丁在位:cordis.patch.yml` |
| **S2-1b** | `v-plugin.sh 装配` · **端 B 平台形态**(`profiles/web` 键位建模 + `dependencies` 的 `link:`) | ✅ **绿 rc=0** | 同上三条;该 profile 共 7 个 bundle(官方 2 + 平台共享层 4 + 本包) |
| **S2-2** | `v-plugin.sh 取数`(**真实 import 本产物**) | ✅ **绿 rc=0** | `exportsOnModule: [PING_PATH, SKELETON_VERSION, apply, inject, name]`;四条 checks 全 `true`;`verdict: GREEN` |
| **S2-3** | `v-plugin.sh 回调`(**真实调用 `apply(ctx)`**,spy ctx) | ✅ **绿 rc=0** | `applyError: null`;`routeCalls: [{ call:"ctx.connection.fetch.register", args:["{\"path\":\"/api/ai1net/ping\",\"methods\":[\"GET\"]}"] }]`;`onCalls:[{call:"ctx.on", args:["\"settings/document-updated\"","<fn>"]}]` |
| **S2-3** | 封包契约门禁(`node scripts/build.mjs --check-only`) | ✅ **绿 rc=0** | 零顶层 import / 零顶层 export / 零顶层 require / 走 `__ModuleLoader__` / 交 `apply` + `inject` / **零 `exports.default`(R3)**;host 半:逐字 `inject = ['connection']`、零顶层 import、代码零 `webServer` 引用 |
| **S2-4** | `v-ui.sh` 浏览器级 | ⚠️ **未取到 rc=3** | `CDP 端 http://127.0.0.1:9330 不可达 ⇒ 本机当前没有运行中的真壳`。⛔ 本线不代启壳(启动器属客户端线) |
| — | `v-plugin.sh 运行` | ⚠️ **不成立(不计入绿)** | 尺子读到的启动日志 mtime = **2026-09-25T09:19** —— **早于本包存在**。本包从未参与该 boot ⇒ "无失败条目"是**空真**。⛔ 不当证据用(详见 §四) |
**S2-3 那条 `routeCalls` 是本棒最硬的一条证据**:它逐字记录了注册的**精确路径** `/api/ai1net/ping`
⇒ 规格书 §五 A2「桌面端只认精确路径、⛔ 无前缀匹配」这条门槛**在代码层被真实满足**。
---
## 三、负控:证明上面那几个绿**不是空绿**(`tmp/p40/负控记录-20260926.txt`)
⚠️ S0 的 `v-neg.sh` 靶子固定为 `@dsh-client/portal-first-screen` ⇒ 它只证明"**尺子**能变红",
**没有**证明"**本包**的绿不是空绿"。故本棒另做一遍,改坏点**只动 `tmp/p40/neg/` 里的副本**:
| case | 改坏点(单变量) | 改坏后 | 改回原件 |
|---|---|---|---|
| ① 装配 | 从沙箱 profile 的 `bundles` 里删掉本包那一行 | `rc=1` **红** | `rc=0` 绿 |
| ② 取数 | `inject` 去掉 `'connection'`(**就是那个静默 404 的坑**) | `rc=1` **红** | `rc=0` 绿 |
| ③ 回调 | 去掉 `ctx.on` 订阅 | `rc=1` **红** | `rc=0` 绿 |
⇒ ✅ **三面负控通过(改坏必红、改回必绿)**。
---
## 四、如实标注:未取到 / 不成立 / 刻意未做
| 项 | 状态 | 说明 |
|---|---|---|
| **浏览器级(`v-ui.sh`)** | ⚠️ **未取到** | 需**真壳在跑**。启动器 `…/dsh-ai1net-desktop/.workbuddy/_devkit/launch-desktop-dev-017.mts` **属客户端线**,本线不代启 ⇒ ⛔ **不折算成"已知"**。取数口:在客户端线窗口内起壳后跑 `bash 交付物/验证脚本/v-ui.sh`。⚠️ 规格书 §3 S2 的完成判据("两端都出现卡片 + JS 错误 0")因此**尚未达成**。 |
| **`v-plugin.sh 运行`** | ⚠️ **不成立** | 见 §二末行。可用日志早于本包 ⇒ 该面无法给出本包的任何信息。**须在真壳起来后的新 boot 日志上重取**。 |
| **真机投放(两端各起一次)** | ⛔ **本棒刻意不做** | 硬边界:⛔ 不碰「起实例 / 取身份 / 把包装进去」三件。本棒只做到"**两种形态的 profile 都能解析并装配它**"(沙箱建模,见 §五)。 |
| **`dist/` 组装产物** | ⛔ **验证后已移除** | `node scripts/build.mjs`(**全量组装**)已跑通 `rc=0`(产物=4 文件+逐文件 sha256 清单,原始输出在 `tmp/p40/组装-full.out`)。⚠️ **刻意不留 `dist/`**:`lib/` 与 `dist/lib/` 是同一份内容的两个副本 ⇒ 造**第二个真相源**(`scripts/build.mjs` 自己的文件头就警告这件事),且分发产物的形状应由 **S4** 定。⇒ 需要时一条命令重建。 |
| **负控用例覆盖** | ⚠️ 3/4 | `v-neg.sh` 的第四面(`运行`)依赖真启动日志 ⇒ 与上「运行面不成立」同因,无法在本机形成有效负控。 |
---
## 五、"两端"到底指什么(本棒的建模口径 · 冷读者必备)
🔴 **"两端"用的不是两套机制,是同一套**:两端的装配键**本来就是同一个** `dsh.profile.bundles`。
| | 客户端(桌面壳) | 平台侧(实例) |
|---|---|---|
| profile 位置 | `…/home-adapt/profiles/desktop` | `<userRoot>/home/profiles/web`(`profileDirOf()`,`plugin-assembly.ts:860`) |
| 装配键 | `dsh.profile.bundles` | **同一个键**(`readProfileManifest()`,`plugin-assembly.ts:72/75`) |
| 包怎么到位 | profile 目录下的 `node_modules` | `dependencies` 写 `link:` 指向共享只读包库(`sharedDirOf()`) |
⚠️ **因此本棒的沙箱是"照实件的键位建模",不是真机**:
- **端 A** = 真桌面 profile `package.json` 的**副本** + 追加本包(⛔ 未动真件 —— 该目录属客户端线 lane,
用户 2026-09-24 明令 + 本棒硬边界「⛔ 不改 `dsh-desktop-0.1.7rc2` 的任何文件」);
- **端 B** = 按 `profiles/web` 的键位手写的沙箱(含平台的 `link:` 依赖写法);
- 两端的 `node_modules/@dsh-local/ai1net` = **指向真包的目录软链**(= 平台侧 `link:` 的落地形态,
⛔ 不是复制)⇒ 尺子量到的**就是真产物**,不是替身。
⛔ **沙箱只证明"该形态的 profile 能解析并装配本包",不等于"真机上已装好"。**
---
## 六、硬边界自查
| 边界 | 自查 |
|---|---|
| ⛔ 不改官方 dsh 主程序与缓存(**R2**) | ✅ 未触碰 |
| ⛔ 不重造分发与更新机制 | ✅ 未动平台侧拉取器/对账;`README` 与 `cordis.patch.yml` 只**指向**既有协议(`plugin-assembly.ts`),⛔ 未复制其实现 |
| ⛔ 不碰「起实例 / 取身份 / 把包装进去」三件 | ✅ 未起实例、未取身份、未向任何实例投放;只做了沙箱 profile 的解析面 |
| ⛔ 不改客户端工作区 `dsh-ai1net-desktop` / `dsh-desktop-0.1.7rc2` 任何文件 | ✅ 只读;端 A 的 profile **副本**落在 `tmp/p40/`(真件的 mtime 未变) |
| 🔴 红线门禁(重启控制面 / 中断在线用户 / 批量 >10 文件 / 不可逆) | ✅ **均未触发** —— 未 ssh、未部署、未改任何生产文件;本棒新增 6 个文件(全在新包内)+ `tmp/p40/` 若干 |
| 🔴 停点:**S4 前必停**(P1 已于 13:30 拍板)|**S9 的 P2 仍待拍板** | ✅ 本棒在 **S2**,⛔ 未跨过任何停点 |
---
## 七、机制层观察(⛔ 未改任何跨库脚本 —— 属机制层须独占,R7/§6)
1. **`preflight-lock.sh` 对 7 个目标路径全判【D】未归类 ⇒ `rc=1` 拒开工**。
判决与本棒目标**全不匹配**(本棒压根不在它的 `ok_files` 覆盖范围内)⇒ 按第 26–40 棒既有惯例,
用 guard 锚点算法**自定域键**后开工,⛔ **未改那个跨库脚本**(改它就是机制层独占动作,须单独排)。
- 实际自定域键(10 个,guard 已复读确认):`aliyun-dsh-server/接续入口_插件投放与分库线_20260922.md`
|`aliyun-dsh-server/.workbuddy`|`aliyun-dsh-server/交付物`|`aliyun-dsh-server/tmp`
|`dsh-plugin-ai1net/package.json`|`dsh-plugin-ai1net/readme.md`|`dsh-plugin-ai1net/cordis.patch.yml`
|`lib/index.js`|`lib/client.js`|`scripts/build.mjs`
- ⚠️ **新包目录(`dsh-plugin-ai1net/**`)在 preflight 里必然落【D】** —— 它既不在文档库也不在工作区,
算法取"末两段"作域键。这是**既有算法对新仓库的固有盲区**,不是本棒引入的问题。
2. **非 ASCII 会话名 ⇒ 锁目录名被改写**:`.locks/插件投放与分库线-40` 实际落成
`.locks/________________________-40-2147666670`(非 ASCII 段→下划线 + `cksum` 后缀)。
⇒ 后续棒**别按会话名猜目录**,要用 `ls .locks/` 找。
3. 🔴 **本次抢锁的"结果校验"方式**(照纪律:⛔ 不看输出、要看结果):复读 `.locks/<实际目录>/OWNER`
与 `DOMAINS` 两个文件并断言归属 —— 未采用 `| grep` 截尾(那会吃掉退出码,也吃掉"抢不到")。
---
## 八、遗留 / 下一棒
| # | 遗留项 | 归属 |
|---|---|---|
| 1 | **浏览器级读数(S2-4)** | 客户端线起真壳后跑 `v-ui.sh`;或由下一棒在拿到真壳窗口时补 |
| 2 | **运行面有效读数** | 同上(需一次**含本包**的 boot) |
| 3 | **真机投放(两端各起一次)** | 撞硬边界「不碰把包装进去」⇒ 归 S4 之后的编排 |
| 4 | **S3 数据面**(声明 ⇒ 建库 `dshs_pl_ai1net` ⇒ 迁移 ⇒ 对账;⛔ 先建库再投放) | **下一棒(第 41 棒 · 执行棒)** |