Skip to content

docs(skills): console-development.md 按 pages/system 现状重写,并同步 eval 的幽灵组件期望 (#3713) - #3729

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-3713-skills-guide-truth
Aug 8, 2026
Merged

docs(skills): console-development.md 按 pages/system 现状重写,并同步 eval 的幽灵组件期望 (#3713)#3729
yinlianghui merged 1 commit into
mainfrom
claude/issue-3713-skills-guide-truth

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #3713

按 PM 裁决方向 1(按现状重写 + 同步 eval),吸收方向 3 的既定事实执行。两文件,无源码改动。

注:正文刻意不写「尖括号 + 字母」的泛型/JSX 形式 —— GitHub 正文消毒器会在存储时把它当 HTML 标签剥掉(#3673 首版栽过)。泛型一律写成 ComponentType< X > 或改用花括号占位。

一、前提复核:issue 结论全部成立(origin/main @ 0cf8f0f70)

7 页面表逐条 find apps/console/src -name '{名}.tsx':

guide 原文声称的文件 实测 本 PR 处置
SystemHubPage.tsx ✅ 存在 保留,补 @deprecated 判词
MetadataManagerPage.tsx ❌ 不存在 移入「Retired names」纠错锚
MetadataDetailPage.tsx ❌ 不存在 移入纠错锚
AppManagementPage.tsx ✅ 存在 保留
UserManagementPage.tsx ❌ 不存在 移入纠错锚
RoleManagementPage.tsx ❌ 不存在 移入纠错锚
PermissionManagementPage.tsx ❌ 不存在 移入纠错锚

pages/system/ 现存 6 个,原 guide 一个都没提其中四个 —— 现已全部补入:ProfilePage / AuditLogPage / ApprovalsInboxPage / AiPendingActionsPage

零命中复核(packages + apps,排除 node_modules):MetadataManagerPage 0、MetadataDetailPage 0、metadataTypeRegistry 0、MetadataTypeConfig 0、registerMetadataType 0、getMetadataTypeConfig 0、pageSchemaFactory 0、listComponent 0、MetadataListComponentProps 0。即 :88listComponent 扩展点与整个 MetadataTypeConfig 接口都是幽灵。

一处与 PR #3699 正文不符的史实,以本次实测为准:#3699cccdf84d7 不是 main 的祖先(当时 main 仅 203 个 commit)。今天 origin/main7517 个 commit,git merge-base --is-ancestor cccdf84d origin/main 返回 ANCESTOR,git log -1 能读到完整提交信息。故本 PR 放心引用它 —— apps/console/src/AppContent.tsx:110 也已经在引。

二、「How MetadataManagerPage works」按真实机制改写(先实测,未照抄派发单)

派发单指出真身在 packages/app-shell 的 metadata-admin,要求先实测。实测结果比「registry 驱动」这句话更强,而且方向是反的:

  • 真实注册表:packages/app-shell/src/views/metadata-admin/registry.ts,类型 MetadataResourceConfig,写入 registerMetadataResource()(幂等 + 合并语义),读出 getMetadataResource() / resolveResourceConfig()
  • 关键反转:旧 guide 教的是「注册表驱动的页面」;真实引擎是一套 ListPage / EditPage / HistoryPage 通吃全部 27 个类型,默认表单由框架 /api/v1/meta/types 返回的 JSONSchema 生成。一个类型完全不注册也能列/建/改 —— 注册项只是覆盖默认值。旧文那种「不注册就没有页面」的心智模型,会让 agent 去写一堆本来不必写的东西。
  • 五步流程按 ResourceListPage.tsx / ResourceEditPage.tsx 逐行改写(含 ListPage 覆盖必须在其它 hook 之前短路这一实现约束、createSchema -> 服务端 schema -> defaultSchema 的取值顺序、409 destructive_change 重试 ?force=true)。
  • 「Adding a new metadata type」的假 API 例子换成 builtinComponents.tsxtype:'permission'真实注册项(EditPage: PermissionMatrixEditPage)。

路由示例整节重写:两文件分工(App.tsx 外骨架 / app-shell DefaultAppContent 应用内 / apps/console/src/AppContent.tsxsystemRoutes fragment)、引擎自己的 metadata/:type… 六条正规路由、以及 SystemObjectRedirect四条腿。

三、#3655 permissions 腿:未落地,按「已裁 A 待落地」措辞写(避免抢跑)

动手前 git log origin/main 实测:9961df297(#3673,四条重定向)已在 main;permissions 腿不在 —— apps/console/src/AppContent.tsx 现仍只有 users / organizations / roles / positions 四行,:191-202 的注释仍在解释为什么 permissions 故意缺席。故 guide 写作:

Four redirects, not five. system/permissions is deliberately absent as of origin/main … The maintainer has since ruled A — sys_permission_set on objectui#3655; that redirect is queued but not yet on main, so today the URL still falls through to app-shell's tail route. Check apps/console/src/AppContent.tsx before quoting this list.

即:陈述现状 + 记录已裁方向 + 给出自查指令,sys_permission_set 落地后这段只需删掉「not yet」那半句,不会与在途 PR 打架。

四、参考装配定位(引 cccdf84)

开头新增引用块:cccdf84d7 把 shell / layout / home / 导航 / 整个 metadata admin 搬进 @object-ui/app-shell,designer 页搬进 @object-ui/plugin-designer,apps/console 只剩薄宿主。两条可执行推论:先在 packages/app-shell;第三方 fork 的是模板不是本 app

模板路径以实测为准:cccdf84d7 建的是 apps/console-starter,今天在 examples/console-starter(apps/ 下只有 consolesite),故 guide 引后者。

五、eval 同步(本单的牙)

先测量消费方式:全仓 scripts/ / .github/ / package.json / turbo.jsonevals 的引用 零命中 —— 本仓没有 eval runner,skills/objectui/README.md 只说这个形状「so the prompts can be run as machine-checkable regression tests」。故校验方式是:逐字段人工核对 + 一个一次性核对脚本(写在 scratchpad,未进提交),规则见下。

eval diff:

位置 改前 改后 理由
eval 1 expected_output 「…automatically appears in SystemHubPage and MetadataManagerPage 讲引擎已自带 list/create/edit/history,UI 侧只是可选的 registerMetadataResource() 覆盖 issue 正文点名的 :7,幽灵组件名被烤进期望答案
eval 1 must_contain MetadataTypeRegistry, columns, formFields, SystemHubPage registerMetadataResource, listColumns, createFields, metadata-admin, navigation MetadataTypeRegistry 零命中;columns/formFields 是幽灵接口的字段名;SystemHubPage@deprecated 面,不该作为正确答案的必要条件
eval 1 must_not_contain new standalone page, /system/objects 追加 registerMetadataType, pageSchemaFactory 照旧指南生成的答案机械判错,而不只是「不加分」
eval 1 prompt 「should show in the system hub」 「reachable from the admin navigation」 不把已废弃的卡片墙写进题面
eval 2 must_contain pageSchemaFactory, registerWidgets, MetadataDetailPage, tabs ComponentRegistry, SchemaRenderer, EditPage, registerMetadataResource 前三个全是零命中的幽灵。额外发现:registerWidgets改前的 guide 里也不存在(真实文件名是 registerObjectDetailWidgets.ts,不含该子串)—— 这条断言从来就无法从指南得到满足
eval 2 must_not_contain [] pageSchemaFactory 同上,补牙
eval 3 未动 未动 实测 NavigationContext / ConsoleLayout / HomeLayout / UnifiedSidebar 四个符号今天都真实存在,只是搬到了 packages/app-shell。eval 断言的是答案里的符号名,不是路径,故该 eval 未被这次漂移污染 —— 如实不动

为什么 MetadataManagerPage / MetadataDetailPage 没进 must_not_contain:一个正确答案完全可能顺口说一句「旧的 MetadataDetailPage 已删」,把它列成反模式会造成假红。改用正向断言把牙做足:照旧指南生成的答案会同时丢掉 registerMetadataResource / EditPage(must_contain 未满足)并命中 pageSchemaFactory(反模式),两条独立失败,已足够。这条取舍在此写明,免得下一个读者以为是漏了。

六、纠错锚 + grep 计数(改前先量,#3656 措辞纪律)

新增「### Retired names — do not import these」小节,每个被删名字保留原名 + 紧跟判词与活体替代物#3656 的教训是「措辞会改变 grep 结果,要先预测」—— 这里方向与 #3656 相反:那次目标是 grep 归零,这次刻意不归零,而是收敛到「只在纠错锚里出现一次」,好让 grep 这些名字的 agent 一定落到判词上。

改前 / 改后计数(guide 内出现次数):

名字 改前 改后 位置
MetadataManagerPage 4 1 纠错锚
MetadataDetailPage 5 1 纠错锚
UserManagementPage 1 1 纠错锚
RoleManagementPage 1 1 纠错锚
PermissionManagementPage 1 1 纠错锚
metadataTypeRegistry 2 1 纠错锚
MetadataTypeConfig 2 1 纠错锚
registerMetadataType 2 1 纠错锚
pageSchemaFactory 3 1 纠错锚
listComponent 2 1 纠错锚
MetadataListComponentProps 1 1 纠错锚

计数脚本的一处自身缺陷已修正并记录:MetadataTypeConfiggetMetadataTypeConfig子串,两者同在纠错锚同一行,裸计数会读成 2 —— 已在脚本里扣掉这层重叠,计的是「独立提及数」。

七、逆向验证(先预测,后运行)

预测:把 origin/main 的旧 guide + 旧 eval 放回去,核对脚本应转红,且红点必须落在(a) 旧 eval 的 must_contain 解析不到真实代码;(b) 纠错锚小节不存在;(c) 每个被删名字在锚外出现,次数应与上表「改前」列逐条相等;(d) 目录树名字集合 ≠ 真实文件集合。

实测(git show origin/main: 取回两文件,apps/packages 软链到本树):23 项 FAIL,逐条吻合:

FAIL  eval 2 must_contain "registerWidgets" appears in the guide
FAIL  eval 1 must_contain "MetadataTypeRegistry" resolves to real code (0 file(s))
FAIL  eval 2 must_contain "pageSchemaFactory" resolves to real code (0 file(s))
FAIL  eval 2 must_contain "MetadataDetailPage" resolves to real code (0 file(s))
FAIL  correction-anchor section exists
FAIL  retired "MetadataManagerPage": total=4 inAnchor=0 outsideAnchor=4 (want 1/1/0)
FAIL  retired "MetadataDetailPage": total=5 inAnchor=0 outsideAnchor=5 (want 1/1/0)
FAIL  retired "pageSchemaFactory": total=3 inAnchor=0 outsideAnchor=3 (want 1/1/0)
FAIL  pages/system/AiPendingActionsPage.tsx is listed in the guide tree
FAIL  tree names === real files

改后同一脚本:ALL CHECKS PASSED(87 项)。

八、门禁与 changeset 判断

  • node scripts/check-control-bytes.mjs -> OK (scanned 3684 tracked text file(s); skipped 85 binary)
  • 越过门禁盲区自扫两文件:grep -naP 控制字符类 -> 无命中(退出码 1)
  • JSON.parse(evals/console-development.json) -> OK;与其余 10 个 eval 文件的键集合逐一比对一致(skill_name,evals / id,prompt,expected_output,files,assertions / must_contain,must_not_contain),must_contain 条数在 README 规定的 3–6 之间
  • 英文单一性(SKILL.md 核心原则 0):两文件均无 CJK 字符,脚本已断言

无 changeset,判断依据实测:skills/没有任何 package.json;根 package.jsonprivate: truefiles 字段;39 包固定版本组里没有任何包把 skills 列进 filesskills-lock.json 只是把 objectui 指到本地路径供 skills CLI 消费,不参与 npm 发布。即 skills/ 不是发布面,本次改动对任何包产物零 delta。与 PR #3656(scripts/ 非发布包 -> 无 changeset)同一判据。

九、围栏

十、越界发现(只报不改)

立单时命中 GitHub API 速率限制,单号待补(内容如下,PM 可代立或本 session 稍后补立):

  1. 同一 guide 的「Key contexts」「Key hooks」「UnifiedSidebar」三处仍把 5 + 7 + 1 个真实存在的符号指到 apps/console/src/{context,hooks,components}/ —— apps/console/src/context/ 这个目录整个不存在,hooks/ 下只剩 useBranding.ts,UnifiedSidebar.tsxpackages/app-shell/src/layout/。符号活着、路径全死,与本单同源(cccdf84)但属不同章节,故未在本 PR 中改。另:「Registered custom widgets」表列 6 个,registerObjectDetailWidgets.ts 实注册 7 个(缺 object-keys)。
  2. apps/console/src/schemas/objectDetailPageSchema.tsbuildObjectDetailPageSchema() 全仓零调用者(唯一调用者正是被删的 MetadataDetailPage),其 7 个 widget 仍由 main.tsx 注册。休眠代码,观察类(finding)。

🤖 Generated with Claude Code

https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt


Generated by Claude Code

…lity and sync its eval (#3713)

Five of the seven `pages/system/` files the guide taught do not exist, and a
whole section documented `MetadataManagerPage` — deleted, zero hits repo-wide —
including a route example and a `listComponent` extension point on a registry
file (`config/metadataTypeRegistry.ts`) that never existed under
`apps/console/src/`.

- Directory tree rewritten to the six real `pages/system/` pages, plus a
  relocation table for everything that left `apps/console` in cccdf84.
- New "Retired names" correction anchor: each dead symbol appears exactly once
  in the guide, immediately followed by its verdict and live replacement.
- The registry chapter now documents the real engine —
  `packages/app-shell/src/views/metadata-admin/registry.ts`,
  `MetadataResourceConfig`, `registerMetadataResource()`, and the actual
  `MetadataResourceListPage` / `MetadataResourceEditPage` flows.
- Routing section replaced with the real two-file split, the engine's canonical
  `metadata/:type…` routes, and the four `SystemObjectRedirect` legs (#3655's
  permissions leg is ruled but not yet on main, and is labelled as such).
- Reference-assembly positioning added up front, citing cccdf84.
- evals/console-development.json: expected_output no longer bakes in
  `MetadataManagerPage`; the phantom `MetadataTypeRegistry`, `MetadataDetailPage`,
  `pageSchemaFactory` and `registerWidgets` assertions are replaced with tokens
  that resolve to real code, and the dead API names move to `must_not_contain`
  so a stale answer now fails instead of passing.

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

vercel Bot commented Aug 8, 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)
objectui Ignored Ignored Aug 8, 2026 9:18am

Request Review

Copy link
Copy Markdown
Collaborator Author

第十节「越界发现」单号补齐

创建 PR 时 GitHub search API 速率限制未过,两单在 PR 开出后随即立完(均未认领,均已按关键词搜过本仓开放 issue、无同源单):

  • docs(skills): console-development.md 的 Key contexts / Key hooks / UnifiedSidebar 三处把 13 个真实符号指到 apps/console 下已不存在的目录 #3730 —— 同一 guide 的「Key contexts」(5 行)/「Key hooks」(8 行里 7 行)/「UnifiedSidebar」三处,把 13 个真实存在的符号指到 apps/console/src/{context,hooks,components}/apps/console/src/context/ 这个目录整个不存在,hooks/ 下只剩 useBranding.ts。符号活着、路径全死。附带记录「Registered custom widgets」表列 6 个而实际注册 7 个(缺 object-keys)。与本单同源(cccdf84d7)但属不同章节,未打 finding(照它去定位会白跑一圈,不是纯台账漂移),未打 pm:queue,留给分诊。
  • console: buildObjectDetailPageSchema 全仓零调用者 —— 唯一消费者随 MetadataDetailPage 一同退场 #3731 —— buildObjectDetailPageSchema() 全仓零代码调用者(唯一消费者正是被删的 MetadataDetailPage),但它的 7 个 widget 仍由 main.tsx 注册、对任何引用这些 type 的 schema 依然可达 —— 所以「顺手删掉」不成立,两侧要分开判。文件自己的 docblock 已写明 post-删除意图(「Render via SchemaRenderer (e.g. inside a custom metadata-admin EditPage)」),故本单不预判 remove,只钉事实,列出 enforce / remove / 保持现状三条并注明各自未测点。已打 finding(观察类:今天无用户可感差异)。

两单都只记录,本 PR 一行未改它们涉及的内容 —— 本 PR 文件面仍是 skills/objectui/guides/console-development.md + skills/objectui/evals/console-development.json 两文件。

需要说明的边界:本 PR 已在 guide 顶部加了「先在 packages/app-shell 找」的引用块,并在 Common mistakes 里加了「不要因为旧版指南这么写就假定符号在 apps/console/src/ 下」。那是通用护栏,#3730 的三处表格里逐行的具体路径仍然是错的,仍会被当作可直接使用的坐标 —— 护栏不替代订正。


Generated by Claude Code


Generated by Claude Code

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.

docs(skills): console-development.md 指路的 7 个 console 页面里 5 个不存在,并整节教用已删除的 MetadataManagerPage

2 participants