Repository navigation
Releases: 5777-wq/OpenHull
Release list
v1.10.0 — 型线图曲面蒙皮(实验性):加密剖切出图 + 曲率诊断
Warning
Experimental release. The lines-plan surface skin is a new
geometry layer and its outputs (dense re-cut offsets, skinned
lines plans) should be treated as experimental until it has seen
wider use. The computational chain (hydrostatics, stability,
resistance, propulsion) is unchanged and fully anchored; the skin
is verified NOT to move the ship (see anchors below), but the
drawing-grade products it feeds are new. Pin v1.9.0 for
production use.
Lines-plan surface skin (openhull.surface) — experimental
The drawing-grade route to fair lines plans: fit a bicubic
(degree 3x3) interpolating B-spline surface through the tabulated
offsets grid, then re-cut dense stations and waterlines from that
skin — the lines plan becomes a projection of a smooth surface
instead of PCHIP-connected sparse points. Engine:
geomdl (MIT), added as a
core dependency under the capytaine/ezdxf precedent — geometry only,
no whitelisted formula touched (AGENTS.md §5, 2026-10-05).
Anchors (why the skin does not change the ship):
| anchor | result |
|---|---|
| knot reproduction | max error 5.0e-14 m on the packaged Series 60 parent (gate 1e-6·B/2) |
| hydrostatics round-trip, x2 grid (41×53) | ∇ +0.0024 %, Cb +0.0024 %, LCB +0.0038 %Lpp, KM +0.017 % |
| hydrostatics round-trip, x4 grid (81×105) | ∇ +0.015 % |
| Simpson parity | odd counts in, odd counts out (intervals doubled/quadrupled) |
Also in this release: per-waterline curvature diagnostics
(curvature_report(), classical κ = |y''|/(1+y'²)^1.5 — a diagnostic;
the task-2.6 difference checks stay the acceptance gate), dense-grid
support in the drawing layer with thinned fan-out waterline labels,
and the example pair
lines_plan_series60.png
(tabulated 25×8) vs
lines_plan_series60_dense.png
(skinned 41×53).
Quality gates: 9 new tests (tests/test_surface.py), 505 total,
ruff clean, cold-install verified.
Full changelog: CHANGELOG.md
v1.8.0 — 任务书可选母型:Series 60 数字化 / JBC 解析拟合
Selectable parent hulls (hull_form.parent)
The constitution §8 registry pattern realised for the mother hull: the task book selects between series60_digitised (the packaged DTMB 1712 Table 7 digitisation — the default, byte-identical to the pre-1.8 chain) and the analytic JBC-family parent jbc_analytic (declared in §5 as a CONSTRUCTION, not a book formula: taper-form build with the (p_a, p_f) Simpson fit pinned to the task-book Cb, plus declared JBC anchor defaults).
- Applicability travels with the registry as data (Series 60 Cb ≈ 0.60–0.80; JBC family Cb ≈ 0.80–0.87); unknown ids are refused naming the registry.
- Anything not pinned falls back to a JBC anchor default that is SURFACED in
parent_hull.defaults_applied, never applied silently; without a KM anchor the wall-sided base form (k = 0) is built and KM is measured, not tuned. - All three hull-building call sites (run / rao / design_space_scan) pass the selection through; the run summary carries a
parent_hullprovenance block. - Example task book: examples/taskbook_bulk_carrier_jbcparent.yaml (TB-001J).
Quality gates: 12 new tests (tests/test_parent_hull.py), 485 total — registry provenance, both refusal paths, Cb/LCB/KM anchors on the analytic parent (KM 18.57 m vs the 18.59 m anchor, ±2 % gate), the JBC-anchored chain run (volume −0.80 % vs the NMRI 178,369.9 m³, Cb +0.0001), scan-path integration, and default-path identity.
Full changelog: CHANGELOG.md
v1.7.0 — MCP 服务器落地:五种工具,其他 harness 的 agent 可直接调用
MCP server surface (openhull[mcp], optional extra)
The agent-native invocation path the constitution §8 "agent-facing contract" promised: a stdio MCP server (openhull-mcp) whose five tools (openhull_version / openhull_check / openhull_run / openhull_optimize / openhull_rao) shell out to python -m openhull.cli in a child process and return the CLI's JSON stdout contract verbatim — no numerics touched, the SDK is imported lazily, and the toolchain disciplines (whitelist provenance, refusal guards, "report, never decide") carry over unchanged. A resource openhull://taskbook-template serves the JBC-anchored task book. Registration snippets for Codex, ZCode, Claude Desktop and generic MCP harnesses (DeepSeek et al.): docs/mcp.md.
The load-line freeboard check is wired into run (task 1.6 discharge)
The chain now computes the type-B summer minimum per Lin Yan Table 3-9 + the five corrections on the BALANCE dimensions and reports it in the summary JSON (freeboard, with a declared skipped state outside the 24–365 m table range), the console, and report section 1.
Quality gates: 14 new tests, 473 total — including the cross-process spawn pin and both refusal paths (a band-edge predicted refusal stays ok=true with refusal_predicted; a validation refusal surfaces ok=false with the stated reason in stderr_tail).
Full changelog: CHANGELOG.md
v1.6.0 — 挂账清偿:硬吃水扫描模式(扫描与单点设计同空间)
v1.6.0 — 挂账清偿:硬吃水扫描模式(扫描与单点设计同空间)
第八轮挂账清偿第二项:draft_is_hard 扫描模式。此前 v1.4.0 拒绝
了硬吃水 + optimize 的组合(B/T 轴与"解出 B/T"语义冲突,静默混算
= 评估另一条船);本轮把 R2-A 决策(v1.1.0 的 B/T 二分)正式延伸到
扫描:
draft_is_hard: true时,optimize扫 L/B × Cb(B/T 轴必须
钉为单值——它不是被扫描的量,显式拒绝多值轴),每个候选解出 B/T
(±1 cm 二分),扫描的可行域与单点run终于在同一设计空间;- 解出的 B/T 落进每一行与 CSV;scan summary 声明模式
("hard draft - B/T solved per candidate to the declared X m"); - 够不到声明吃水的候选按零外推承诺记录为
hard_draft拒绝(带
端点数字),不是崩溃; - 硬模式下天气默认的受风面积取硬平衡的干舷(交付的那条船)。
测试:448 项全绿(446→448)。数值链零改动(软扫描路径与全部
既有验收数字不变)。同轮清偿顺带:resistance 注册表与模块文档不再
把 Holtrop-Mennen 写成"待源论文"(v1.5.0 起过时的表述)。
C₀ 图 7-3 下沿谱系如实挂起:数字化工具链已建(标定/叠加/站窗,
归档知识库 _render_tmp),但放大目核发现图内曲线比标签多(约
每 0.15 一个谱系间隔,标签只覆盖一半曲线),手工描线的读数歧义
(哪条曲线对应哪个标签)超出验收容差——宁可不交数,不交错数。待
后续会话以描线板方式细做或业主裁定容差。
Assets 附源码 tarball 与 SHA256;锁定精确 commit:57eabb7366b5f23a3a0961ff8d62525d880c1ccd。
v1.5.0 — 挂账清偿:Holtrop-Mennen (1982) 有效功率法入库(论文算例零缺陷复现)
v1.5.0 — 挂账清偿:Holtrop-Mennen (1982) 有效功率法入库(论文算例零缺陷复现)
业主指示"挂账的自己 web search、按宪法实施"。头号挂账——Holtrop &
Mennen 有效功率法(VALIDATION §3.1 的注册占位,卡在"缺源论文")——
本轮 discharge:
流程(严格按宪法顺序)
- 源论文定位并归档:Holtrop & Mennen (1982), ISP vol. 29, pp. 166–170
(公开大学课程镜像全文扫描;IOS Press 出版元数据交叉核对);同一 PDF
附 Holtrop (1984) 再分析(334 模型样本)——已归档、注册、未实现; - 页核转录:全部公式对照渲染页图像目核(OCR 指数不可信),20+ 个
论文自带算例中间量逐位复现——零声明缺陷(转录过程中排除了两处
转录自身错误:波浪阻力式的 ∇ 项、i_E 回归式的负号;以及 Cp 口径——
论文 Cp 介于 Lpp 与 LWL 之间,模块接受声明 Cp/C_B 或按 LWL 推导并
声明口径); - §5 白名单先行:AGENTS.md 修订单独提交(f61578d),含 lcb 基准
(½L、%LWL,算例验证 −2.02 %Lpp → −0.75 %L 的换算)、两处公式
符号差异(形态因子加号 / i_E 减号——原文如此)、适用域声明; - 实现
openhull.holtrop(库层,用于验证与交叉核对——有意不接
入默认链,照 Kwon 库层先行的先例;接线与守卫重构是下一增量提案); - 验收锚:论文自带算例(第 170 页数值表)= 宪法锚点分类中的"书内/
论文算例"类——20 个印刷量全部逐位钉死(tests/test_holtrop.py)。
如实声明:JBC 波段外部锚(±10–15% 计划验收行)保持未结——
东京 2015 EFD 表在 workshop proceedings 里,本轮未能取得权威表格源;
取得后即补该行。这不是静默放弃。
数值链零改动:默认链功率仍是艾亚法;446 项测试全绿(440→446,
6 项新锚)。Assets 附源码 tarball 与 SHA256;锁定精确 commit:
7acd452953dc581c1c43529f30bcd1076e28003b。
v1.4.0 — 第七轮端到端 QA 收口:任务书输入契约落地
v1.4.0 — 第七轮端到端 QA 收口:任务书输入契约落地
独立端到端 QA(45 组探针 + 源码通读,业主委托)对 v1.3.2 的结论:
数值链健康、逐字节可复现;全部缺口集中在输入层——未知键、类型错、
重复键、残缺块一律静默通过或裸栈崩溃(16 条:2 P0 / 6 P1 / 8 P2,
其中 11 条同源于"输入契约缺失")。本轮把这一层建起来,16 条全部处置:
P0
- OH-01:任务书缺
kg_m时run直接崩(文档明示可选)——两个初始化
变量误写在if kg_m块内。已提出块外,文档行为恢复; - OH-02:8 类非法输入走裸栈回溯且 exit 1 与 check 的"拒绝=1"撞车。
三层修复:加载层(UTF-8/GBK 指引、YAML 行号、目录路径检查)、
_number数字助手(字段指认)、main()兜底 except→exit 2
(OPENHULL_DEBUG=1可重抛);exit 1 归 check 独占。
输入契约(新)
- OH-03 键白名单:未知/拼错键拒绝 + 大小写不敏感拼写建议
("did you mean 'kg_m'?")——白名单上线当天就抓到我们自己
v1.3.0 测试里夹带的私生键; - OH-15 重复键拒绝(带行号)——旧版"末值静默获胜"曾造成过
+18.8% 功率的隐形改动; - OH-04 效率显式判空:
or 1.0曾把声明的 0 换成最乐观的 1.0,
轴功率低报约 2%——现在拒绝并给典型区间; - OH-14 船型白名单:
ship_type从不参与计算(写 tanker 出散货船),
现拒绝并说明,直到分船型统计校准落地; - OH-05 缺
shaft_immersion_m时空泡校核不再无声消失:
JSONcavitation_skipped+ 报告声明行(控制台原本就有)。
一致性
- OH-07:run/check/rao 共用一个平衡解析器(
draft_is_hard同船);
optimize 显式拒绝硬吃水(扫描的 B/T 轴与硬吃水互斥); - OH-09:check 恒真关卡标
PASS (statistical constant);
draft_is_hard验收锚改为被求解的量(B/T vs JBC 2.727 = +1.7%)、
声明 L/B=6.0 vs JBC 6.222 的口径差(AGENTS.md 同步修订); - OH-11:扫描拒绝直方图统一
ayre单名(原ayre/ayre_band双名); - OH-06:图表降级按真实原因分型(依赖缺失/路径不可写/未预期),
不再一律"请重装"; - OH-13:报告 §5 增列轴功率 PS(主机选型输入)。
文档与产物
- OH-08:旗舰示例如实定位——TB-001 在 JBC 真实 14.5 kn 落在艾亚带外,
功率段声明式拒绝是产品纪律的演示;README 双语 + demo README
开门见山说明,全链成功路径指向技能模板(45,000 t / 16 kn); - OH-10:demo_outputs 全套按当前链重生成(原 CSV 落后 15 个版本且
混有 stderr 脏行),并加逐字节漂移测试; - OH-12:README 测试数/版本钉/示例吨位纠正("25 万吨"实为
14.99 万载重吨 Capesize); - OH-16:新增
tests/test_taskbook_contract.py——每条拒绝一个测试,
断言退出码 + 字段名 + 无堆栈。
数值链零改动:440 项测试全绿(428→440,12 项新回归),此前全部
验收数字不变(QA 复核可复现性为逐字节相同)。Assets 附源码 tarball
与 SHA256;锁定精确 commit:eb83b122fc308258263ce9d9e74e632fc30d52a8。
v1.3.2 — 第六轮复核收口:run 的画图守卫补齐 + 幻影路径清偿
v1.3.2 — 第六轮复核收口:run 的画图守卫补齐 + 幻影路径清偿
第五轮复核的受控实验(藏起 cycler)确认 optimize 守卫修得干净——
同一个探针随即挖出同族缺口:run 自己的两个画图参数完全没守卫,
坏环境下 exit 1、17 行裸堆栈;配上 --report 时因为一张可选图,
主交付物报告一个字都没写。本轮把守卫补齐到全部三处:
修复
_write_optional_chart通用守卫,三处画图调用共用(静水力曲线图 /
总布置图 / 扫描图):坏依赖降级为一句声明(stderr + JSON 的
chart_notes),报告与数据产物照常完整,声明里带补救指引
(卸载、清%APPDATA%\uv\tools\openhull、重装——即 SKILL 安装应急);- 幻影路径清偿:降级时
outputs.chart不再列出那张没生成的 PNG
(恢复 v1.0.1 不变量——outputs 里列出的文件必定真实写盘),声明
顶替其位;顺带清掉run_taskbook里一行重复return。
新增
check的零成本提示:importlib.util.find_spec存在性探测
(毫秒级,不 import matplotlib)发现绘图依赖缺失时加一行控制台
提示——退出码契约不动(0/1 只关于设计,不关于环境),--json
不含该提示(采纳复核方意见,不把环境问题混进 check 的语义)。
测试:428 项(423→428,5 项新回归:run 两条降级路径的报告幸存、
JSON 带声明不带幻影路径、check 提示行与 --json 纯净)。45,000 t 默认
路径与 TB-001S 扫描经复核方逐位复测零漂移。白名单公式零改动。
Assets 附源码 tarball 与 SHA256;锁定精确 commit:51b59f7d7175abc734504c93e16e62bef3abf6a7。
v1.3.1 — 第五轮核查收口:过期文案清偿 + 图表降级 + 门面双语化
v1.3.1 — 第五轮核查收口:过期文案清偿 + 图表降级 + 门面双语化
外部核查方(前四轮同一人)对 v1.1.0–v1.3.0 做了第五轮真机核查:所有
可量化声称逐位复现(硬吃水锚 / check 预检 / 可行界提示 0.816 vs 独立
实测 ≈0.815 / Kwon 1.71% / 天气默认 980 m² / 基线零漂移 / 419 测试)。
本轮把报告发现全部处置:
修复
- SKILL.md「常见追问」的 Kwon 段落仍是 v1.2.0 时代的"尚未接入 run 链",
与同文件 v1.3.0 章节自相矛盾——agents 会照抄 SKILL,这是本轮唯一
"主要"项(发现 6.1);已改写为已接入契约; optimize图表:绘图依赖残缺时不再裸抛第三方堆栈——降级为声明式
说明(控制台一行 +outputs.chart_note),CSV/JSON 数据产物完整
(发现 6.2;3 项新测试含 monkeypatch 端到端);- 控制台 Kwon 行改 "1.7% slower":原 "-1.7%" 扫一眼像在提速(6.4)。
新增
- SKILL 安装段两则应急:uv
os error 5malformed-tool 的抢救步骤、
慢网络 tarball 兜底安装(发现 6.2/§7); - SKILL 机器可读字段路径速查:
resistance_sensitivity在
propeller_design里不在顶层、cavitation_unchecked、
feasibility_hint、seakeeping.speed_loss(发现 6.3); - README 双语改版(业主指示):README.md 默认即中文全功能版,
英文移至 README.en.md,README_zh.md 改跳转防断链,8 个小语种占位
退役(过时翻译比没有更不专业);仓库 About 官网字段指向
openhull-site。
记录:发现 6.5——changelog 的 4.8324 出自 10 万吨书,核查方在
4.5 万吨书量到 4.8322,差 0.0002 属书口径差,不改数字。
白名单公式零改动(423 项测试,419→423)。Assets 附源码 tarball 与
SHA256;锁定精确 commit:d47f0bddccf66034e27294bef4559eb90890cff5。
v1.3.0 — 账上能做的全做掉:check 预检、Kwon 接线、天气默认、可行域提示
v1.3.0 — 账上能做的全做掉:check 预检、Kwon 接线、天气默认、可行域提示
业主指示"现在能做的就把它做掉"——外部审查(产品审查第六轮)延期的五条 P1
中无外部障碍的全部,加上顺手的小 P2。白名单公式一个没动(419 项测试,
此前 419→数字不变;check 只编排现有守卫,可行域提示与吃水提示同属
"口径随数字声明"的反算类)。
P1-3:openhull check 预检(秒级)
只跑链条里便宜的部分(重量平衡 + 比值代数),预测完整 run 会撞哪些守卫带,并给出数字:
Lpp / B / D / T : 249.74 / 41.62 / 22.30 / 15.416 m (soft draft mode)
weight balance : 0.0856 ['<= 0.1 %', 'converged'] PASS
Froude number : 0.1914 [0.1, 0.25] PASS
Ayre C0 family band : 4.8324 [4.88, 6.41] REFUSED (predicted)
declared draft vs… : 0.6130 ['<= 0.05 m, else reported'] WARN (reported in run, not fatal)
verdict : 2/9 gates predict a refusal - adjust before running
退出码 0(可跑)/ 1(预计拒绝);--json 出机器可读门列表。审查者的 Cb 0.84
案例预测 C₀ 拒绝于 4.8324——与其扫描实测 4.832 逐位吻合。全链独有阶段
(IS Code 衡准/空泡/耐波性)如实列出不猜。
P1-1b:Kwon 波浪失速接入 run
seakeeping:
speed_loss: {beaufort: 6, direction: head}报告 §6 / 控制台 / JSON 三处给出:ΔV/V₁ = 1.71%(V₂/V₁ 0.9829,即损失
0.31 kn)——与库层数值一致。出数域是诚实的:Cb 0.80 @ Fr 0.19 就拒绝
(Kwon 方法页核适用域如此,肥大低速船常在域外),拒绝原样转述。不给海况时
报告明示"所有功率均为静水值"。
P1-5:weather_criterion: default
不想手工推导受风面积时一行搞定:面积 = Lpp×干舷(忽略上层建筑——偏不保守
方向,明示)、力臂 = 型深/2、舵龙骨 0、水线长 1.025×Lpp——JBC 任务书手工
推导的同一套,产品化进 run 和 optimize,报告 §4 列出全部推导并请总布置
细化后回填实测值。
P1-2 前半:拒绝块带可行域数字
艾亚拒绝现在附最近可行 Cb(口径声明:保持排水量与 L/B、B/T 不变的一次
反算)——审查者 Cb 0.84 案例给出边界在 (0.78, 0.82],与其实测 0.80–0.82 吻合;
速度带拒绝则给出本船几何下的可达航速窗口。原 v1.2.0 的 optimize 引导保留。
接口与小项(P2)
--json PATH/--csv PATH可写文件、可同时给;裸旗标保持 stdout;
两个裸旗标同给会被劝阻(stdout 只服务一路);--json纯净性契约跨进程
边界再钉一次(v1.2.0 的教训);--csv-step:静水力表默认 0.1T = 10 行(与曲线图粒度对齐),0.25 恢复
旧 4 行(P2-2);- 报告里两个横摇周期(§4 规范简式 vs §6 书内式)加口径脚注(P2-3);
seakeeping.wave_periods可自定义海区(P2-4);optimize 网格帮助写明
航速如何移动 Cb 带(P2-6)。
供应链
Assets 附源码 tarball 与 SHA256;锁定精确 commit:1e7ec1c0ef4af89ce20ead4cfa583d4ddb3daca1。
还在账上(未动)
PyPI 发 wheel(等挂起的许可决策)、R2-B 第二锚与 Wigley 表源(等检索)、
Holtrop 阻力转录(双法交叉校验)、P2-8 计数自动化。
验证
VALIDATION 第 26 条逐项含数字;测试 405 → 419(tests/test_backlog_batch_v13.py 14 项)。
v1.2.0 — C₀ 峰区敏感性诊断 + 空泡/stdout 诚实契约(产品审查第六轮)
v1.2.0 — 产品审查第六轮:三个 P0 全落地(诊断只加文字,不改数字)
一份以真实用户身份走完整条设计链的产品审查(100,000 t / 20 kn / Cb 0.76)提出 3 个 P0、5 个 P1、8 个 P2。本轮落地全部 P0 + 审查者自己排的 Quick wins——全部是"只加文字、不改数字"的诊断与契约修复:白名单公式、守卫阈值、验收数字一个未动(405 项测试,此前 393 项数字不变;§5 白名单在写码之前修订,提交 6a78084)。
P0-1:C₀ 峰区方法敏感性告警
已数字化的 C₀ 族在 V/√L ≈ 0.70 处见顶(六条曲线全部如此),峰区附近 C₄ 修正会抵消或放大 V³ 增长(审查者船 15→17 kn 每节只涨 9.9%,纯 V³ 应为 21%)。工具从白名单表自身算出:族峰值站位、本点是否在峰区、局部斜率(20 kn 例 −4.8%/0.05)、海军部系数走廊 Ac @ V−1/V/V+1(799.4/754.0/682.0)。三处呈现:报告 §5 ⚠ 声明、控制台一行、JSON resistance_sensitivity。Ac 仅作展示诊断,永不进入数值链(§5 明文)。
P0-2:空泡出带 = "未校核(非通过)"
不再写"声明式跳过":⚠ 未校核(非通过) + 带外哪一侧(低侧 = 空泡风险更高)+ 方向性提示(降转速/加大盘面比/加深轴系浸深)+ JSON cavitation_unchecked。溯源原文不再截断(P2-5)。
P0-3:stdout 快速性段(三态齐备)
run 的 stdout 末尾固定输出快速性段:成功给系列/桨径/ηo/PD·PS/空泡状态/敏感性;拒绝给 stage + 一行原因;未请求给 not requested。
Quick wins
P1-1a Kwon 如实文案(库层已实现未接线,功率均为静水值);P1-2 拒绝块附 openhull optimize --grid-cb … 引导;SKILL.md 关卡表新增 C₀ 峰区行。
供应链(P1-4 部分)
- Assets 附源码 tarball 及其 SHA256:
f7fd94b69ec126088c23230fc2f794a5d3417ecdd5488f6c75eb910f290d8355(与 Assets 中 sha256 文件一致); - 锁定精确 commit:
bae7b1d7c95daf4448d1c43736207fddc9491571。
自查记录
首建 v1.2.0 时一处编辑把结尾提示行顶格到模块层,import 时污染 --json 输出(进程内测试全绿、冷装校验抓到)——已修复并把 --json 纯净性钉到子进程级测试;标签已移至含修复的提交。
挂账(已记录进 CHANGELOG)
openhull check 预检(P1-3)、PyPI 发 wheel(P1-4,与挂起的许可决策联动)、风浪衡准默认模式(P1-5)、Kwon 接入 run 链(P1-1b)、拒绝块可行 Cb 上界(P1-2 前半)、P2-1/2/3/4/6、双阻力法交叉校验(中期)。
验证
VALIDATION 第 25 条:P0-1 现象复现、峰区判定、Ac 走廊、空泡措辞、stdout 三态、子进程级 JSON 纯净性、405 回归全绿。