Skip to content

asset_ledger.v3 契约与资产管线提升进 main(模型级颜色 + 尺寸方案 C + Isaac 首验 + 路径可移植) - #6

Open
huyuxinn wants to merge 36 commits into
mainfrom
worktree/hyx
Open

asset_ledger.v3 契约与资产管线提升进 main(模型级颜色 + 尺寸方案 C + Isaac 首验 + 路径可移植)#6
huyuxinn wants to merge 36 commits into
mainfrom
worktree/hyx

Conversation

@huyuxinn

Copy link
Copy Markdown

这是什么

把 HYX 侧已定稿的资产入库 metadata 契约 asset_ledger.v3 及其配套管线提升进 main,让其他管线可以直接消费统一的资产元数据(检索、验证状态、许可、跨仿真器表示)。契约本体与决策依据:

  • 定稿决策记录:self_improving/asset_pipeline/active/docs/2026-08-15-asset-ledger-v3-decision-record.md
  • 字段手册(各管线环节对齐指南):docs/reports/20260815_ledger_field_handbook.html
  • 本批次执行报告:docs/reports/20260816_six_task_batch.html

共享层改动(请 reviewer 重点看这三个文件)

绝大部分改动(100+ 文件)都在 self_improving/asset_pipeline/ 自己的地盘,纯增量。动到共享代码的只有:

文件 改动 性质
scene_gen/catalog.py CatalogModel 新增可选字段 colors(颜色是 model 的属性:同一资产下黄/红/白三只篮子) 纯增量,缺省空 tuple
scene_gen/grounding.py 模型级颜色判分:命中 +4.0;实测颜色明确缺请求色的 model 拒绝并入 rejected 记录;无颜色信息不受影响(着色回退语义保留) 行为变化见下方实测
scene_gen/envs 一处小修

实测(seed=42,生产目录):yellow basket → 110_basket m1(黄),同资产 m0/m2 因实测色缺 yellow 被明示拒绝;red mug → 039_mug m10(实测红 40.9% 主导)。

其他管线怎么消费

  • 1_asset_reuse/lib/ledger.py 是唯一契约与校验器(validate_ledger / latest_verification——latest-per-(backend,check) + digest 未过期语义);账本在 git:data/asset_library/*/ledger.json + data/upstream_ledgers/
  • 路径可移植:本 PR 起账本内路径一律为 ACTIVE_ROOT 相对(可用 ASSET_PIPELINE_ROOT 环境变量重定向),resolve_uri/to_portable_uri 为唯一转换点;87 份存量账本已迁移,/home|/Users 清零并有测试固化(与 main 的 redact-public-evidence-paths 同向)
  • 投影:catalog/fragment 视图用 scripts/ledger/gen_fragment.py 再生成,不手抄
  • 写验证:只走 scripts/ledger/writeback_verification.py(digest 锚定 + run_id 幂等)
  • 边界:网格本体不入 git(data/ ignored root);22 个 NVIDIA Isaac Props 系 model 的许可为"内部研发可用、禁再分发"(账本 license 块可筛)

合并前自跑冒烟(全部真实运行)

  • 1_asset_reuse 测试 272 全绿;仓库级测试 104 全绿(含 test_public_evidence_redaction
  • 全库账本审计:asset_library 64/65 clean(余 1 为 08-13 已标记的 /tmp webcache 旧指针)+ upstream 16/16
  • SAPIEN 生产链:s12 外部专属 e2e 5/5 PASS;s10 红杯链全过(判据升级为内容判定:选中 model 实测含 red)
  • Isaac 链:302_can 经相对 uri 全链复跑(生产编译→RigidBodyAPI+convexHull 真物理 300 步@120hz)verdict=pass,指标与前日逐位一致

已知残留(如实):320_teddy_bear 一条 /tmp webcache 死指针(08-13 审计已标记,需重新镜像源文件,另行处理);303_boombox 无账本(上游源消失,08-09 已存档)。

🤖 Generated with Claude Code

https://claude.ai/code/session_01MWzzZx8VvE8dNYDEfFjQSg

BorisGuo6 and others added 30 commits August 14, 2026 14:02
迁移到 yuhang-B850M-C 后按"测量必须对着消费它的运行时"原则全量重测
(校准 441/534、探针 14 空腔),暴露 v4 腔底的语义冲突:同一个
interior_floor_z_offset_m 被两个消费者以相反方向拉扯——求解器在
floor+clearance 生成(希望它高,避开格栅缝隙),包含检查要求沉降后的
物体整体在 floor 之上(希望它低,因为载荷真实会陷进缝隙几毫米)。
合并栈上积木停在"+8mm 生成余量"腔底之下 9mm,检查永不可满足。

拆分:腔底 = 载荷实测停留高度 − 5mm(检查安全);防楔入改由 schema
自带的 support_spawn_clearance_m 承担(s9 对发布内腔统一置 0.02)。
B11(把积木放进篮子里)新机复验 fail=0、inside_contained=true。
随提交更新新栈实测的 native_origin_calibration.json 与
top_support_survey.json。265 passed。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1Grc8sYxW5qcP2gUuBsAx
同层 provider 指向同一索引时只显示一次;objaverse 从 lvis-annotations.json.gz
读物体/类别数并显示每类上限。两 workspace 同步补丁。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R79SC1mEtQvTH52T3v2jSP
删(零决策消费者,grep 全覆盖证明):semantic_name、tags、mass/friction 的
runtime_default 对、physical.mesh_up_axis/origin_convention、
representations[].size_bytes。降级:size_resolution 决策留痕四件、
verification[].report_path、source.source_manifest_path。

增(实验实证):external_ids(E2:身份断裂使 ledger-backed Isaac 链在首个
真实资产上 skipped_no_ledger,修复后 compile 全绿);
representations[].frame/geometry_state(E2:无 scale_baked 声明的无条件
scale 中和让 cracker box 在 Isaac 大 2.8527×≡1/scale,30 个 model 命中);
models[].appearance(E1:模型级实测色接入选型后 44 条矩阵颜色真命中
9→23、错配 23→9);physical.placement(可放置性几何入账);
restitution/friction 拆分/惯量主轴(业界最小物理集);
measured_against 强制戳(同库两种互斥姿态语义 + 换加载器停留差 9mm 的
测量-栈耦合实证);BACKENDS+=mujoco。

管线义务落地:gen_fragment 投影 materials(v2 缺失 bug——材质查询永远
命不中外部资产)+ 账本 appearance 作颜色权威(52 资产入 fragment);
usd_enrich 身份键改走 AssetBundle.source、scale 中和以显式 scale_baked
为前提;backfill 实测帧写入 representation。

迁移 79/79 零失败(appearance/placement 自实测文件回填、姿态方言显式化、
上游 scale_baked=false 修正)。测试 262+57 全绿;目录 156 可用;
B11 e2e fail=0。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1Grc8sYxW5qcP2gUuBsAx
TV 案证据链(run 20260815_002333):全角空格被吞 → "Place a TVon the
table" → 整句熔成类目 tvon_the_table → Khronos 无缩略图候选按 unverifiable
放行 → 新机 VLM 缓存路径断(HOME 相对路径破了保真假设)→ 后渲染复核
unreadable 且 fail-open → SheenWoodLeatherSofa 以 tvon_the_table 入库。

四道防线:①a4 入口把一切 Unicode 空白归一为 ASCII 空格;②scene_acquire
拒绝含虚词的解析类目(malformed_category_from_parse,给可读提示而非
采购整句);③unverifiable 放行前要求候选名与类目至少一个实义词交集
(零证据不入库);④后渲染复核对 requested_by_acquire 来源 fail-closed
——unreadable 即拒收(对已带缩略图证据的 basis=vlm 保持诚实降级)。
VLM 缓存已修(yuhang home 软链);362_tvon_the_table 已退役。

蓝衣架案:着色回退对多材质三角网格取聚合 .material 会在 SAPIEN C++ 层
抛 RuntimeError(getattr 默认值救不了),整场渲染崩死——改为 try/except
后走 parts 材质,复跑 fail=0。

262 测试全绿(夹具候选名补类目词以过名字证据滤网)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1Grc8sYxW5qcP2gUuBsAx
她的实测观察:沙发和电视在桌上都和篮子一样大——根因是采购缺省
absolute:0.25 把一切归一到 25cm(0.73m 电视与 43.75m 乱标衣架同罪)。

解耦原则落地:账本存"世界的真",视图管"桌子的取舍"。
①configs/category_sizes.yml:172 类目典型真实最长边(置信度标注,低置信
  待抽查)+ tabletop 视图三档阈值(fit 0.42/cap 0.42/refuse 0.84);
②采购路径:已知类目按真实尺寸(category:<m>)或压包络打标(capped:0.42)
  入库;离谱超限(沙发 2m)采购前即诚实拒绝并给可读理由——资产真实尺寸
  语义保留给未来非桌面环境;未知类目保持旧缺省并记录"这是缺省";
③s9 桌面视图类目排除:典型尺寸超限的 12 类(11 model)在视图层摘除
  placement 而非删资产(换环境即恢复);
④存量回填 rescale_backfill.py(幂等:磁盘网格实测因子;尺寸不变量由
  推导满足):36 个 absolute:0.25 出身的 model 重定标至真实/压限尺寸
  并逐个重验 settle;4 个复检失败诚实剔除(cherry 缩到真实 2.5cm 会滚,
  应当如此);证据定标的 YCB 系资产分毫未动。

实跑验证:TV/hanger 现按 0.42m 出场景且 runtime fail=0;sofa 采购前
拒绝(oversize_for_tabletop_view + 可读 hint);268 测试全绿。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWzzZx8VvE8dNYDEfFjQSg
E1 实验(9→23 命中)用的是 /tmp 补丁副本;本次正式落地四处:
①scene_gen/catalog.py CatalogModel 增 colors 字段(override 通道解析)——
颜色是 MODEL 的属性不是资产的(110_basket 一个 id 下黄/红/白三只);
②scene_gen/grounding.py 模型环:实测色含请求色 +4 分(真色模型胜过一切
未知色候选),实测色明确不含则模型级拒绝,未测保持放行(着色回退不变);
③gen_fragment 逐模型投影 appearance.colors_measured(写入器同步);
④s9 属性补丁将 attributes.json 的模型级颜色注入原生资产 override。

生产实测:yellow basket→m1(黄) / red basket→m0(红) / red cup→301_cup,
资产级时代不可能做到的按色选模型自此可用。268 测试全绿。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWzzZx8VvE8dNYDEfFjQSg
settle_repair.py:滚动类失败的正解不是放宽总位移,而是多起始姿态重测 +
末窗静止判据(滚过再停=合格)。樱桃/管钳/烟感器测得真实静置姿态写回账本
(measured_against 戳齐全);ahead 卷帘路牌任何姿态 6 秒内都停不下来——
诚实剔除。目录 144->147 可用。

许可回填:22 个 NVIDIA Isaac 5.1 Props 按 2026-08-09 审计口径 carry-
forward(Isaac Additional License:内部研发允许、再分发禁止);
351_grid 按 Objaverse 机读标签 CC-BY-SA-4.0(注明 ShareAlike 传染)。
unknown_license_models 23->0;audit 仅剩历史项 303_boombox(上游已消失,
08-09 已档)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWzzZx8VvE8dNYDEfFjQSg
- 2_sim_migration/scripts/isaac_settle_check.py: 生产编译链 + isaac-smoke
  重入自身跑真物理(RigidBodyAPI+convexHull, 300步@120hz, 末窗<2mm 且
  倾角<15°);证据 json 含 applied-schemas before/after 自证非静态空洞
- 302_can m3 / 303_box m0 首批 (isaacsim,settle)=pass 写回账本,
  run_id=isaac-settle-20260816,digest 锚定,幂等复跑验证
- scripts/ledger/writeback_verification.py: 唯一验证写回通道
  (v3 契约"不写回的 Isaac 运行不算完成"的执行工具)
- TV 案清账:362_tvon_the_table(实为沙发)移出资产库,
  acquired_manifest 保留采购史实记录

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWzzZx8VvE8dNYDEfFjQSg
三 tab 成果页:验收矩阵(6 项+清账)、分任务详解带真实载荷、
302_can 端到端 case、69 条账本变更全量可筛审、运行/构成双画像。
所有数字来自真实运行(grounding 实跑、账本 diff、Isaac 证据 json、
片段统计、268 测试 10.68s)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWzzZx8VvE8dNYDEfFjQSg
呼应 main 的 redact-public-evidence-paths(PR #5)政策,并修掉
"绝对路径在别人机器上是死链接"的消费正确性问题:

- lib/ledger.py 新增 to_portable_uri/resolve_uri(锚 ASSET_PIPELINE_ROOT
  环境变量,缺省 ACTIVE_ROOT,与 runtime_config 语义一致);
  validate_ledger(check_files) 经 resolve_uri 解析相对 uri
- 写入方(import_materialize/backfill_upstream/writeback_verification)
  一律写 ACTIVE_ROOT 相对 posix 路径;读取方(usd_enrich/rescale_backfill)
  经 resolve_uri(usd_enrich 在边界处转绝对路径交给编译器)
- 存量一次性迁移 scripts/ledger/relativize_paths.py:87 份账本重写
  (80 份 /home 前缀剥除 + 7 份旧纪元 "../" CWD 相对 uri 归一),
  isaac/sweep 证据搬入 results/(gitignore 本地保留),0 失败;
  账本内 /home|/Users 字符串清零,卫生测试固化
  (test_ledger_path_hygiene.py,与源码卫生测试同族)
- s10.2 判据升级为内容判定(选中 model 实测含 red):08-03 写死的
  "必须选 301_cup" 在原生资产获得模型级实测颜色后成为陈旧金标
  ——039_mug m10 实测红 40.9% 主导,按类目精确匹配胜出是正确行为

验证(全部真实运行):272 测试 + 仓库级 104 测试全绿;全库审计
asset_library 64/65 clean(余 1 为 08-13 已标记的 /tmp webcache 旧账)
+ upstream 16/16;Isaac can 案经相对 uri 全链复跑,指标与前日逐位一致;
s12 外部专属 5/5;s10 全过。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWzzZx8VvE8dNYDEfFjQSg
10 处代码各自假定「资产是 asset_library 的直接子目录」。按来源分子夹之前
先把这个假设收口到 lib/ledger.py 的两个函数:

  asset_dir(library_dir, asset)  -- 先试平铺 <lib>/<asset>,再试分层
                                    <lib>/<provider>/<asset>;不存在返回 None,
                                    由调用方带自己的上下文报错
  iter_assets(library_dir)       -- 两种布局都遍历,按 asset id 排序输出,
                                    重复 id 直接抛错(迁移期重复 = 搬迁中断,
                                    择一胜出会把它藏起来)

双兼容是有意的:读取改造与目录搬迁是两个提交,中间任何时刻代码都能跑,
任何一半都可以单独回滚。asset id 一律 `<数字>_<类目>`,provider 层永远不是,
所以分类是纯名字判断、不额外 stat。

ledger_path() 改走 asset_dir(),但资产不存在时回退平铺路径——它同时被用来
计算「新资产的账本该写到哪」。

s9 那处是必改项:库分层后 lib.iterdir() 拿到的是 nvidia/ objaverse/ github/,
把它们软链进影子根等于给上游扫描器三个假资产、并藏掉全部 65 个真的。

测试:1_asset_reuse 272 passed、web 12 passed、openxsim 57 passed(目录此时
仍是平的,等于纯重构,不全绿即改错)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjLbdTcHnTutTEhG4Kv6Uz
为什么按来源、而不是类目/许可/usable:来源是资产唯一永不改变的属性。类目会
加别名、许可会从 unknown 转 declared、usable 会在一次实测把资产盘活时翻面——
任何一个进了路径,日后都要搬目录。来源在采购那一刻定死,而且它同时是上游
重同步的单位和许可族的单位,是唯一值得占一层路径深度的轴。

归类证据链(强到弱,无证据即拒绝归类、保持平铺,不猜):
  1. 账本 models[*].source.library —— 契约本身,65 个用它
  2. 采购清单的 group prefix —— 给还没有账本的资产。规则用全部 65 份账本反
     验过:`Assets/...`(或空) 是 NVIDIA Isaac 服务器布局,`Models/<名>/
     glTF-Binary` 是 Khronos glTF-Sample-Models 树。Objaverse 的 prefix 是
     物体标题,永远走不到这条——objaverse 资产全都有账本。
  只有 303_boombox 走了第 2 条(无账本;prefix `Models/BoomBox/glTF-Binary`
  与三个已确认 github 资产同形)→ github/。

同一提交里必须改 .gitignore:账本从 */ledger.json 深到 */*/ledger.json,
不补规则的话 65 份账本会在 mv 的瞬间静默掉出版本控制。

账本内 201 处相对 uri 同步重指(`data/asset_library/<id>/` →
`.../<provider>/<id>/`)。`_source/` 的 144 处一处未动——它没搬,且 `_source`
不匹配 `<数字>_` 的资产 id 形状。345 = 201 + 144,核对相符。

验证:ledger_audit 65 audited / 64 clean / 1 violation,唯一那条
(320_teddy_bear 指向已清空的 /tmp webcache)搬迁前就存在于 HEAD,与本次无关;
no_ledger 仍只有 303_boombox。测试 272 + 12 + 57 全绿(此时库已分层,等于
真正验证了阶段 0 的双布局读取)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjLbdTcHnTutTEhG4Kv6Uz
import_materialize 里 10 处 `lib / <asset>` 拼接收口到一个 adir_for():
已存在的资产保持原位(ledger.asset_dir 先查现址,重复引入不会在另一个来源下
分叉出第二个目录),新资产按 _provider_dir() 落位。_provider_dir 与写账本
source.library 的分支是同一处判断(group `web_*` → 看 source_provider,否则
NVIDIA),所以目录与账本声明的来源不可能对不上。

新增检索层未在 _WEB_PROVIDER_DIRS 登记即报错退出,不给「悄悄落进 github/」
留口子——那会让账本声明的来源与它的路径不一致。

.gitignore 再补一条 `!.../asset_library/README.md`:`asset_library/*` 会把库根
下的任何文件吃掉,新写的 README 差点静默不入库(和账本那次是同一个坑)。

新增 data/asset_library/README.md:布局与每个资产夹的内容、为什么按来源分
(四个候选轴里只有来源永不变)、只有 ledger.json 入 git 及其 .gitignore 例外链、
新资产落哪、读取一律走 asset_dir/iter_assets、约 250 个时在来源夹内按号段再分片、
以及三个已知例外(303_boombox 无账本、320_teddy_bear 的 /tmp 失效 uri、_source
不按来源分)。1_asset_reuse README/OVERVIEW 的具体资产路径示例同步更新,
并修掉「asset_library 不入 git」这句已过期的描述。

验证:run_smoke 全链 PASS(隔离库里自动生成 nvidia/301_cup)——materialize →
s9 影子根+扩展 catalog → grounding 选中 301_cup m0(red-measured)→ SAPIEN 回放
fail=0 / 120 帧 → 全量验证 fail=0 not_run=0。测试 272 passed。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjLbdTcHnTutTEhG4Kv6Uz
分层迁移的三件事写进 README 本身:同盘 mv、改账本相对 uri(只动 `<数字>_` 资产段,
_source/ 不动)、同步 .gitignore 放行深度。第三条是这次真踩到的坑——账本每深一级
就要补一组 `!*/`、`*/*`、`!*/ledger.json`,漏了会在 mv 的瞬间静默掉出版本控制
(同一个坑这次犯了两次:账本一次、库根 README 一次)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjLbdTcHnTutTEhG4Kv6Uz
① s12 external-only 验收门自换机起一直是坏的。它读的
data/scene_gen_ext/asset_catalog_external_only.json 是 2026-08-03 手工产出的,
之后没有任何脚本会重新生成它——s9 只写 asset_catalog.json 和
asset_overrides_ext.yml。于是它一路带着上一台机器的绝对路径
(/home/jingxiang/yuxin/env-gen-dev/...) 活到今天,5 个用例全挂在
real_asset_files 检查上,而底下的物理其实是好的(runtime status=pass、
漂移 1.2mm/0.56°、120 帧)。

修法不是重新手工生成一份,而是让 s9 每次无条件从刚建好的 catalog 派生这个视图:
一个跟着源一起重生成的视图不可能再漂移。派生放在最后,所以 --admission enforce
过滤掉的东西同样反映进去;派生结果为空直接 FAIL(那意味着 s12 无物可 ground)。
重跑后 66 条,s12 恢复 5/5 PASS(302_can/303_box/304_bottle/302_bowl/306_block
全部 runtime fail=0 + val fail=0 not_run=0)。

② 320_teddy_bear 的 portable 表示指向 /tmp/teddy_acq2/webcache/... —— 采购期的
run-scoped 缓存,/tmp 一清就悬空。路径卫生(2026-08-16)刻意放过 /tmp 字符串
(不含用户名、是诚实的临时指针),诚实但是死的。

同一份文件其实早已按池的来源契约镜像在 _source/web_320_teddy_bear/ 下:
sha256 494fb1f6... 与账本记录逐位相同、大小同为 419,920 字节。据此改指向镜像,
不是猜。工具 work/oneoff/rehome_uris.py 做成通用形态(扫全库悬空 uri → 在
_source/ 找同名文件 → 仅当 sha256 与账本已记录的值相等才改写),同名但哈希不同
一律只报告不改。全库只此一条可修、零条不可修。

ledger_audit: 65 audited / 65 clean / 0 violations(此前 64 clean / 1 violation)。
测试 272 + 12 全绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjLbdTcHnTutTEhG4Kv6Uz
configs/ 只留代码真读的活配置(providers/category_sizes) + templates/(引进请求
模板,改名 acquire_request.*);smoke_manifest→tests/fixtures/;external_manifest
→archive/(历史留档,现行账本零引用已核实);acquired_manifest→data/(机器台账,
须与 asset_library 同区同进退)。4 处路径引用同步,README 群刷新。
验证: pytest 284/284 + run_smoke B+C 全链路 PASS(fail=0 not_run=0)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R79SC1mEtQvTH52T3v2jSP
data/robotwin_assets/ 是 2026-08-09「与上游 checkout 解耦」决策留下的 4.4G
vendored 副本,换机迁移把 ROBOTWIN_ROOT 指回 external/RoboTwin 之后它就没人用了。
owner 决定所有资产统一进库,于是它成为第四个来源夹。

搬之前逐字节校验:rsync -rcn 比对 data/robotwin_assets/objects 与
external/RoboTwin/assets/objects(排除只在前者存在的 900_* 代理)**0 处差异**;
残留的 7 个 RoboTwin 自带文件(same.json/trans.py/README.md…)同样逐个 sha256
核对一致后才删源目录。同盘 rename,不复制 4.4G。

落位:objects/<id>/ → robotwin/<id>/;usd/<id>/<file> → robotwin/<id>/usd/<file>;
LICENSE.upstream 随资产走。账本仍在 data/upstream_ledgers/(所有权不同:那批是
从上游 catalog 派生的),资产目录内不放 ledger.json。33 处账本 uri 同步重指,
每条改写后都验证过能解析,会悬空则整份不动。

三处代码随之改:
- iter_assets 在来源夹下不再做名字判断。RoboTwin 有 5 个非 `<数字>_` 命名的原生
  资产(cube / vis_box / sapien-block1,2 / objaverse),名字判断只在根一层需要
  (平铺旧布局下 provider 夹与资产夹是兄弟)。
- s9 装配改为「库优先、上游补缺」:同名资产两边都可能有,反过来会在第二遍
  symlink_to 抛 FileExistsError。900_* 代理在两侧都排除出影子视图(那条排除是
  「先复用再生成」的执行点,它们自己有账本但不参与场景生成)。
- external-only 视图判据从「路径在库下」改为「来源夹不是 robotwin」。搬迁后旧
  判据会匹配全部 191 条,把 s12 的前提(掩蔽上游、必须 ground 到我方资产)变成
  不可证伪——实测确实先产出了 191 条的错误视图,改判据后回到 66 条。

验证:catalog 191→191、集合一致、把上游资产路径归一化后**零差异**、usable
504/504;ledger_audit asset_library 65/65 clean + upstream_ledgers 16/16 clean;
测试 272 + 12 + 57 全绿;s10 PASS;**s12 5/5 PASS**。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DjLbdTcHnTutTEhG4Kv6Uz
…校验留痕

materials 不再被硬编码空列表吞掉;VLM 验货观察的颜色/材质回填 semantics
(声明优先/观察只填空,来源标记 manifest|vlm|mixed,仅新账本写入);
re-import 时声明为账本子集则沿用账本值,新值冲突仍走防漂移报错;
validate_entries 未知字段警告→stderr+evidence.input_warnings。
tests: 277/277。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R79SC1mEtQvTH52T3v2jSP
wczmiracle and others added 6 commits August 19, 2026 15:06
match_local 本地同类匹配(逐值核对,mismatch/unverified 区分);tier0 复用属性化
(带约束请求先全梯队找 exact,blue-ball 假成功根修);VLM attribute_veto 候选
入 similar 池,exact 落空按信任序兜底引进(allow_similar 条目级开关);evidence
每条附 match{grade,asset,unmet},stdout MATCH 行,SUMMARY 带三档计数,
exact/similar 视为成功退出码;blocker 附 nearest_local;web 第②步徽章展示。
tests: 294/294。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R79SC1mEtQvTH52T3v2jSP
根因两处:backfill_upstream 的 identity.evidence 直写 CLI 绝对路径;
_relative_to_root rebase 失败回落绝对路径(ext 模型住 asset_library 不在
robotwin root 下)。均改走 to_portable_uri。数据侧 90 文件/497 字段改写为
active-relative(write_ledger 原子+锁)。test_ledger_path_hygiene 转绿,294/294。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R79SC1mEtQvTH52T3v2jSP
同类资产存在但账本 profile 冲突时不再追加模型(会撞防漂移门),改为找
兼容位/开新编号;三调用点按来源声明 profile(web=sapien_only, Kit/USD=
cross_backend)。实证:blue ball 以 exact 引进 366_ball(colors=[blue,purple]
attribute_basis=vlm, identity vlm verified),catalog 192 条。tests 295/295。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R79SC1mEtQvTH52T3v2jSP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants