Repository navigation
P0:5 个已发布模板对真实新用户是坏的 —— 脚手架的对象名前缀改写对所有远程模板静默跳过,夜间金丝雀连红 20 次无人察觉 #4926
Description
影响
npx create-objectstack@latest my-app -t <模板> 对 6 个模板里的 5 个产出的工程连 objectstack build 都过不去(exit 2)。只有本仓库自带的 blank 是好的。
Registry canary: todo ✗ Object 'todo_task' is missing the package namespace prefix.
Rename it to 'canary_app_todo_task' (namespace = 'canary_app')
Registry canary: compliance ✗ 4 issues
Registry canary: content ✗ 9 issues
Registry canary: contracts ✗ 3 issues
Registry canary: procurement ✗ 4 issues
Scaffold E2E 的 registry-canary 最近 20 次定时运行全部失败,连续至少从 2026-07-27 到今天(最近一次 run 30784751821)。
为什么无人察觉
registry-canary 的条件是 if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' —— PR 永远不跑它,只在夜里跑,而夜里的红灯没有任何人或机制去看。这个 workflow 的全部存在意义就是当新用户金丝雀,它红了一周多,首次使用体验一直是坏的。
根因:同名文件、两套 schema
packages/create-objectstack/src/index.ts 的 rewriteProjectIdentity 只从 objectstack.manifest.json 读模板原始 namespace:
if (typeof m.namespace === 'string') templateNamespace = m.namespace;
…
if (namespace !== templateNamespace && templateNamespace) { …改写 src/**/*.ts 里的对象名… }而 objectstack.manifest.json 这个文件名对应两种完全不同的文档:
自带 blank |
远程模板(objectstack-ai/templates) | |
|---|---|---|
| schema | app 形态 | $schema: …/template-manifest.json(注册表文档) |
namespace 字段 |
有("blank") |
没有 —— 只有 name/displayName/category/skills/translations |
| 真实 namespace 在哪 | manifest + config | 只在 objectstack.config.ts |
于是对每个远程模板 templateNamespace 都是 undefined,守卫 && templateNamespace 为假,对象名改写整段被跳过;而 objectstack.config.ts 的 namespace: 是无条件改写的。结果就是 namespace: 'my_app' 与 name: 'todo_task' 并存,直接违反 packages/spec/src/kernel/namespace-prefix.ts 的 ${namespace}_${shortName} 规则。
实测(把 objectstack-ai/templates@960f24d 的真实模板喂给新旧两套逻辑):
| 模板 | 旧逻辑读到的 namespace | 新逻辑 | 应改写的对象名 | 旧逻辑实际改写 |
|---|---|---|---|---|
| todo | undefined |
todo |
7 | 0 |
| compliance | undefined |
compliance |
17 | 0 |
| content | undefined |
content |
22 | 0 |
| contracts | undefined |
contracts |
12 | 0 |
| procurement | undefined |
procurement |
16 | 0 |
生产上共 74 处对象名从未被改写。
代码注释本身就留了线索 —— 「Used to swap the bundled template's literal blank_ object-name prefix」:这段逻辑从设计起就只考虑了自带模板,远程路径从未被覆盖。
修复方向(PR 随后)
objectstack.config.ts作为 namespace 的权威来源,manifest 降为回退。config 里的namespace:正是脚手架自己要改写的那个字面量,两者不可能不一致。- 改写完成后自我校验。「静默什么都没做」和「本来就不需要做」在外部完全同形 —— 这个歧义正是本缺陷得以出厂的原因。残留任何旧前缀就直接报错退出,把失败拉回到脚手架现场,而不是留给用户的第一条
objectstack build。
顺带发现:4 个模板完全没有自动化覆盖
objectstack-ai/templates 里有 10 个包。脚手架 TEMPLATES 注册表只提供 5 个远程模板,金丝雀矩阵也只有这 5 个 + blank。而 expense / helpdesk / hr / project 各自都有完整的 objectstack.config.ts 和 namespace(expense/helpdesk/hr/pm),却既不对用户开放、也无任何 CI 覆盖。(all 没有 config,不是模板。)是有意暂不发布还是漏了,需要维护者确认 —— 另行记录。
Activity
chore: changeset for #4926
xuyushun441-sys commentedon Aug 3, 2026
这些模版已经下架了,目前有效的在维护的只有 hotcrm 仓库
fix(create-objectstack): 远程模板的对象名改写被静默跳过 —— 5/6 已发布模板对新用户不可用 (objects…
docs(create-objectstack): re-anchor the dead tracker citations in pac…