跳转到内容

材质库来源与设计:工程材料与显示外观的统一身份:手册数据扩充与来源查证

主文档与完整目录。本分篇保留原调查日期的依据与实测记录;其中的当前状态、建议和授权仅属于历史快照,不是执行队列。

14. 选择控件与 D1 执行记录(2026-09-09)

Section titled “14. 选择控件与 D1 执行记录(2026-09-09)”

来源可用性:archive.org 的 milhdbk-5-j 除 70 MB PDF 外还提供 2.26 MB 的文本层 (MILHDBK5J_djvu.txt),可直接检索。

但它只有一半能用。 密集的许用值表在提取中丢失了行标签与列归属—— 6061 sheet 表里 F,„ ksi 与 F^ 之下只剩一串裸数字,靠肉眼把值配回牌号与基准是不可靠的。 而物理常数块保留了标签:

E, 10^ ksi. 10.3 G, 10^ ksi. 3.9 //. 0.33 a>, Ib/in.^. 0.101

所以本批只取物理常数,不取许用值。

更重要的发现,它推翻了 §10.3 对 D1 的一处预期:MIL-HDBK-5J 的强度是 A/B 基准设计许用值,材料卡记的是典型值——这不是同一个量。 实测 6061-T6:手册 A 基准 Ftu 42 ksi(290 MPa)对卡片典型值 310 MPa 差 6.5%, Fty 36 ksi(248 MPa)对 276 MPa 差 10.1%。拿它们互相佐证会制造出一个并不存在的冲突。 因此导入脚本明确不比较强度,只比较非统计量。

导入结果(脚本自动换算 lb/in³、ksi 到 SI,并自动算偏差):

材料 来源 密度 E G ν
6061-T6 Table 3.6.2.0(b1), p. 3-264 0.466% 0.940% 0.764% 0.000%
7075-T6 Table 3.7.6.0(b4), p. 3-374 0.513% 0.963% 0.039% 0.000%

四项全部落在 grade 档容差内(密度 1%、模量 5%),两个铝牌号因此拿到了牌号级佐证, 不再只靠 CC0 通用铝的粗对照。两者的强度仍如实标记为单源。

方法上的结论:这条路是可行但逐表人工的——每个牌号要定位表、辨认块、核对物理自洽 (E ≈ 2G(1+ν))。它不能机械批量抓取。手册里的数字以原始单位与表号记录在脚本里, 换算由脚本完成,所以进入 fixture 的 SI 数值仍然没有一个是手敲的。

文件 改动
LiveWorkbenchController bodyMaterial() 读当前材料;previewBodyMaterial(material | null) 提出变更
LiveWorkbenchOperationDriver 两个方法进 controller surface
MaterialControls.tsx 下拉框:14 个已发布材料 + “未指定”
WorkbenchStructureDock / WorkbenchShell 新增 footer / materialControls 插槽
LiveWorkbenchApp 传入控件
i18n、workbench.css 三个键与一段样式

控件不自己造补丁:previewBodyMaterial 调用 P1 的 createExactBodyMaterialPatchV04, 再交给既有的 previewGraphOperations。于是人工选择与模型的 set-material 步骤 产出同一条 body.put,走同一条路径——一份赋值,两个入口,而不是人工机制旁边再立一个 agent 机制。 未知材料、无变化、无 body 三种拒绝也因此只有一份实现。

放在结构面板的页脚:材料是实体的属性,它该出现在列出该实体的那棵树下面, 不是显示设置,也不是选择动作。

tsc(contracts build + web)、eslint --max-warnings 0、prettier 全过; §13.3 的两个 scratch 脚本重跑通过。

控件没有做可视验证。 live 路线以空模型启动(startMode: 'blank'), 没有 body 时控件按设计是禁用的;要看到它工作需要先有模型,而那需要一次付费模型调用—— 本项目明确要求显式授权。本会话也没有起 dev server(同一限制)。 因此这一批的证据是类型、静态检查与契约级断言,不包括一次真实的点击。


关于提交范围:D0、P1、P3 与选择控件(§11、§12、§13.2、§14)已提交。 P2(§13.1)的代码未包含在该提交中:它构建在并发会话尚未提交的 ExactCadExpectation.preserve、tolerances 与 evaluateExactCadQuantity 之上 (git show HEAD 里三者都还不存在),单独提交我的那部分会得到一棵编译不过的树。 等那批改动落地后,P2 随下一批提交。

15. D1 第二批:MIL-HDBK-5J 十个牌号(2026-09-09)

Section titled “15. D1 第二批:MIL-HDBK-5J 十个牌号(2026-09-09)”

发布 14 → 23 条,金属 5 → 14 条。 手册这次是被引用的来源本身,不再只是佐证。

每个牌号只从一张点名的表的物理常数块读,写进脚本前必须过各向同性关系 E = 2G(1+ν)(容差 ±10%)——块被读错,这条就不成立,assert 直接中断导入。 十个块全部通过。数字以手册自己的单位(lb/in³、ksi)记在脚本里,换算由脚本做。

牌号 表 ρ kg/m³ E G ν vs CC0
AISI 1025 2.2.1.0(b) 7861 199.9 GPa 75.8 GPa 0.32 0.11%
低合金钢族 2.3.1.0(f1) 7833 199.9 GPa 75.8 GPa 0.32 0.46%
17-4PH H900 2.6.9.0(b) 7806 196.5 GPa 77.2 GPa 0.27 2.43%
AISI 301 退火 2.7.1.0(b) 7916 193.1 GPa 77.2 GPa 0.27 1.04%
2024 3.2.3.0 2768 72.4 GPa 27.6 GPa 0.33 2.52%
5083 3.5.2.0(c) 2657 70.3 GPa — 0.33 1.58%
7050 3.7.4.0(c1) 2823 70.3 GPa 26.9 GPa 0.33 4.57%
Ti-6Al-4V 5.4.1.0(b) 4429 110.3 GPa 42.7 GPa 0.31 2.45%
AZ31B 4.2.1.0(b) 1769 44.8 GPa 16.5 GPa 0.35 1.83%
Inconel 718 6.3.5.0(c) 8221 202.7 GPa 78.6 GPa 0.29 7.63%

独立确认:十条的密度与模量与公开文献值全部相差 1–2% 以内 (2024 2768/2780、Ti-6Al-4V 4429/4430、AZ31B 1769/1770、17-4PH 7806/7800……)。 这不是闸门的一部分,是我读完之后的另一次核对。

  1. 5083 不记剪切模量。表里的 3.35×10³ ksi 比该行 E 与 ν 推出的值低 13%—— 超出合金各向异性的量级,像是位数读错。宁可缺一项也不发一个可疑值。
  2. Inconel 718 被扣留(密度差 7.63% 超 generic 档 5%)。这不是错误:CC0 库里 Nickel 是元素,镍基高温合金不是镍。闸门抓住的正是这种精度错配, 如实扣留比强行发布诚实。它要发布,需要一个牌号级的第二来源。
  3. 这批没有强度。手册报的是 A/B 基准设计许用值,而许用值表正是文本提取里 丢掉行标签的那部分(§14.1)。有密度就能算质量,行本身站得住;强度留给后续来源。

命名上两处克制:metal.steel.low-alloy 是族行(一张表覆盖 4130/4140/4340,常数是族的 不是某一牌号的),metal.aluminum.2024 不带回火态(密度与模量属于合金,不属于回火)。 17-4PH 的密度随热处理状态变,所以那一行明确叫 17-4ph-h900。

逐表人工,不能机械批量抓:定位表 → 辨认块 → 过自洽检查 → 记录表号。 十个牌号一轮是合理节奏。手册文本里还有 130 处密度行、113 个带标签的 G 行, 所以这条路还能继续走很远——只是每一轮都是这个代价。

16. D1 第三批:再八个牌号(2026-09-09)

Section titled “16. D1 第三批:再八个牌号(2026-09-09)”

发布 23 → 31 条,金属 14 → 22 条。

牌号 表 ρ kg/m³ E G ν vs CC0
15-5PH 2.6.7.0(c) 7833 196.5 GPa 77.2 GPa 0.27 2.08%
PH13-8Mo 2.6.6.0(b) 7723 195.1 GPa 75.8 GPa 0.28 3.47%
17-7PH 2.6.10.0(b) 7640 199.9 GPa 79.3 GPa 0.28 4.50%
AM-355 2.6.2.0(c) 7806 199.9 GPa 75.8 GPa 0.32 2.43%
AerMet 100 2.5.3.0(b) 7889 193.1 GPa — 0.305 0.24%
5052 3.5.1.0(b1) 2685 69.6 GPa 26.5 GPa 0.33 0.56%
6013 3.6.1.0(b) 2713 68.3 GPa 26.2 GPa 0.33 0.47%
Ti-8Al-1Mo-1V 5.3.2.0(b1) 4373 120.7 GPa 46.2 GPa 0.32 3.67%

八个都过了 E = 2G(1+ν)(AerMet 100 除外,见下),事后对文献也全部落在 1–2% 内。 AerMet 100 的 E 与密度对上 194 GPa / 7890;17-7PH 的 0.276 lb/in³ 与厂商数据表一致 (不是某些资料里 7.81 g/cm³ 那个数,那属于别的 PH 牌号)。

这一轮丢掉了两张表,理由记在这里而不是悄悄跳过:

  • 7475-T761(7.5.2.0(b)):ω 那一列是 0.085 | 0.083 | 0.082 | 0.081——铝不可能是这个密度。 这张表在断裂韧性章,提取时把行合并了,整块不可信。
  • Ti-5Al-2.5Sn(5.3.1.0(b)):标签与数值完全脱开,值列从厚度表头开始,无法确定归属。

AerMet 100 不记剪切模量:表里印了,但那个值没能通过文本提取, 而各向同性检查不能拿一个没读到的数去跑。

重合金化的牌号过不了元素级对照。 Inconel 718 差 7.63%,2219 铝差 5.59%(因此本轮没收), 铍铜 C17200 与锰青铜按同样算法也会超。原因不是数据错,而是 CC0 库里 Nickel、Copper、 Brass 是元素或基础合金,用它去卡一个重合金化牌号本来就太钝。

后果是铜族目前进不来:手册没有纯铜,CC0 有纯铜但对不上铜合金。 要解开这一类,需要的是一个牌号级的第二来源,不是放宽容差——放宽只会让检查失去意义。 这是下一步该解决的事,也是 §10.2 里铜/黄铜/青铜那 20 条目前空着的原因。

17. 解开牌号级对照的卡点,并补上铜(2026-09-09)

Section titled “17. 解开牌号级对照的卡点,并补上铜(2026-09-09)”

发布 31 → 35 条,金属 22 → 26 条。 这一轮先修的是 §16.2 那个模式的根因,而不是继续堆牌号。

原来的两档把两种完全不同的检查混成了一档:

  • 拿 PC 的通用值去对 CC0 的 Plastic (PC)——同一种东西的两个代表;
  • 拿 Inconel 718 去对 CC0 的 Nickel——一个重合金化牌号对一个纯元素。

第二种被 5% 的 generic 带卡住,但那个带对它没有意义。新增 element 一档:

档 密度 模量 强度
grade 1% 5% 10%
generic 5% 10% 20%
element 10% 15% 30%

为什么 10% 不是放水:跟元素比只回答一个问题——这是不是这种金属。 合金化本身就能把密度挪几个百分点(镍基高温合金离镍 7.6%,铝合金离铝最多 6%)。 而这一档要抓的错误比它大一个数量级:单位忘换是 ×27,680,用错金属是几十个百分点。 它抓不出用错牌号——但 5% 那档同样抓不出(两个铝合金也就差 4%)。 所以收紧只是在否掉正确的行,不是在多抓错误。

容差按两侧较钝的一方取(element < generic < grade),佐证条目自己声明属于哪一档, CC0 每一条也在导入脚本里显式标注是元素还是族(Nickel 元素、Stainless Steel 族、 Plastic (PC) 通用)。

结果是精准的:Inconel 718 解开发布(7.63% < 10%),而 PVC 依旧被扣留(6.15% > 5%)——两个通用 PVC 来源之间的分歧是真分歧,这一档没被动过。

MIL-HDBK-698A(铜与铜合金)在这里拿不到(everyspec 403,archive.org 没有)。 但5J 第 7 章本来就有铜合金,加上新的 element 档就够了:

牌号 表 ρ kg/m³ E G ν 对照
C17200 铍铜 7.3.2.0(c) 8249 127.6 GPa 50.3 GPa 0.27 element 7.73% ✓
C86500 锰青铜 7.3.1.0(c) 8332 103.4 GPa — — generic 3.12% ✓
C86300 锰青铜 7.3.1.0(d) 7833 97.9 GPa — — generic 8.91% ✗ 扣留
铍(结构级) 7.2.1.0(b) 1855 289.6 GPa 137.9 GPa 0.10 element 0.25% ✓

C86500/C86300 的剪切模量与泊松比表里印了标签却没留下值,所以两行都没有各向同性检查—— 如实缺项,不猜。C86300 的密度离黄铜 8.91%(高强锰青铜确实如此),继续扣留: 它需要的是更贴近的对照,不是更松的带。

铍这一行的 specificity 是 element——材料本身就是元素,所以行和对照同档,这是新增那一档 在行这一侧的第一个用例。

17.3 闸门抓到了导入器的一个真 bug

Section titled “17.3 闸门抓到了导入器的一个真 bug”

加铜合金时构建失败:

material metal.brass.c86500: singleSourceProperties names poissonRatio, which the row does not report

原因是 handbookProperties 无条件写 poissonRatio: reading.poissonRatio, 表里没有泊松比时这个键带着 undefined 存在——Object.keys 看得见它, JSON.stringify 看不见。于是行“声称”报告了一个它并不报告的属性。 这正是“每个属性要么有佐证、要么显式声明单源”那条规则该抓的东西,它抓住了。

18. D1 第五批:再十一个牌号(2026-09-09)

Section titled “18. D1 第五批:再十一个牌号(2026-09-09)”

发布 35 → 46 条,金属 26 → 37 条。 十一个全部通过,没有新增扣留。

牌号 表 ρ kg/m³ E G ν 对照
2219 铝 3.2.8.0(c) 2851 70.3 GPa 26.9 0.33 element 5.59%
9Ni-4Co-0.30C 钢 2.4.3.0(b) 7750 196.5 GPa — — element 1.52%
Custom 450 2.6.3.0(b) 7750 193.1 GPa 77.2 0.29 generic 3.12%
Custom 455 2.6.4.0(b) 7750 196.5 GPa 77.9 0.27 generic 3.12%
工业纯钛 5.2.1.0(c) 4512 106.9 GPa 44.8 — element 0.62%
Ti-6242 5.3.3.0(c) 4540 113.8 GPa 42.7 0.32 element 0.01%
AZ91E 镁 4.3.2.0(c) 1805 44.8 GPa 16.5 0.35 element 3.90%
ZK60A 镁 4.2.3.0(b) 1824 44.8 GPa 16.5 0.35 element 5.01%
Inconel 625 6.3.3.0(c) 8442 205.5 GPa 81.4 0.28 element 5.14%
Inconel X-750 6.3.6.0(b) 8249 211.0 GPa 81.4 0.30 element 7.32%
L-605 钴基 6.4.1.0(b) 9134 224.8 GPa 86.9 0.29 element 2.63%

2219 是上一批点名扣留的那条,element 档一开就进来了(5.59% < 10%),这是 §17.1 那次改动 在新数据上的第一个直接兑现。密度与模量对文献仍然全部落在 1–2% 内。

18.1 检查规则被一个真实案例修正了

Section titled “18.1 检查规则被一个真实案例修正了”

工业纯钛这一行让导入直接中断:

Table 5.2.1.0(c): shear modulus is NaNx the value E and the Poisson ratio imply

原因是各向同性检查只看有没有 G,而这张表给了 E 和 G、没给泊松比—— 拿一个不存在的数去算,结果是 NaN。规则改成三个都在才检查: 两个值的块留作未检查,而不是拿一个没人印出来的数去“检查”。

顺带一个判断:CP 钛的 E=15.5、G=6.5 反推出的泊松比是 0.19,比通常引用的 0.34 低得多。 这不是读错——钛是六方晶系,公开的 E/G 对本来就推不出那个 0.34(文献 103 GPa / 45 GPa 反推是 0.14)。所以两个值都照收,泊松比一个字不填,这一行就没有各向同性检查。 不猜是这里唯一正确的做法。

9Ni-4Co-0.30C 同理只有 E 和密度:表里印了 G 与 ν 的标签,后面没有值。

19. D1 收尾:手册读完(2026-09-09)

Section titled “19. D1 收尾:手册读完(2026-09-09)”

发布 46 → 72 条,金属 37 → 63 条。 MIL-HDBK-5J 的物理常数块已经读到底。

铝 13(2017、2026、2124、2424、2519、2524、2618、5454、5456、6151、7010、7040、7049)、 镁 3(AZ61A、QE22A、ZE41A)、钛 1(Ti-15-3)、 钢与不锈钢 4(5Cr-Mo-V、9Ni-4Co-0.20C、Custom 465、PH15-7Mo)、 镍与钴 5(Inconel 706、Rene 41、Waspaloy、HAYNES 230、MP35N)。全部发布,无新增扣留。

密度与模量对文献仍然逐条落在 1–2% 内(MP35N 8415/8430、HAYNES 230 8968/8970、 Inconel 706 8083/8080、Ti-15-3 4761/4760、2618 2768/2760)。

手册里带物理常数块的表共 129 张(去重后)。逐个牌号核对,未被引用的只剩四张, 而这四张都是读过并明确拒收的:

表 情况 处理
2519(3.2.11.0(b)) 模量标签在,值整段丢失 只收密度
2524(3.2.12.0(b)) primary/secondary 合并成一个标题,四个数分不清谁是谁 只收密度
7475-T761(7.5.2.0(b)) 密度列是 0.085–0.081 lb/in³,铝不可能 不收
Ti-5Al-2.5Sn(5.3.1.0(b)) 标签与数值分处两段,按厚度表头排列,无法归属 不收

所以“读完”的准确含义是:每一张有物理常数块的表,要么被引用,要么有记录在案的拒收理由。 不存在“看过但忘了”的表。

同一类错误的另外两次:

material metal.stainless.custom-465: youngsModulusPa (null) is outside the admissible range
material metal.steel.5cr-mo-v: youngsModulusPa (null) is outside the admissible range

只有密度的读数里 youngsModulusKsi 是 undefined,undefined * KSI_TO_PA 得到 NaN, 序列化成 null。连同各向同性检查也要改成三个常数都在才跑(此前只检查了剪切模量与泊松比, E 缺失时又会算出 NaN)。

三次都是同一个形状的错误(§17.3 的泊松比、这里的杨氏模量与检查前置条件): 可选字段无条件赋值。闸门三次都抓住了,因为它检查的是“行声称报告了什么”与“行实际报告了什么”是否一致—— 这条规则不是为了抓这类 bug 设计的,但它抓住了。

72 条材料 / 43 个外观类,金属 63 条,覆盖钢、不锈钢、铝、钛、镁、镍、钴、铜、铍、 以及塑料 4、玻璃 3、混凝土 2。对着 §10.2 的 ~186 条目标,金属那半边(~133 条)已完成约一半, 且这一半是牌号级的。

D1 到此结束。剩下的覆盖缺口不再是手册能补的:

  • 铜族:手册只有 C17200 与两种锰青铜,纯铜与常用黄铜青铜都不在其中;
  • EN/GB 结构钢与铸铁:手册是美制航空体系,没有 S235/S355/EN-GJL;
  • 工程塑料与弹性体:手册不涉及。

这三块要各自的来源,属于 D2 与 D3。

20. D2 与 D3:来源查证与一处规则修正(2026-09-09)

Section titled “20. D2 与 D3:来源查证与一处规则修正(2026-09-09)”

结论先说:D2 与 D3 计划里点名的来源,逐一查证后全部不可用——不是工作量问题,是来源本身。 这一轮的产出是这份查证记录,加一处不依赖新来源的规则修正。

目标 候选来源 结果
铜族(纯铜、常用黄铜青铜) MIL-HDBK-698A《Copper and Copper Alloys》 everyspec 403、DTIC 403、archive.org 无此条目
铜族 MIL-HDBK-5J 第 7 章 只有 C17200 与两种锰青铜(已收),没有纯铜
铜族 / 元素密度佐证 NIST 低温材料库 可达,覆盖无氧铜、黄铜 C2600、铍铜、304/316、6061-T6、Inconel 718、Ti-6Al-4V、尼龙、Teflon——但只给随温度变化的曲线拟合系数(导热、比热、膨胀、弹性模量),没有密度。密度是闸门的必填项,因此它既不能当引用源,也不能当密度佐证
聚合物外观(ABS/PA6/PLA/PTFE) refractiveindex.info 数据库(CC0-1.0) 有 PLA、PET、PC、PVC、PMMA、聚苯乙烯、聚乙烯;没有 ABS、聚酰胺、PTFE。而且它只给折射率,不给密度
EN/GB 结构钢与铸铁 EN 10025 / GB/T 标准正文付费,无 PD/CC0 的机器可读版本

所以两条线各缺一样东西:铜族缺一个带密度的公有领域来源; ABS/PA6/PTFE 缺任何一个第二密度来源(FreeCAD 卡给了密度,但没有第二方可比)。

查证过程中暴露出一条本来就写错的规则:unknown-appearance-class 曾是扣留理由之一。

它把两件事混成了一件。外观是材料的投影,不是材料本身。 没人测过 PTFE 的颜色,不改变一块 PTFE 零件有多重—— 为了省一种灰色而扣留整行,代价是这种材料做的每个零件都算不出质量。 这和 §17.1 是同一形状的错误:一条规则盖住了两个不同的问题。

改法:这条扣留理由删除。没有可发布外观的行照常发布,用显示默认值绘制 (与未赋材料的实体相同),packet 仍带 materialId,所以界面知道它是什么。 构建输出新增一行,点名哪些行是这样绘制的——默默这样做会看起来像显示 bug。

效果:发布数不变(72 条现在都有外观类),但扣留原因从 12 条降到 7 条。 木材、ABS、PA6、PLA、PTFE 现在只剩一个理由——no-corroboration, 那才是真正挡住它们的东西,也是可行动的那一个。

  • 铜族:一个带密度的 PD/CC0 铜合金来源。MIL-HDBK-698A 是对的文档,只是这里拿不到; 能拿到它的人跑一次 §15 的读法即可,导入器不用改。
  • ABS / PA6 / PTFE / 木材:一个第二密度来源。厂商 TDS 可以逐条引用,但要逐条判定可引用性 (这是 D3 原本的做法),不是一次性导入。
  • EN/GB 钢与铸铁:需要标准正文,或一个引用了它们且许可可用的公有领域文档。

在此之前继续堆手册牌号不会碰到这三块——手册已经读完(§19)。

21. 对齐记录:材质工作与当前仓库(2026-09-14)

Section titled “21. 对齐记录:材质工作与当前仓库(2026-09-14)”

§10–§20 写于 2026-09-09,之后五天并发会话把产品结构(M1)与工程定义(M2)做完, 其间改动了材质工作的四个接点。本节按当前 HEAD 逐项核对代码,记下记录与代码不再一致的地方; §12–§13 的原文按“历史快照”保留,不回改。

3eb571bb(2026-09-13)把原来 1002 行的单篇按 §1–§9 / §10–§13 / §14–§20 拆成三个文件, 目录在主文档。内容无删减。

21.2 代码侧四处变化(并发会话所为,此前本文未记)

Section titled “21.2 代码侧四处变化(并发会话所为,此前本文未记)”
  1. 材料封套改了形状,Core 才接受它。 a12fc062(2026-09-09 10:50,比 §20 的提交晚一小时) 把 Body.extensions['aira.material/0.1'] 从 { materialId } 改为 { semantic: true, version: '0.1.0', materialId }。原因有两个,§12.3 当时都没看到: Core 的 validate.rs 只放行 SUPPORTED_SEMANTIC_EXTENSIONS 里的命名空间,aira.material/0.1 不在其中,所以真实赋材质在 Core 静态校验就被拒;而 canonical.rs 的 semantic_extensions() 只把 semantic: true 的封套投影进 modelHash—— 裸封套即使被放行,材料也不会进模型身份,两个只差材料的修订会得到同一个哈希。 现在 Core 校验封套的三个键(materialId 非空且 ≤128 字符),材料进 modelHash; 旧裸封套不再接受,没有迁移。§12.3 说“没有改 AMIR schema”在 schema 文件的意义上仍然成立, 但它漏掉了 Core 必须认识这个命名空间这一层。
  2. set-material 必须指名 bodyId。 a034cb13(2026-09-12)之后文档持有多个 Body 是常态, §13.1”不指名 body,由 host 解析文档中唯一的 body“不再成立;契约与 schema 都要求 bodyId, 期望值量的是这个 body,“including when it is not the main root”。同一步在 a12fc062 起可带 requirements,材料与持久要求进同一个候选、一次提交。
  3. 守恒检查照旧,只是基线换了取法。 质量基线从候选所基于的 head 读取实际输出 body 的材料 (exact-cad-plan.ts L1488–1493), 不再依赖调用分支是否传入节点 ID;affects: [] + enforce: true 保留(L1516–1523), 缺材料时的诊断仍指名缺失的那一半。
  4. BOM 消费了材质。 M2 的 productBillOfMaterials 对每个 Body 调 readBodyMaterialId,按物料号/版本归并后给出 materialStatus: consistent / unassigned / conflict(同一物料号下多种材质),经 aira_model_read({bom:true}) 可读。 这是材质工作在本文之外的第一个消费者。

并发会话在 a12fc062 用外部 Chrome 经同一 SDK 做了真实验证:6061-T6 与持久要求共同提交, 底孔八列改十列时质量期望通过,撤销/重做与重开后材料保留。这补上了 §13.3”没有做可视验证” 里端到端那一半;屏幕上的外观仍未经人眼核对。

仓库里现在有两个不同的身份,名字相近,必须分开:

材质(本文) 物料身份(M1/M2)
回答的问题 这个 Body 由什么做成 这个 Body 在 BOM 里算哪一项
落点 Body.extensions['aira.material/0.1'] product.partIdentities[bodyId] → partNumber / partRevision
派生 密度 → 质量;class → 外观 归并数量、层级用量、STEP PRODUCT 记录
写入 set-material / 选择控件 set-product / product.put

产品结构方案 明确“不能按形状相同或 Body 相同自动决定物料相同”, 同理也不按材质相同决定物料相同。探测环 R3 的“物料身份”只指右列;BOM 是两者唯一的交汇处。

发布表 72 条 / 43 个外观类、扣留 7 条(§20.2);闸门与导入器未动;选择控件仍挂在 LiveWorkbenchApp;外观投影与 AS_MACHINED_ROUGHNESS 未动; P4(3MF <basematerials>)未开始,export.ts 里没有该元素; D2/D3 仍卡在 §20.3 列的来源上。

§7.4 规划、此前一直没做的那一项。对齐(§21)时查证:set-material 拼错即拒绝,拒绝文案让模型 “去查材质库”,但没有任何工具能查——aira_library_reference 只索引 Replicad 程序库。 72 条材料因此只对人(选择控件)可用,对模型只在猜中拼法时可用;探测环也从未碰过材质。

不新建工具。aira_library_reference 的每个查询词同时问一遍材质库,命中时结果多出一段 materials(total / nextOffset / entries,与 Replicad 段共用 offset、limit 分页):

  • 精确拼法先答(id / 标准号 / 别名 / 名称,复用 findMaterial);
  • 其余按词排序:id 段命中 > 其他拼法命中 > 前缀 > 子串,命中词更多的行在前 (searchMaterials,放在契约里而不是工具里,选择控件将来可复用);
  • 族词表在 host:aluminium→aluminum、fiber→fibre、不锈钢→stainless、钛合金→titanium、 高温合金→nickel/cobalt 等——一次查不中就是一次往返,这张表是最便宜的省 token 项;
  • materials / 材质库 列全表分页;被扣留的行不出现。

摘要行只带决策用得着的东西:身份、标准号、密度、三个强度及其 basis、有无外观; detail: 'full' 才给全部物性、别名与引用。实测一页 8 条摘要约 440 token,一整行约 230 token, 对着 §7.4 估的 200–400 token 量级。

结果契约加在 exact-operation-results schema 的 LibraryReference.materials, 经现有 createExactOperationResultValidator 校验通过,所以公共 Interface 的 catalog.search scope=library 与 MCP 同样拿得到。拒绝文案与 set-material 的 schema 描述 现在都指名这个工具和用法。

rankLibraryEntries 对没有可检索 token 的查询(如一个中文材料名)会返回整个 Replicad 库, 再截成 8 条无关条目。改为返回空——空查询列库的行为在上层单独处理,不受影响。

contracts / cad-tools / web 类型检查、eslint --max-warnings 0、prettier 通过(exact-cad-plan.ts 里另一处不合 prettier 的括号属于并发提交 80e55a30,未动)。scratch 脚本(未入库)覆盖: 五种拼法都解析到 6061;aluminum / aluminium 同族同数;不锈钢、钛合金 只返回对应族; inconel 四条、7075、Ti-6Al-4V、polycarbonate 首位正确;列表与分页边界;Replicad 符号与 步骤种类单独查询不带 materials;混合批量三段齐全;PVC / PTFE 查不到;摘要字段集与 full 字段; 五种结果经真实 wire 校验器通过。

没有做真实模型调用(付费,需授权):模型是否会主动查、查后拼法是否正确,要等一轮带材质的探测。

22.4 一处裁定:标准号只答一行(2026-09-15)

Section titled “22.4 一处裁定:标准号只答一行(2026-09-15)”

closure client 在当前字节上首次跑通材质一节(见 P2 复跑记录)时发现: AA 6061-T6 精确命中后仍回 21 行——归一化后拆成 aa / 6061 / t6 三个词项,命中全部铝行。 那条“只回一行”的断言是我提交时没跑过的;复跑者把它改成“命名行排第一、无第二行带同一标准号”, 并把要不要收窄留给我裁定。

裁定:id 或标准号按定义只指一样东西,答案就是那一样东西;名称与别名是便利拼法,也可能读作族 (steel、铝合金 6061),命名行之后跟着族才是有用的答案。实现是 searchMaterials 在 id / designation 精确命中时直接返回单行;别名路径不变。工具描述同步说明。 6061 这类别名本来就与其他行无共享词项,前后都只回一行;变化只落在带标准号前缀或 可读作族的查询上。

23. P4 改道:材质身份进 STEP(2026-09-14)

Section titled “23. P4 改道:材质身份进 STEP(2026-09-14)”

§10.5 把 P4 写成“3MF <basematerials>”。开工前核对:仓库里的 3MF 导出器 @aira/3mf-export 只接 Lane F 的 Field IR, 没有任何调用方(工作区里无人引用它),而 Lane F 处于暂缓;精确实体从来只导 STEP。 往一个没有驱动方的导出器里加 <basematerials> 是死代码,不做。

同时 §7.5 “STEP 今天只能带名称与颜色、物性要等 XCAFDoc_MaterialTool 绑定”已经过时:M2 给零件 定义接了 TDataStd_NamedData 字符串属性,aira:partNumber / aira:partRevision 就走这条通道进 STEP(SetMetadataMode(true) 写成 PROPERTY_DEFINITION + DESCRIPTIVE_REPRESENTATION_ITEM)。 材质身份用同一通道,零新绑定、不重建 sealed runtime;物性本来就不该进文件,损失照 RFC-0005 申报。

处 内容
编译器 amir-v0.4-exact-feature-graph.ts 产品求值输入的每个 body 带 material: { materialId, name, color? },从已校验的 Body 扩展解析
维护版 exact-product.ts 零件定义追加 aira:materialId / aira:materialName 两个字符串属性,并把材质基色设为零件表面色;执行对象新增 materials(bodyId → materialId)
维护版 exact-step-exchange.ts 回执 preserved 在任一零件带材质时加 material-identities;omitted 固定加 material-properties
结果 schema 两个词汇入枚举,计数随之调整
契约 materialBaseColorHex 库里的线性基色量化成 #rrggbb 交给导出器

颜色的一处实测:维护版导出器把 #rrggbb 直接喂给 Quantity_Color,而 OCCT 的 Quantity_Color 是线性空间,STEPCAF 写文件时自己做线性→sRGB。所以交给它的必须是线性分量——先编码成 sRGB 会把 曲线套两次。实测 #c8c9cb(0.784)写出 COLOUR_RGB(0.898,…),正是 sRGB(0.784)。 纯白(PC)按 STEP 惯例写成 DRAUGHTING_PRE_DEFINED_COLOUR('white')。

aira_inspect_brep 的 definitions[*].stringProperties 本来就原样带回全部字符串属性,所以 Aira 导出的 STEP 再导入时,aira:materialId 出现在检查结果里;按仓库“不自动推断身份”的规矩, 它不自动变成 Body 的材质赋值,由 set-material 显式接上。看得见、要动手——这就是“不新增静默丢失”的口径。

在 Node 里直接加载 sealed OCCT(142 ms)跑通道往返(scratch 脚本,未入库):两个盒体零件分别带 6061-T6 与 PC,writeSTEPDocument 后 Part 21 文本含两组 aira:materialId / aira:materialName 描述项、PRODUCT('PLATE-1'…) 的身份投影未受影响、铝的 COLOUR_RGB 等于 sRGB(线性量化值)(±0.003)、 白色为预定义色;readSTEPProduct 读回两个零件的四个字符串属性,id 能解析回库。 contracts / replicad(含 aira 子程序)/ web / cad-tools 类型检查、eslint、prettier 通过。

完整链已由并发会话跑通(2026-09-15):closure client 的材质一节(f6fbfd63)在干净的 4ed330f3 worktree 上 74/74 通过,从「文件 → 导出 STEP」取得的 20,731 B 经 OCP 独立回读——收据 preserved 含 material-identities、omitted 含 material-properties,文件里同时出现 Aluminum 6061-T6 与 metal.aluminum.6061-t6,密度与强度不在文件里。记录见 P2 复跑。 同一记录指出 STEP 导出在同一修订上不可字节复现(FILE_NAME 时间戳与 occurrence 计数器), 这属于 STEP 写出器而非材质工作,由该处维护者处理。