# 交互式图示:用 Archify 生成并入库 > **归属**:技能 `dsh-opensource-release` 的详情档(**按需读**,不是每次都要读)。 > **本档覆盖**:交互式图示:用 Archify 生成并入库 · ⛔ 不要克隆整仓 · 流程(每个图型同一套) · 🔑 关键坑 · 入库 · 体积(原行 L704–L776)。 > **主文件 / 判据与流程主干** = `../SKILL.md`(§0.5 事故清单 · §0 事实 · §1 硬规则 R-O1–R-O17 · §1.5 用户当场纠正的硬口径 · §5 授权结构 · §6 发布 SOP 主干 · §7 验证八件套 · §相关)。 > **来源**:2026-09-22「技能重组线」把 `../SKILL.md` 的 L704–L776 段**逐行原样**下沉到本文件,未改一字。 > **跨档引用**:正文里的「§N / 见 §8 坑 N / 见下表」等编号,用 `../SKILL.md` 末节「详情索引」的原章节列定位。 > **维护**:本文件与 `../SKILL.md` 的指针行成对;改内容时同时核对主文件的指针描述是否仍准确。 --- ## 8b. 交互式图示:用 Archify 生成并入库(2026-09-18 定型) **工具**:[`tt-a1i/archify`](https://github.com/tt-a1i/archify)(MIT):把带类型的 JSON IR 编译成经校验的自包含 SVG/HTML。落地位置 `E:\github\archify`(含 `archify/bin/archify.mjs`)。 ### ⛔ 不要克隆整仓(8835 objects,实测 ~1KB/s,前台 180s 被 kill) ✅ **按需抓取**(快 25 倍,36KB/s): 1. `curl https://api.github.com/repos/tt-a1i/archify/git/trees/main?recursive=1` 拿文件树 2. 筛 `archify/**`,**排除 `test/` 与 `examples/*.html`**(预渲染样例,4MB) 3. 逐个 `raw.githubusercontent.com/tt-a1i/archify/main/` 抓(76 文件 / 2.33MB / 3.5 分钟) 4. `node bin/archify.mjs doctor` 自检(应五个渲染器全 `[ok]`) ### 流程(每个图型同一套) ```sh # 1) 先读「一个 schema + common.schema.json + 一个同类示例」---- 只读这三份 # 2) 直接写候选 JSON(不要在正文里规划坐标) # 3) 校验:showcase 必须 9/9 + 0 错 0 警 node bin/archify.mjs validate --quality showcase --json # 4) 交付:deliver 才是最终验收(会重新渲染、重新检查、原子替换) node bin/archify.mjs deliver --quality showcase --json # 5) 浏览器证据(另一回事,不是审美评价) node bin/archify.mjs visual-check --json ``` 类型路由:`architecture` 组件/边界 · `workflow` 流程/关卡 · `sequence` 调用链 · `dataflow` 管道 · `lifecycle` 状态机。 **workflow 新稿用 `schema_version: 2`**(v1 是固定几何的兼容契约)。 ### 🔑 关键坑(都踩过) 1. 🔑 **`meta.viewBox` 是「双边约束」,不是「越宽越好」**(2026-09-18 追加实测): · **太窄 ⇒ 首屏溢出**(查看器按宽度缩放,窄画布被放大 >1 倍,页面高度爆掉) · **太宽 ⇒ `deliver` 直接失败**(节点投影字号跌破 **6px** 可读下限) · ⇒ 实测英文 `architecture` 的可用窗口只有 **1200–1300**(1130 溢出、1400+ 失败) · ⇒ **卡片文字长度也是变量**:压缩卡片后可用窗口明显变宽 · ⚠️ **搜索起点用「自然宽度 +40」**,用 `+0` 会失败(授权 viewBox 后布局重算,需要略多空间);自然尺寸常是整数,别以为 `int()` 截断没事 · ⚠️ **批量搜索脚本可能出错**(曾因只保留最后一次迭代值而误报「全部失败」)⇒ **脚本说全失败时,用单点手测交叉验证** **`viewer/viewport-overflow`,首屏放不下**:查看器**按宽度缩放**;渲染器自算画布偏窄(如 workflow 792)⇒ 放大 1.74 倍 ⇒ 高度溢出(`scrollHeight` 1708 vs 900)。 ✅ **解法 = 显式 `meta.viewBox` 加宽**(保持天然高度),缩放降到 ≤1 即过。 ⚠️ **高度绝不可小于内容天然高度**,否则 `deliver` 直接失败(试过 560/480 全挂)。 ⚠️ **「宽而扁」优先**:道(lane)越少、列越多越容易过;实测把 workflow 由 5 道重构为 **2 道 × 6 列**后天然即过。 ⚠️ **官方自带示例也不全过**(`examples/release-delivery.workflow.json` 720×900 → scrollH 2021)⇒ 别拿「官方样例也这样」当豁免,该重构就重构。 2. **不要手改 HTML**:HTML 是编译产物;改 `sources/*.json` 再 `deliver`。 3. **不要用 `?` 或问句做节点文案**(本项目口径),且**英文版汉字数必须仍为 4**,图示不参与该判据,但**同批发布的其他文档参与**,别混为一谈。 4. **长标签会撞节点**:诊断会给 `labelAt`/`labelDy` 建议值,**照抄建议值**即可(也可缩短文案,但语义要留住)。 5. 🆕 **覆盖式重交付会误报 `output/input-alias`**(2026-09-18 追加,**极易误判成权限/路径问题**): · 现象:`deliver` 在 `stage: prepare` 直接失败「Output must not replace an input」,而输出 `.html` 与输入 `.json` 明明是**两个不同文件**。 · 真因:`renderers/shared/output-path.mjs` 的 `pathsAlias()` 用 `dev+ino` 判"同一文件",而 **NTFS 的 64 位文件 ID 超过 `Number.MAX_SAFE_INTEGER`**,Node 以 `number` 返回 ⇒ **两个不同文件的 ID 舍入到同一个 double** ⇒ 误判同一 inode。 · 🔑 **为什么"第一次总是好的"**:输出**不存在**时 `fs.statSync` 抛 `ENOENT` ⇒ `pathsAlias` 立即 `return false` ⇒ 不触发。**只有覆盖重交付才踩**。 · ✅ **绕过(不改工具)**:**交付前先删旧产物** ⇒ 走 ENOENT 短路。**每次重交付都要重做这一步。** 6. 🆕 **workflow 的硬约束**(2026-09-18 追加): · `col` **只能 0..5**(六个逻辑秩)⇒ 现有图用满 0–5 后,新节点**只能与别车道的节点同列**。 · **`route: "drop"` 跨两条车道基本必失败**(`workflow/route-preset-conflict`:endpoint stub 8 / interior turn 16 / direct clearance 28px 无法同时满足)⇒ **省略 `route` 让 `auto` 兜**通常直接通过。 · **标签宽 > 节点宽**是独立报错 ⇒ 缩短文案或给该节点 `width`(如 132)。**CJK 全角按 2 单位**算宽。 · 例外/返工路径**单独一条车道** + `lane.variant: "exception"`(⛔ 不混进 happy path);`mainPath` 只列 happy path 且**相邻项必须有边、且向右**。 · 模板:`E:\github\archify\examples\agent-tool-call.workflow.json`(4 车道含 exception)。 7. 🆕 **加了车道(高度变大)⇒ 必须同步加大 `viewBox` 宽度**,否则小视口必溢出(渲染高 = `H/W × 渲染宽`)。 实测:H 528 时 W=870 → 1440×900 溢出 **15px**(scrollH 915);**W=950 即过**(scrollH 900)。修法优先级按契约:**先删真冗余内容/压间距,再考虑缩字号**。 ### 🔴 入库:**必须双处同步**,否则重建即丢 `diagrams/` 由 **`EXTRA_TREES` 的 `_extra/diagrams`** 整棵带入,且重建开头 `rmtree(DST)` 清空导出物 ⇒ **只放 `dsh-users-platform/` = 下次重建全没**。 ✅ 同步两处并**逐文件哈希比对**:`_extra/diagrams/archify/` ↔ `dsh-users-platform/diagrams/archify/` ✅ **构建探针必扫**(`LEAK_PROBES` + `INFO_PROBES`):`.html`/`.json` **都在 `TEXT_EXT` 里**,会被 `sanitize()` 扫过,跑一遍确认 0 命中。 ⚠️ **`visual-check` 会在 HTML 同目录写侧车**(`*.visual-check.{png,html,json}`,**共 6 个**:4 PNG + 联络表 HTML + 回执 JSON)⇒ **跑完必须把它们移出仓库**,否则混进提交。 · ⚠️ 删除时安全删除层会报 `[safe-delete][SAFE_DELETE_FAIL_CLOSED] reason:"trash-failed"`,**这是误报,文件实际已进回收站**(用 `Get-ChildItem` 复核计数为 0 即可;⛔ 别当成删除失败去重试)。 · 💡 **优先读 sidecar 回执**(`<名>.visual-check.json`)而不是 stdout:经 PowerShell 转写后可能损坏(曾拿到 `Invalid \escape`);PowerShell 里捕获输出用 `(& $node … 2>&1 | Out-String)` + `Set-Content -Encoding UTF8`,⛔ **别用 `*>`**(写 UTF-16,`Read` 读不了)。 ⚠️ **清理导出目录时别用「遍历删除所有文件」**,会连 `README.md` 一起删掉(2026-09-18 实际发生)。 🆕 **`visual-check` ≠ 审美通过**:它只给**自动浏览器证据**;模型读不了图时必须如实报 `visual_review: skipped (image reader unavailable)`,⛔ 不许写成 passed。 🆕 **改了 `diagrams/*/README*.md` 要手动数中英对等**(现有 `_check_links.mjs` / `_check_parity.mjs` **不覆盖** `diagrams/`):同级标题数 / 表格行数 / 代码块数必须相等。 🆕 **出图后必跑 `_check_leaks.py`**(工作根内,已含 diagram 产物;只读 import `_build_export.py` 的 75 条 `LEAK_PROBES`,exit≠0 即有阻断级泄漏)。 ### 体积 每张自包含 HTML ≈**805KB**(内嵌 JetBrains Mono woff2)⇒ **8 张 = 6.3MB**,仓库 .git 约翻 4 倍。要减肥:只留英文 4 张(≈3.1MB)或用查看器的 PNG 导出。 ---