dsh-molbio-tools 0.19.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +141 -0
  2. package/README.md +96 -33
  3. package/align.mjs +28 -0
  4. package/batch.mjs +185 -0
  5. package/benchmark/README.md +27 -8
  6. package/benchmark/sequences.mjs +7 -0
  7. package/benchmark/tasks/02-primers.json +132 -19
  8. package/benchmark/tasks/03-restriction.json +113 -29
  9. package/benchmark/tasks/04-cloning.json +167 -34
  10. package/benchmark/tasks/05-plasmids.json +172 -29
  11. package/benchmark/tasks/06-analysis.json +387 -100
  12. package/benchmark/tasks/09-formats.json +132 -23
  13. package/benchmark/tools.mjs +28 -2
  14. package/benchmark/verifications.mjs +17 -1
  15. package/build/release-preflight.mjs +2 -2
  16. package/crispr.mjs +392 -78
  17. package/docs/history.md +10 -0
  18. package/docs/maintainer.md +8 -6
  19. package/docs/roadmap.md +22 -8
  20. package/docs/rules.md +1 -1
  21. package/docs/workflow.md +7 -7
  22. package/fastq-qc.mjs +735 -735
  23. package/icon.svg +8 -0
  24. package/index.mjs +573 -36
  25. package/lib/client.js +665 -86
  26. package/multiplex.mjs +87 -0
  27. package/package.json +12 -5
  28. package/packages/molbio-panel/lib/client.js +665 -86
  29. package/packages/molbio-panel/package.json +1 -1
  30. package/preset/molbio-lab/agent.cordis.yml +4 -4
  31. package/preset/molbio-lab/preset.patch.yml +2 -2
  32. package/preset/molbio-lab/preset.yml +1 -1
  33. package/silent-site.mjs +286 -0
  34. package/snapgene.mjs +17 -1
  35. package/taqman.mjs +163 -7
  36. package/test/contract.mjs +14 -0
  37. package/test/release.mjs +23 -3
  38. package/test/smoke.mjs +377 -3
  39. package/benchmark/reports/20260923-142935-suite.json +0 -545
  40. package/benchmark/reports/20260923-142935-suite.md +0 -30
  41. package/benchmark/reports/20260923-190149-suite.json +0 -2024
  42. package/benchmark/reports/20260923-190149-suite.md +0 -235
  43. package/benchmark/reports/20260923-192913-suite.json +0 -1856
  44. package/benchmark/reports/20260923-192913-suite.md +0 -158
  45. package/benchmark/reports/20260923-200212-suite.json +0 -3587
  46. package/benchmark/reports/20260923-200212-suite.md +0 -163
  47. package/benchmark/reports/20260923-202830-suite.json +0 -3129
  48. package/benchmark/reports/20260923-202830-suite.md +0 -99
  49. package/benchmark/reports/20260923-203856-suite.json +0 -71
  50. package/benchmark/reports/20260923-203856-suite.md +0 -16
package/CHANGELOG.md CHANGED
@@ -10,6 +10,147 @@
10
10
  改为按**包名**引用后模块缓存问题随之消失——没有拷贝,也就没有需要保持同步的版本目录。
11
11
  下文历史条目里出现的 `vN` 目录保持原样,作为当时的记录。
12
12
 
13
+ ## [0.20.1] — 2026-10-18(插件专属图标)
14
+
15
+ **工具数不变(60),运行时零改动;包内只多一个 746 B 的 SVG。**
16
+
17
+ ### 1. 插件管理器为什么一直显示默认插画
18
+
19
+ DSH 的插件管理器从包根的清单 `icon` 或导出的 `./icon` 读取展示图,读到的字节会转成
20
+ base64 data URL 交给 `PackageArtwork`;两者都没有时保留面板默认插画。本包此前既没有
21
+ `icon` 字段也没有 `./icon` 导出,因此卡片和插件行一直是默认图——不是缓存,也不是
22
+ 安装坏了,而是**展示元信息根本没声明**。
23
+
24
+ ### 2. 图标:透明底双螺旋,按 30/36 px 的展示尺寸设计
25
+
26
+ `icon.svg`(64×64 viewBox,746 B)是原创的双螺旋:青绿 `#0D9488` 与蓝 `#2563EB`
27
+ 两条主链、四条琥珀 `#F59E0B` 碱基对,圆头描边、无渐变/字体/外部引用。透明底是刻意的:
28
+ 插件管理器把它放进 40×40(行)和 48×48(卡片)的圆角框里,图本身再加一层背景会变成
29
+ “框中框”;不留背景也让同一张图在浅色和深色主题下都成立。主链可视范围约 28×58(64 单位
30
+ 画布),在 36 px 卡片和 30 px 行图标上仍能读出双螺旋,20 px 时退化为可辨的轮廓。
31
+
32
+ ### 3. 接入:导出、白名单,以及一个 gitignore 例外
33
+
34
+ - `package.json` 的 `exports` 增加 `"./icon": "./icon.svg"`,`files` 白名单加入
35
+ `icon.svg`;本包 `files` 是白名单而不是默认全带,漏了它 `npm pack` 就会静默丢掉图标。
36
+ - 根目录的 `/*.svg` 规则原本用来挡住工具生成的图(`logo.svg`、质粒图等),新增
37
+ `!/icon.svg` 例外,图标才能作为源文件提交;git 忽略与 npm `files` 是两套规则,不能只改
38
+ 一处。
39
+ - 不新增依赖、不改 `dsh.client`、不改 preset 行清单;已安装的 profile 是指向本目录的
40
+ junction,重新读取 manifest 即可看到,不需要重装。
41
+
42
+ ### 4. 验证
43
+
44
+ - `createRequire(...).resolve('dsh-molbio-tools/icon')` 解析到包内 `icon.svg`;
45
+ `npm pack --dry-run --json` 的 118 个文件中包含它。
46
+ - 用本包自己的 `svgpng.mjs` 光栅化:64×64,`unsupported: []`;另按 36/30/20 px
47
+ 下采样检查过轮廓。
48
+ - `test/contract.mjs` 16/16;`test/release.mjs` 13/13(本机沙箱下按该测试自带的
49
+ `npm_config_user_agent` 兜底跑通)。
50
+ - 根包 `0.20.0 → 0.20.1`;面板 `0.1.3` 不动(`lib/client.js` 未变,发布前置检查不会
51
+ 要求面板 bump)。标题/描述仍回退到 `package.json` 的包名与长描述;本次没有新增
52
+ `locale/*.json`,如果要本地化展示文案,应作为独立改动。
53
+
54
+ ## [0.20.0] — 2026-10-17(Cas 家族几何、qPCR 订购/配平、批量分析与静默位点突变;并入 0.19.1 硬化)
55
+
56
+ **工具数 58 → 60,benchmark 56 → 61 题(60/60 覆盖)。** 这一版把 0.19.1 计划的四项硬化直接并入,
57
+ 并落地 roadmap 2.3 / 2.5 / 2.7 / 2.8 与 survey #8。Cas12a/Cas13 不是"再加一个 PAM 字符串":
58
+ 原来的 `findProtospacers` 把 3' PAM、20 nt 和 3' 种子写死在几何里,对 Cas12a/Cas13 会给出**生物学上错误**的
59
+ 坐标与评分,因此这一版把家族几何做成一张表,并补上了反向链脱靶定位的静默错误。
60
+
61
+ ### 1. 并入的 0.19.1 硬化(原计划单发 patch,现随 0.20.0 一起)
62
+
63
+ - **Smith-Waterman 的 DP 矩阵上限**:`molbio_align` 在分配前拒绝超过 50,000,000 cells 的输入对,
64
+ 而不是让两个几百 kb 的序列把宿主进程的内存吃光;工具描述同步说明"对齐窗口或改用
65
+ `molbio_verify_sanger`"。`test/smoke.mjs` 用 10 kb × 10 kb 的输入证明拒绝发生在分配之前。
66
+ - **SnapGene/PubMed XML 数值实体**:`�` 曾让 `String.fromCodePoint` 抛出 RangeError
67
+ 并逃出整个解析器;现在越界码点与代理项按字面文本保留,合法实体(含星形平面)照常解码。
68
+ - **`molbio_sequence_logo` 的并发声明**:它写共享默认路径 `logo.svg`,之前却默认 `safe`;
69
+ 现与其他画图工具一致声明 `safe: false`。
70
+ - **npm `files` 白名单**:不再整目录带 `benchmark`,改为 `benchmark/*.mjs`、`benchmark/tasks`、
71
+ `benchmark/README.md`,因此 `.gitignore` 里的本机 `benchmark/reports/` 不会再被打进包
72
+ (此前约 1.4 MB)。`test/contract.mjs` 直接禁止裸 `benchmark` 条目。
73
+
74
+ ### 2. roadmap 2.5:Cas12a/Cas13 家族几何(以及反向脱靶定位缺陷)
75
+
76
+ - `crispr.mjs` 新增 `CAS_FAMILIES` 表:SpCas9(3' NGG / 20 nt / 3' 种子)、SaCas9
77
+ (3' NNGRRT / 21 nt)、Cas12a(**5' TTTV / 23 nt / 5' 种子**)、Cas13a(RNA / 3' H PFS / 28 nt)、
78
+ Cas13b(RNA / 5' D + 3' NAN / 30 nt)、Cas13d(RNA / 无 PFS / 22 nt)。PAM 校验现在按
79
+ **PAM 的哪一侧贴近 protospacer** 检查简并位,而不是一律要求首位为 N——`TTTV` 因此不再被误拒。
80
+ - **Cas13 不是 PAM**:它有 PFS **偏好**,工具报告 PFS、按缺失扣分并明确说明"不是硬性 PAM";
81
+ 只有 `require_pfs=true` 才过滤。Cas13 的 `tm_celsius` 返回 `null`,因为对 RNA guide 报 DNA
82
+ NN Tm 是另一个分子;工具描述与渲染都写明这一点。
83
+ - **反向链脱靶定位是真 bug**:索引把每个 k-mer 记在 top-strand 起点,旧 `finalizeSites` 却对
84
+ 反向命中减去 `guideLength-1`,使它们整体偏移 19 nt 并大多越界丢弃——正向 fixture 永远看不见。
85
+ 现在两种链都从 `entry.position` 起算,PAM 按 5'/3' 侧与链向取 top-strand 窗口;新增的
86
+ smoke fixture 在 forward guide 与 reverse perfect copy 之间互指,断言反向脱靶 `start/end/pam`
87
+ 与 0 mismatch。
88
+ - 新 benchmark:`crispr-cas12a`(5' TTTV、23 nt、坐标 9-31)与 `crispr-cas13`(RNA、PFS A、28 nt)。
89
+ `test/smoke.mjs` 另钉住 Cas12a/Cas13a 的几何、PFS 过滤与错误路径。
90
+
91
+ ### 3. roadmap 2.8:TaqMan MGB 与订购 CSV
92
+
93
+ - `probe_chemistry: 'mgb'` 使用 13-20 nt、未修饰 NN Tm 48-60 °C 的窗口;**MGB 修饰的 Tm 不被
94
+ NN 模型预测**,因此报告的是未修饰 Tm,并以 `tm_model` 与 notes 明确要求向供应商复核。
95
+ MGB 不施加"探针 Tm 高于引物"的未修饰差值罚分(那会把每个 MGB 候选都罚掉)。
96
+ - 新增 `taqmanOrderRows` / `taqmanOrderCsv`:每条 assay 三行(F/R/P),列含 5'/3' 修饰、规模、
97
+ 纯化与说明;MGB 默认 `NFQ-MGB`,5' 默认 FAM。`save_path` 写 CSV;不传则只返回结构化 order。
98
+ - 标准 chemistry 的默认值、排序与已发布数值保持不变(smoke 的 9 assays 与 pinned probe 仍绿)。
99
+
100
+ ### 4. roadmap 2.7:多重 PCR 的退火温度与浓度配平建议
101
+
102
+ - `checkMultiplex` 新增 `annealing`:最低引物 Tm − `annealing_offset_c`(默认 3 °C),
103
+ 给出 ±`annealing_window_c` 范围、最低 Tm 引物、Tm 离散度与是否超过警告阈值。
104
+ - 新增 `primer_concentrations` 与 `concentration_note`:默认 200 nM;当扩增子大小比 ≥ 2 时,
105
+ 最短的降到 150 nM、最长的升到 300 nM,并明确这是**起始点**而非实测最优。
106
+ - 这些是清晰标注的规则性建议,notes 写明"不是热循环优化,需跑梯度"。
107
+
108
+ ### 5. roadmap 2.3:批量分析 + CSV/TSV
109
+
110
+ - 新模块 `batch.mjs` 与新工具 `molbio_batch_analyze`:扫描目录(可递归)或显式 paths,复用
111
+ 同一批 FASTA/FASTQ/GenBank/SnapGene 解析器,输出一张 CSV/TSV。
112
+ - 每行:格式、拓扑、条目数、总长、GC%、N%、特征数、平均长度;`analysis: orf` 加 ORF 数/最长
113
+ ORF,`analysis: enzymes` 加指定酶的位点数,`all` 两者都加。单个坏文件变成一行 `error`,
114
+ 其余文件继续;文件/字节上限与 `truncated` 都显式报告。
115
+ - 拓扑按 GenBank/SnapGene 声明优先(环状质粒的位点计数不会被当成线性);无声明时才用
116
+ `circular` 参数。新 benchmark `batch-analysis` 同时读 `pUC118.gb` 与 `pUC118.dna`。
117
+
118
+ ### 6. survey #8:静默酶切位点突变
119
+
120
+ - 新模块 `silent-site.mjs` 与新工具 `molbio_silent_site_mutagenesis`:只在同义密码子内枚举,
121
+ 因此**蛋白序列按构造不变**;输出逐碱基变化、密码子前后与氨基酸、可直接喂给
122
+ `molbio_mutagenesis_primers` 的 mutation texts、以及突变后序列。
123
+ - 支持 remove/add、frame 1-3、可选 `host`(按 e_coli/yeast/human 密码子偏好排序)与区域限制;
124
+ 只接受识别序列无简并碱基的酶(`GGTNACC` 这类直接拒绝而不是猜)。
125
+ - 新 benchmark `silent-site` 钉住 EcoRI 的 `C12T`(TTC→TTT,Phe)与突变后序列。
126
+
127
+ ### 7. 版本、基线与文档
128
+
129
+ - 根包 `0.19.0 → 0.20.0`,面板 `0.1.2 → 0.1.3`(客户端产物因 crispr/taqman/multiplex 改动而变,
130
+ 两个 npm 条目需分别发布)。
131
+ - **DSH 基线 `0.1.7-rc.1 → 0.2.0-rc.2`**:`.github/workflows/test.yml` 的 pin、roadmap/maintainer/
132
+ workflow 与 preset 头注释同步;`preset-health` 在 0.2.0-rc.2 上仍为 30 行全过(行清单无需改动)。
133
+ - README/preset 描述/工具表/benchmark 计数同步到 **60 tools / 61 tasks**;新增模块进入 npm
134
+ `files` 白名单与目录树。
135
+ - **未做**:`benchmark-score` 里 2 条 0.16.0 之前的冻结响应(`methylation-block`、`qpcr-primers`)
136
+ 仍是 suspended;本次没有用真实模型重录,测试输出会继续点名这两条,而不是假装它们已通过。
137
+
138
+ ### 8. 发布前完整 benchmark(2026-10-17,真实模型)
139
+
140
+ - **61 题首跑 55/61**:tool selection **61/61**,arguments **59/61**,final answer **57/61**;
141
+ 12.7M tokens / 1747 s。
142
+ - **新功能任务全部通过**:`taqman-mgb`、`crispr-cas12a`、`crispr-cas13`、`silent-site`、
143
+ `batch-analysis`。`multiplex-panel` 在把"退火温度/浓度"明确写进指令后复跑通过。
144
+ - **4 个失败是断言写死格式,不是产品缺陷**:`plasmid-digest`(模型写 `2,840`)、
145
+ `protein-props`(`3,935`)、`codon-optimize`(`EcoRI-free`)、`chart-volcano`
146
+ (任务要求 `de.svg`,断言却写 `volcano.svg`)。修正后 `--replay` 四题全部转为 PASS。
147
+ - **1 个真实可用性缺陷**:`molbio_extract_region` 的 schema 广告 `sequence`,但
148
+ `resolveVector` 只读 `vector`,于是文档里写的参数被静默忽略、调用报
149
+ "provide either vector or vector_path"。现在 `vector`/`sequence`/`reference` 三个已声明别名
150
+ 都接受,smoke 增加回归断言。该任务的真实模型复跑因 DSH 沙箱对 headless 子进程的审批限制
151
+ 未完成,因此发布时的实测口径是 **60/61**(这一题以 smoke 回归 + 修复代码为准,而不是假装已跑)。
152
+ - benchmark 工具本身未改;全量首跑使用了一次性更宽沙箱来启动 headless DSH 子进程。
153
+
13
154
  ## [0.19.0] — 2026-10-11(环形树的旋转多行标签;比对后处理套件;持续交付)
14
155
 
15
156
  **工具数 57 → 58。** 这一版是 [roadmap](docs/roadmap.md) 2.4 与 2.2 两条候选的落地:
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # dsh-molbio-tools
2
2
 
3
- **给 AI 助手装上分子生物学的"手"**:一个零依赖的 DeepSeek Harness 插件包,为它提供 **58 个
3
+ **给 AI 助手装上分子生物学的"手"**:一个零依赖的 DeepSeek Harness 插件包,为它提供 **60 个
4
4
  `molbio_*` 工具**——序列分析、引物/探针自动设计、克隆模拟、质粒图谱、测序验证、蛋白与 CRISPR
5
5
  分析、qPCR 统计、文献与实验记录。装上之后,你可以直接用自然语言让助手完成这些计算,并把结果
6
6
  画成图。
@@ -31,7 +31,7 @@
31
31
  ## 目录
32
32
 
33
33
  - [安装](#安装)(3 步)
34
- - [它会做什么](#它会做什么)(按任务分组的 58 个工具)
34
+ - [它会做什么](#它会做什么)(按任务分组的 60 个工具)
35
35
  - [典型用法示例](#典型用法示例)
36
36
  - [输出文件、自动打开与浏览器面板](#输出文件自动打开与浏览器面板)
37
37
  - [方法学与使用须知](#方法学与使用须知)(各工具的模型、估算范围与边界)
@@ -44,21 +44,35 @@
44
44
 
45
45
  需要一台已装好 [DeepSeek Harness](https://deepseek-harness.github.io/deepseek-harness/) 的机器。
46
46
 
47
- ### 推荐:专属模式 preset(2 步)
47
+ ### 推荐:在 DSH 插件页安装(3 步)
48
48
 
49
- 装完后,预设选择器里会出现 **Molecular Biology Lab** 模式;**58 个工具只在这个模式里出现**,
50
- 不会污染你其它会话(这点很重要:工具多了会占提示预算)。
49
+ 装完后,预设选择器里会出现 **Molecular Biology Lab** 模式;**60 个工具只在这个模式里出现**,
50
+ 不会污染你其它会话(这点很重要:工具多了会占提示预算)。**右栏的 Molbio / Papers 两个面板也随这个包
51
+ 一起装好**,不需要再装 `dsh-molbio-panel`。
51
52
 
52
- ```powershell
53
- # 1. 把包装进你的 profile(web 是默认 profile 名,按需替换)
54
- dsh plugin --profile web add D:\path\to\dsh-molbio-tools
53
+ 1. 打开 DSH Web GUI,点侧栏的 **插件**(Plugins)。
54
+ 2. 点 **添加插件**(Add plugin),在「包名或地址」里输入 `dsh-molbio-tools`,点 **安装**(Install);
55
+ 装完点 **立即启用**(Enable now)——关掉对话框只会装好、不会启用,之后也可以在插件页打开它的开关。
56
+ 3. 重启该 profile,然后在预设选择器里选 "Molecular Biology Lab" 新建会话。
57
+
58
+ ### 次选:命令行安装
59
+
60
+ 没有图形界面时(例如服务器上只用 CLI),用这条命令;它和插件页安装等价,都从 npm registry 取包:
55
61
 
56
- # 2. 重启该 profile,然后在预设选择器里选 "Molecular Biology Lab" 新建会话
62
+ ```bash
63
+ # web 是默认 profile 名,按需替换;装完同样要重启该 profile
64
+ dsh plugin --profile web add dsh-molbio-tools
57
65
  ```
58
66
 
59
- **升级**同样只有一条命令,不用重新复制、也不用改配置:
67
+ > 只有在改本仓库源码、还没发布到 npm 时,才需要从本地目录安装
68
+ > (路径按实际情况替换,Windows 示例):
69
+ > ```powershell
70
+ > dsh plugin --profile web add D:\path\to\dsh-molbio-tools
71
+ > ```
60
72
 
61
- ```powershell
73
+ **升级**(图形界面装的也适用)同样只有一条命令,不用重新复制、也不用改配置:
74
+
75
+ ```bash
62
76
  dsh plugin --profile web update dsh-molbio-tools
63
77
  ```
64
78
 
@@ -86,9 +100,9 @@ dsh plugin --profile web update dsh-molbio-tools
86
100
  | 层 | 作用 |
87
101
  | --- | --- |
88
102
  | `cordis.patch.yml` | 只插一行**惰性宿主锚点**(`./host.mjs`),不注册任何工具 |
89
- | `preset/molbio-lab/preset.patch.yml` | 声明 **Molecular Biology Lab** 模式,58 个工具在这一层里 |
103
+ | `preset/molbio-lab/preset.patch.yml` | 声明 **Molecular Biology Lab** 模式,60 个工具在这一层里 |
90
104
 
91
- 所以 58 个工具**只在选中该模式的会话里加载**,其它模式(standard / ptc / minimal / cordis)
105
+ 所以 60 个工具**只在选中该模式的会话里加载**,其它模式(standard / ptc / minimal / cordis)
92
106
  不带它们,不占提示预算。bundle 安装 ≠ 工具全局可见:bundle 只是把"模式"和"面板"一起装进来。
93
107
 
94
108
  > **那一行锚点不是多余的。** DSH 的客户端模块扫描只走**宿主 Loader 树**(官方原话:
@@ -102,20 +116,25 @@ dsh plugin --profile web update dsh-molbio-tools
102
116
  > 如果你确实想要"工具对所有会话全局可见",那需要把工具行加到宿主层——但那不是本包的设计,
103
117
  > 且会让专属模式里的同一行变成死行(0.1.7 上表现为选择器显示"加载失败")。
104
118
 
105
- ### 只要浏览器面板(可选)
119
+ ### 只要浏览器面板
106
120
 
107
- 如果只想要图形面板、不想让该 profile 装 58 个工具(连模式都不装),装面板专用包即可
108
- (见[浏览器面板](#浏览器面板)):
121
+ 如果只想要图形面板、不想让该 profile 装 60 个工具(连模式都不装),装面板专用包即可
122
+ (见[浏览器面板](#浏览器面板可选))。**它和 `dsh-molbio-tools` 二选一**:两者注册同一组右栏 tab
123
+ (`dsh-molbio-tools` / `dsh-molbio-tools/papers`),同时装会重复注册并报
124
+ `tab type id ... is already registered`。同样在 **插件 → 添加插件** 里输入 `dsh-molbio-panel`,
125
+ **安装** → **立即启用**。命令行等价于:
109
126
 
110
- ```powershell
111
- dsh plugin --profile <profile> add D:\path\to\dsh-molbio-tools\packages\molbio-panel
127
+ ```bash
128
+ dsh plugin --profile <profile> add dsh-molbio-panel
112
129
  ```
113
130
 
131
+ > 从本地源码目录安装时,把包名换成 `<包目录>/packages/molbio-panel`。
132
+
114
133
  ---
115
134
 
116
135
  ## 它会做什么
117
136
 
118
- 58 个工具按任务分为十组。下表是"你想做什么 → 用哪个工具"的索引,参数细节模型会在调用时自己
137
+ 60 个工具按任务分为十组。下表是"你想做什么 → 用哪个工具"的索引,参数细节模型会在调用时自己
119
138
  填;你只需要把意图说清楚。
120
139
 
121
140
  ### 1. 序列分析与酶切(7)
@@ -136,10 +155,10 @@ dsh plugin --profile <profile> add D:\path\to\dsh-molbio-tools\packages\molbio-p
136
155
  | --- | --- |
137
156
  | `molbio_design_primers` | **自动设计 PCR 引物对**:Tm(SantaLucia 1998 最近邻模型,盐/浓度可调)、GC、GC clamp、run/发夹/自互补/二聚体约束、错配容差、非特异结合检查、3' 目标位置偏好(SNP/定点设计),按罚分排序给出多组候选 |
138
157
  | `molbio_design_intron_primers` | **跨内含子 qPCR 引物**:给定基因组序列 + 外显子坐标,正向引物跨外显子-外显子连接点,基因组 DNA 不会扩增(可设最小基因组间距) |
139
- | `molbio_design_taqman` | **TaqMan(水解探针)测定设计**:引物对 + 探针一次给出(探针 5' 端非 G、Tm 比引物高 5 °C 起、无 run/重复、不与引物二聚化),每条候选附逐项罚分 |
158
+ | `molbio_design_taqman` | **TaqMan(水解探针)测定设计**:引物对 + 探针一次给出(探针 5' 端非 G、Tm 比引物高 5 °C 起、无 run/重复、不与引物二聚化),每条候选附逐项罚分;支持 **MGB 化学**(更短、按未修饰 NN Tm 报告并明确标注修饰未建模)和**订购 CSV**(引物/探针、5'/3' 修饰、规模、纯化) |
140
159
  | `molbio_primer_tm` | 单条引物 Tm 估算(Na⁺/Mg²⁺/dNTP 盐校正) |
141
160
  | `molbio_primer_check` | 引物结构筛查:重复序列、3' 端加权的自互补、发夹、引物对二聚体,以及 Primer3 同款热力学指标 |
142
- | `molbio_multiplex_check` | **多重 PCR 互扰检查**:面板内所有引物对的二聚体、3' 尾的脱靶与跨模板退火、扩增子是否能在胶上分辨,并给出重设计建议 |
161
+ | `molbio_multiplex_check` | **多重 PCR 互扰检查**:面板内所有引物对的二聚体、3' 尾的脱靶与跨模板退火、扩增子是否能在胶上分辨,并给出重设计建议;另给出**退火温度建议**(最低引物 Tm − offset,含范围与 Tm 离散警告)和**引物浓度起始计划**(按扩增子大小比例配平) |
143
162
 
144
163
  ### 3. 质粒与图谱(4)
145
164
 
@@ -150,7 +169,7 @@ dsh plugin --profile <profile> add D:\path\to\dsh-molbio-tools\packages\molbio-p
150
169
  | `molbio_plasmid_map_file` | **一步成图**:直接读 `.dna`/`.gb`/`.gbk` → 把 SVG 图谱**写入工作区**并自动打开 |
151
170
  | `molbio_plasmid_map` | 从序列 + 特征数组渲染环形/线形图谱(可选 GC skew 环、单切酶标记) |
152
171
 
153
- ### 4. 克隆构建(6)
172
+ ### 4. 克隆构建(7)
154
173
 
155
174
  | 工具 | 用途 |
156
175
  | --- | --- |
@@ -159,6 +178,7 @@ dsh plugin --profile <profile> add D:\path\to\dsh-molbio-tools\packages\molbio-p
159
178
  | `molbio_golden_gate` | **Golden Gate 多片段组装**:自动设计 4 bp 突出端、检查酶不切片段、给出可直接下单的片段序列、拼出最终质粒 |
160
179
  | `molbio_clone_primers` | 给插入片段加酶切位点 + 保护碱基(内置推荐表)或 Gibson 同源臂,并复检全长 Tm/GC/二聚体 |
161
180
  | `molbio_mutagenesis_primers` | QuickChange 式定点突变引物(`A123G`/`123A>G`/`123_125del`/`after123insGCT`),报告氨基酸变化 |
181
+ | `molbio_silent_site_mutagenesis` | **静默酶切位点突变**:在同义密码子范围内添加/移除限制性位点,保持蛋白序列不变;输出逐碱基变化、可直接喂给 `molbio_mutagenesis_primers` 的 mutation texts、突变后序列;只支持识别序列无简并碱基的酶 |
162
182
  | `molbio_extract_region` | 从质粒文件按特征名(如 "AmpR"、"MCS")或坐标提取子序列,可选反向互补与存 FASTA |
163
183
 
164
184
  ### 5. 测序与实验数据(6)
@@ -182,7 +202,7 @@ dsh plugin --profile <profile> add D:\path\to\dsh-molbio-tools\packages\molbio-p
182
202
  | `molbio_helical_wheel` | **螺旋轮投影**:残基按 3.6 残基/圈落在圆周上、按性质着色,给出疏水矩 μH(判断是否两亲性),出 SVG |
183
203
  | `molbio_hydropathy_plot` | **Kyte-Doolittle 疏水性图**:滑动窗口曲线 + GRAVY + 达到跨膜阈值的峰,出 SVG |
184
204
 
185
- ### 7. 比对与保守性(6)
205
+ ### 7. 比对与保守性(7)
186
206
 
187
207
  | 工具 | 用途 |
188
208
  | --- | --- |
@@ -192,12 +212,13 @@ dsh plugin --profile <profile> add D:\path\to\dsh-molbio-tools\packages\molbio-p
192
212
  | `molbio_alignment_postprocess` | **比对后处理**:共识(plurality/union/strict 三选一)、按缺口比例修剪(报原始 1-based 列号)、两两同一性矩阵、逐列覆盖度 |
193
213
  | `molbio_sequence_logo` | **序列标识图**:把保守性画成 SVG logo(字母高度 = 信息量 bits) |
194
214
  | `molbio_fasta_fastq` | 工作区 FASTA/FASTQ:条目统计、按 id 提取、FASTQ→FASTA、FASTQ 质量报告 |
215
+ | `molbio_batch_analyze` | **批量文件分析 + CSV/TSV**:对目录(或显式 paths)里所有匹配的 FASTA/FASTQ/GenBank/.dna 跑同一套摘要/ORF/酶切位点分析;单个坏文件是一行 error,不会中断整批 |
195
216
 
196
217
  ### 8. CRISPR(1)
197
218
 
198
219
  | 工具 | 用途 |
199
220
  | --- | --- |
200
- | `molbio_grna_design` | **gRNA 设计**(默认 SpCas9 `NGG` PAM):双链扫描、GC/poly-T/自互补/发夹等质量指标、逐项公开的启发式评分,以及**同序列内的错配容差脱靶搜索**(种子区不许错配);可出订购 CSV 与带标记的图谱 |
221
+ | `molbio_grna_design` | **gRNA 设计**(默认 SpCas9 `NGG` PAM,亦可 SaCas9/Cas12a/Cas13a/Cas13b/Cas13d):按家族选择 PAM/PFS 侧、crRNA 长度和种子定义(Cas12a 是 5' TTTV + 5' 种子,Cas13 是 RNA 靶标 + PFS 偏好而非 PAM);双链扫描、GC/poly-T/自互补/发夹等质量指标、逐项公开的启发式评分,以及**同序列内的错配容差脱靶搜索**;可出订购 CSV 与带标记的图谱 |
201
222
 
202
223
  ### 9. 文献与实验记录(12)
203
224
 
@@ -252,6 +273,11 @@ dsh plugin --profile <profile> add D:\path\to\dsh-molbio-tools\packages\molbio-p
252
273
  | "这对引物除了目标还会在哪扩增?预期几条带" | `molbio_pcr_simulate(template, primer_pairs:[…])` → 产物大小 + 凝胶图 |
253
274
  | "这几条序列谁跟谁最近,这个结论有信心吗" | `molbio_phylogenetic_tree(sequences:[…], bootstrap:100)` → 支持度 + Newick |
254
275
  | "这段是不是启动子/CPG 岛?复制起点在哪" | `molbio_gc_composition(sequence)` → CpG 岛区间 + 累积 GC skew 的 ori/ter 提示 |
276
+ | "把这 60 个质粒/reads 一起做个汇总表" | `molbio_batch_analyze(directory, pattern, analysis:'all', enzymes:[…])` → 一张 CSV/TSV |
277
+ | "把 EcoRI 位点静默去掉,蛋白不能变" | `molbio_silent_site_mutagenesis(sequence, enzyme:'EcoRI', action:'remove')` → mutation texts → `molbio_mutagenesis_primers` |
278
+ | "用 Cas12a 设计 gRNA(5' TTTV PAM)" | `molbio_grna_design(sequence, cas_family:'cas12a')` |
279
+ | "用 Cas13a 敲低这个转录本" | `molbio_grna_design(sequence, cas_family:'cas13a', target_strand:'forward')` → 看 PFS 与 require_pfs |
280
+ | "TaqMan 用 MGB 探针,并出一张订购表" | `molbio_design_taqman(sequence, probe_chemistry:'mgb', save_path:'order.csv')` |
255
281
  | "搜一下 KRAS G12D 抑制剂的最新文献并存进阅读库" | `molbio_pubmed_search` → `molbio_paper_add` |
256
282
 
257
283
  ---
@@ -409,6 +435,12 @@ mutations remain deferred")。所以插件无法在工作区里合法地落一
409
435
  snake_case 键(`region_start`/`tm_min`/`amplicon_max`/`na_mm`…),未知键会明确报错。
410
436
  - `tm_delta_vs_primer`(探针 Tm − 较热引物 Tm)为负时探针仍会给出,但在 `notes` 里点名该
411
437
  扩增子——看到这条就说明这套测定该换个区域。
438
+ - **MGB(0.20.0)**:`probe_chemistry: "mgb"` 用 13–20 nt、未修饰 NN Tm 48–60 °C 的窗口。
439
+ MGB 修饰会把真实 Tm 抬高,但**NN 模型不预测这个增量**,所以报告的是未修饰 Tm,并在
440
+ `tm_model`/notes 里要求向供应商复核;也不会用"探针 Tm 必须高于引物"的未修饰差值去惩罚每个
441
+ MGB 候选。
442
+ - **订购 CSV(0.20.0)**:`save_path` 写出每条 assay 的 F/R/P 三行,含 5'/3' 修饰、合成规模与
443
+ 纯化;不传路径时只返回结构化 `order`。探针默认 5' FAM、3' 按化学(MGB 默认 NFQ-MGB)。
412
444
 
413
445
  ### 多重 PCR 互扰(v17)
414
446
 
@@ -420,6 +452,11 @@ mutations remain deferred")。所以插件无法在工作区里合法地落一
420
452
  - 大小分辨:差 < 20 bp(`min_size_separation_bp`)= 胶上不可分辨,< 40 bp = 偏近。
421
453
  - `compatible` 为 `false` 只由三类阻断项决定:**跨 target 二聚体 / 跨模板退火 / 不可分辨的
422
454
  扩增子大小**。
455
+ - **退火温度(0.20.0)**:`annealing.recommended_c` = 最低引物 Tm − `annealing_offset_c`
456
+ (默认 3 °C),`range_c` 按其 ±window 给范围;`spread_c` 超过阈值时明确说"一个温度不可能对
457
+ 所有引物最优"。这是规则性起点,不是热循环优化。
458
+ - **引物浓度(0.20.0)**:默认 200 nM;当已知扩增子大小比 ≥ 2 时,最短的降到 150 nM、最长的
459
+ 升到 300 nM。`rationale` 逐 target 说明属于哪种情形,notes 写明这是起始点而非实测最优。
423
460
 
424
461
  ### 甲基化与双酶切(v17)
425
462
 
@@ -483,14 +520,38 @@ mutations remain deferred")。所以插件无法在工作区里合法地落一
483
520
 
484
521
  ### CRISPR
485
522
 
486
- - 几何按 SpCas9 约定:protospacer 是紧邻 PAM **5' 侧**的 20 nt;`start`/`end` 是**顶链 1-based
487
- 闭区间**,`sequence` 始终是按 5'→3' 下单的序列,`pam` 始终读在 **guide 靶向的那条链**上。
523
+ - **几何按家族**(0.20.0):SpCas9 是 3' NGG / 20 nt / 3' 种子;SaCas9 是 3' NNGRRT / 21 nt;
524
+ **Cas12a 是 5' TTTV / 23 nt crRNA / 5' 端种子**;**Cas13a/b/d 是 RNA 靶标 + PFS 偏好**(不是 PAM:
525
+ Cas13a 3' H / 28 nt,Cas13b 5' D + 3' NAN / 30 nt,Cas13d 无 PFS / 22 nt)。`start`/`end` 仍是
526
+ 顶链 1-based 闭区间,`sequence` 是按 5'→3' 下单的 DNA 序列(Cas13 另给 `rna_sequence`),
527
+ `pam` 读在 guide 靶向的那条链上(Cas13 为空)。
528
+ - **PFS 不是 PAM**:Cas13 的 PFS 缺失只扣分并标注,只有 `require_pfs: true` 才过滤;Cas13 不报
529
+ DNA NN Tm(返回 null),因为 guide 是 RNA。
530
+ - **反向链脱靶**(0.20.0 修复):旧 `finalizeSites` 对反向命中减了 `guideLength-1`,使反向脱靶
531
+ 偏移 19 nt 并大多被丢弃;现在两种链都从 top-strand 起点算,PAM 按 5'/3' 侧与链向取窗口。
488
532
  - 评分逐项公开(GC 偏差、Tm 偏差、poly-T 与同聚、自互补、种子自互补、发夹 Tm、**每个脱靶
489
533
  8 分**、PAM 前一位为 G 时 +4),起点 100。**这是排序用的启发式,不是切割效率或特异性的
490
534
  预测值。**
491
- - 脱靶搜索只建模**替换**(无 bulge/indel)、要求 PAM 完好、种子末端 2 位不允许错配;默认只搜
492
- 得分最高的若干候选。想在基因组尺度搜索,需要把基因组序列作为 target 传入(当前实现的规模
493
- 上限就是单次调用的序列长度)。
535
+ - 脱靶搜索只建模**替换**(无 bulge/indel)、要求 PAM 完好、**家族对应的种子端**不允许错配
536
+ (SpCas9/SaCas9 3' 末 2 位,Cas12a 5' 起 2 位,Cas13 无硬种子);默认只搜得分最高的若干候选。
537
+ 想在基因组尺度搜索,需要把基因组序列作为 target 传入(当前实现的规模上限就是单次调用的
538
+ 序列长度;Cas13 另有候选窗口上限并提示缩小 region)。
539
+
540
+ ### 批量分析(0.20.0)
541
+
542
+ - 目录扫描默认不递归;`recursive: true` 才进子目录(深度上限 8)。`paths` 与 `directory` 二选一,
543
+ 显式 paths 优先。
544
+ - 每个文件独立解析,**坏文件是一行 `error`**,不会让整批失败;`truncated` 表示触到文件数/字节上限。
545
+ - 拓扑以 GenBank/SnapGene 声明为准(环状质粒的酶切位点计数不会按线性处理),没有声明时才用
546
+ `circular` 参数。ORF 用所选遗传密码与 ATG 起始规则;长 ORF 不等于真基因。
547
+
548
+ ### 静默位点突变(0.20.0)
549
+
550
+ - 只在**同义密码子**内枚举:蛋白序列按构造不变;`changes` 逐碱基给出位置/前后碱基/密码子/氨基酸。
551
+ - `mutation_texts` 是 `A123G` 形式,可直接传给 `molbio_mutagenesis_primers`;`mutated_sequence`
552
+ 是改完的 CDS。
553
+ - 只支持识别序列**无简并碱基**的酶(`GGTNACC` 这类直接拒绝);`host` 只影响同义密码子的排序,
554
+ 不改变"是否静默"这一事实。静默是蛋白层面的,mRNA 结构/剪接/密码子使用仍可能变化。
494
555
 
495
556
  ### 文献与记录
496
557
 
@@ -615,13 +676,13 @@ node <包目录>\preset\install.mjs --profile web --check # 只报告,不组
615
676
 
616
677
  想评估"模型到底会不会用这些工具",看 **[benchmark/README.md](benchmark/README.md)**:
617
678
  `npm run bench:offline` 零成本校验期望值(在 `npm test` 里),`npm run bench` 用真实模型
618
- 跑 **core 档 14 题**,`npm run bench:full` 跑**全部 56 题(覆盖 58/58 个工具)**。
679
+ 跑 **core 档 14 题**,`npm run bench:full` 跑**全部 61 题(覆盖 60/60 个工具)**。
619
680
 
620
681
  > **改动与 benchmark 的关系(硬规则)**:新增或改动任何工具行为,**必须**新增/更新对应的
621
682
  > benchmark 任务并重跑;没有改动就不必重跑。日常只需要一条命令——
622
683
  > `node benchmark/run.mjs --model --changed`——它会从你的改动反推出该跑哪几题
623
684
  > (`lib.mjs` 这类共享库会自动放大到全量),改动只在文档/测试时则直接回答"无事可跑"。
624
- > `test/benchmark-coverage.mjs` 会拦住"新工具没有任务"(断言 58/58 覆盖),
685
+ > `test/benchmark-coverage.mjs` 会拦住"新工具没有任务"(断言 60/60 覆盖),
625
686
  > `bench --offline` 会拦住"期望值过期"。完整对照表见
626
687
  > [docs/workflow.md](docs/workflow.md) 第 2 节。
627
688
 
@@ -647,7 +708,7 @@ node <包目录>\preset\install.mjs --profile web --check # 只报告,不组
647
708
 
648
709
  ```
649
710
  dsh-molbio-tools/
650
- ├── index.mjs # 插件入口:export { name, inject, apply },注册 58 个工具
711
+ ├── index.mjs # 插件入口:export { name, inject, apply },注册 60 个工具
651
712
  ├── lib.mjs # 基础库:IUPAC、翻译、酶表、NN 热力学、qPCR、lab math、甲基化/buffer 参考表
652
713
  ├── design.mjs # 引物自动设计(含跨内含子 qPCR)
653
714
  ├── taqman.mjs # TaqMan 水解探针设计(复用 design.mjs 的引物引擎)
@@ -662,12 +723,14 @@ dsh-molbio-tools/
662
723
  ├── msa.mjs # 多序列渐进式比对与保守性分析
663
724
  ├── align-post.mjs # 比对后处理:共识/缺口修剪/同一性矩阵/逐列覆盖度
664
725
  ├── logo.mjs # 序列标识图(信息量 + SVG)
665
- ├── crispr.mjs # CRISPR gRNA 设计(PAM 扫描、评分、脱靶搜索)
726
+ ├── crispr.mjs # CRISPR gRNA 设计(SpCas9/SaCas9/Cas12a/Cas13 家族几何、评分、脱靶搜索)
666
727
  ├── cloning.mjs # 克隆模拟:选酶/酶切连接/Gibson/Golden Gate/克隆引物/突变引物
728
+ ├── silent-site.mjs # 静默酶切位点突变(同义密码子内添加/移除位点)
667
729
  ├── sanger.mjs # ABIF (.ab1) 解析 + 测序验证
668
730
  ├── plot.mjs # SVG 柱状/散点图 + 虚拟琼脂糖凝胶
669
731
  ├── charts.mjs # 实验数据图表:CSV/TSV 读取 + 折线/直方图/箱型/小提琴/火山/热力图(基于 svgio)
670
732
  ├── seqio.mjs # FASTA/FASTQ 解析与统计
733
+ ├── batch.mjs # 批量文件分析:同一套摘要/ORF/酶切位点 → CSV/TSV
671
734
  ├── records.mjs # 协议库 / 实验日志存储
672
735
  ├── papers.mjs # 文献库存储
673
736
  ├── view.mjs # auto-view:把 SVG 交给系统默认应用打开
package/align.mjs CHANGED
@@ -8,6 +8,27 @@
8
8
 
9
9
  import { MolbioInputError } from './lib.mjs';
10
10
 
11
+ /**
12
+ * Safety limits, exported so the tools, their descriptions and the tests share
13
+ * one source.
14
+ *
15
+ * Local alignment allocates the WHOLE dynamic-programming matrix up front — a
16
+ * scoring array and a direction array of `(len(a)+1) * (len(b)+1)` cells, both
17
+ * filled before a single backtrace step. The cost is quadratic in the input, and
18
+ * the only cap upstream is `normalizeSequence`'s 1,000,000 bases, so without a
19
+ * budget here one call with two unremarkable few-hundred-kb sequences asks for
20
+ * tens of gigabytes and takes the host process down with it. Measured on the
21
+ * development machine: 8,000 x 8,000 costs ~237 MB and 0.5 s, so 50e6 cells is
22
+ * ~250 MB and ~2 s.
23
+ *
24
+ * `msa.mjs`, `phylo.mjs` and `align-post.mjs` each carry a budget of their own;
25
+ * this covers the pairwise path, which had none.
26
+ */
27
+ export const ALIGN_LIMITS = {
28
+ /** DP cells (length(a) * length(b)) one local alignment may allocate. */
29
+ maxCells: 50_000_000,
30
+ };
31
+
11
32
  /**
12
33
  * Smith-Waterman local alignment of `a` against `b`.
13
34
  * @returns {object} aligned strings, start offsets, identity, and a unified
@@ -15,6 +36,13 @@ import { MolbioInputError } from './lib.mjs';
15
36
  * relative to `b`).
16
37
  */
17
38
  export function smithWaterman(a, b, { match = 2, mismatch = -2, gap = -1 } = {}) {
39
+ const cells = a.length * b.length;
40
+ if (cells > ALIGN_LIMITS.maxCells) {
41
+ throw new MolbioInputError(
42
+ `alignment of ${a.length} x ${b.length} bases needs ${cells} matrix cells (limit ${ALIGN_LIMITS.maxCells}); `
43
+ + 'align a window instead — an exact 21-mer anchor keeps a read-vs-reference alignment linear in practice (see molbio_verify_sanger)',
44
+ );
45
+ }
18
46
  const m = a.length + 1;
19
47
  const n = b.length + 1;
20
48
  const H = new Int32Array(m * n);