Skip to content

fix(create-objectstack): 远程模板的对象名改写被静默跳过 —— 5/6 已发布模板对新用户不可用 (#4926) - #4927

Merged
os-zhuang merged 2 commits into
mainfrom
claude/ci-errors-i1t8fi
Aug 4, 2026
Merged

fix(create-objectstack): 远程模板的对象名改写被静默跳过 —— 5/6 已发布模板对新用户不可用 (#4926)#4927
os-zhuang merged 2 commits into
mainfrom
claude/ci-errors-i1t8fi

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #4926

npx create-objectstack@latest my-app -t todo(以及 compliance / content / contracts / procurement)产出的工程objectstack build 都过不去。6 个模板里 5 个如此,只有本仓库自带的 blank 是好的。夜间金丝雀 —— 那个存在意义就是当新用户探针的 workflow —— 连续 20 次定时运行全红(≥2026-07-27),因为它 if: github.event_name == 'schedule',PR 永远不跑,夜里没人看。

根因:同名文件、两套 schema

rewriteProjectIdentity 只从 objectstack.manifest.json 读模板原始 namespace。而这个文件名对应两种完全不同的文档:

自带 blank 远程模板
schema app 形态 $schema: …/template-manifest.json(注册表文档)
namespace 没有
真实 namespace manifest + config 只在 objectstack.config.ts

于是远程模板一律读到 undefined,&& templateNamespace 守卫落空,对象名改写整段跳过;而 config 的 namespace:无条件改写的。结果 namespace: 'my_app'name: 'todo_task' 并存,违反 ${namespace}_${shortName}

代码注释本身留了线索 ——「Used to swap the bundled template's literal blank_ prefix」:这段逻辑从设计起就只考虑自带模板。

改动

抽出 src/rewrite-identity.ts(index.ts 在 import 时 program.parse(),里面的东西测不了 —— pkg-utils.ts 当初就是为此而拆):

  1. objectstack.config.ts 成为 namespace 的权威来源,manifest 降为回退。config 里的 namespace: 正是脚手架自己要改写的那个字面量,两者不可能不一致。
  2. 改写完成后自我校验。「静默什么都没做」和「本来就不需要做」在外部同形 —— 这个歧义正是本缺陷得以出厂的原因。残留任何旧前缀就抛错,指名文件与行号,把失败拉回脚手架现场,而不是留给用户的第一条 objectstack build

验证

objectstack-ai/templates@960f24d真实模板对新旧逻辑各跑一遍:

模板 旧逻辑 namespace 新逻辑 应改写 旧逻辑实改 新逻辑残留
todo undefined todo 7 0 0
compliance undefined compliance 17 0 0
content undefined content 22 0 0
contracts undefined contracts 12 0 0
procurement undefined procurement 16 0 0

生产上共 74 处对象名从未被改写。

其余闸门:

  • 10 个新单测,覆盖两种 manifest 形态、回退路径、两者皆无、以及 manifest 不可解析;
  • 自带 blank 无回归:实跑脚手架产出 namespace: 'regr_app' + name: 'regr_app_note';
  • 包内测试 28/28,tsc --noEmiteslint 均为 0 退出码。

未在本 PR 处理

金丝雀「只在夜里跑且无人看」这个结构性问题本身没修 —— 本 PR 只让它接下来会变绿。要不要给它加通知/让 PR 也跑,由维护者定。

🤖 Generated with Claude Code

https://claude.ai/code/session_01BbNVKv6KgPzuQ5p76nMgnf


Generated by Claude Code

claude added 2 commits August 3, 2026 16:31
…te for every remote template (#4926)

`npx create-objectstack@latest my-app -t <template>` produced a project that
could not build for 5 of the 6 offered templates. Only the bundled `blank`
worked. The nightly registry canary — the workflow whose entire purpose is to
be the new-user canary — had been red on all five for at least a week (20/20
scheduled runs since 2026-07-27), unseen because it runs only on `schedule`.

`rewriteProjectIdentity` read the template's original namespace from
`objectstack.manifest.json` alone, and that filename means two different
documents. The bundled template's is app-shaped and carries `namespace`; a
remote template's is the template-REGISTRY document
(`$schema: .../template-manifest.json`) and carries none — its namespace lives
only in `objectstack.config.ts`. So `templateNamespace` came back undefined for
every remote template, the `&& templateNamespace` guard fell through, and the
object-name rewrite was skipped entirely — while the config's `namespace:` was
rewritten unconditionally. That leaves `namespace: 'my_app'` beside
`name: 'todo_task'`, which the ${namespace}_${shortName} rule rejects.

Measured against the real templates at objectstack-ai/templates@960f24d, the old
code resolved `undefined` for all five and rewrote 0 of the 74 object names that
needed it: todo 7, compliance 17, content 22, contracts 12, procurement 16.

Two changes, in a new module because index.ts calls program.parse() on import
and nothing there is testable (the reason pkg-utils.ts already exists):

- `objectstack.config.ts` is now the AUTHORITY for the template namespace, with
  the manifest as fallback. The config holds the very literal the scaffolder
  overwrites, so the two cannot disagree.
- The rewrite VERIFIES ITSELF. A prefix rewrite that quietly does nothing is
  indistinguishable from one that was not needed, and that ambiguity is what let
  this ship. Any surviving stale prefix now throws, naming the files and lines,
  at the scaffold — not in the user's first `objectstack build`.

Verified: 10 new unit tests covering both manifest shapes, the fallback, the
absent case and an unparseable manifest; all five real templates now resolve
their namespace and rewrite every literal with zero stale left; the bundled
blank template still scaffolds to `namespace: 'regr_app'` / `name:
'regr_app_note'`; package suite 28/28, tsc --noEmit and eslint clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbNVKv6KgPzuQ5p76nMgnf
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbNVKv6KgPzuQ5p76nMgnf
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 3, 2026 4:32pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): create-objectstack.

8 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx (via create-objectstack)
  • content/docs/ai/skills.mdx (via create-objectstack)
  • content/docs/deployment/self-hosting.mdx (via create-objectstack)
  • content/docs/getting-started/index.mdx (via create-objectstack)
  • content/docs/getting-started/your-first-project.mdx (via create-objectstack)
  • content/docs/plugins/packages.mdx (via create-objectstack)
  • content/docs/releases/v15.mdx (via create-objectstack)
  • content/docs/releases/v9.mdx (via create-objectstack)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added the size/m label Aug 3, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 4, 2026 00:05
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit 8d41998 Aug 4, 2026
25 checks passed
@os-zhuang
os-zhuang deleted the claude/ci-errors-i1t8fi branch August 4, 2026 00:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants